-
+
@@ -82,7 +87,7 @@ const App = () => {
>
: '' }
- { currentUser.role === "Admin" || pages.infrastructure ? <>
+ { user.role === "Admin" || pages.infrastructure ? <>
@@ -92,12 +97,12 @@ const App = () => {
>
: '' }
{ pages.account ?
: '' }
- { currentUser.role === "Admin" ?
+ { user.role === "Admin" ?
: '' }
- { currentUser.role === "Admin" || pages.api ?
+ { user.role === "Admin" || pages.api ?
: '' }
diff --git a/src/common/menu.js b/src/common/menu.js
index 93488a1..b30eb1c 100644
--- a/src/common/menu.js
+++ b/src/common/menu.js
@@ -20,13 +20,15 @@ import { useEffect, useState } from 'react';
import { NavLink } from 'react-router-dom';
import branding from '../branding/branding';
import { useGetConfigQuery } from '../store/apiSlice';
-import { currentUser } from '../localStorage';
+import { useSelector } from 'react-redux';
const SideBarMenu = (props) => {
const values = branding.values;
const [isExternalAuth, setIsExternalAuth] = useState(false);
const [logoutLink, setLogoutLink] = useState('');
+
+ const { user: currentUser } = useSelector((state) => state.auth);
const {data: configRes} = useGetConfigQuery();
@@ -34,11 +36,7 @@ const SideBarMenu = (props) => {
if(configRes) {
setLogoutLink(configRes.authentication.logout_url);
}
- }, [configRes])
-
- const logout = async () => {
-
- }
+ }, [configRes]);
const getLinks = () => {
let links = [];
diff --git a/src/pages/account/account.js b/src/pages/account/account.js
index d3401a5..966de16 100644
--- a/src/pages/account/account.js
+++ b/src/pages/account/account.js
@@ -16,10 +16,10 @@
******************************************************************************/
import { useState } from "react";
+import { useSelector } from "react-redux";
import IconButton from "../../common/buttons/icon-button";
import { Form, Row, Col } from 'react-bootstrap';
import EditOwnUserDialog from "./edit-own-user";
-import { currentUser } from "../../localStorage";
import NotificationsFactory from "../../common/data-managers/notifications-factory";
import notificationsDataManager from "../../common/data-managers/notifications-data-manager";
import { useUpdateUserMutation } from "../../store/apiSlice";
@@ -28,6 +28,7 @@ const Account = () => {
const [isEditModalOpened, setIsEditModalOpened] = useState(false);
const [updateUser] = useUpdateUserMutation();
+ const { user: currentUser } = useSelector((state) => state.auth);
const buttonStyle = {
marginLeft: '10px',
diff --git a/src/pages/infrastructure/ic-category-table.js b/src/pages/infrastructure/ic-category-table.js
index 3e3a38a..59cd821 100644
--- a/src/pages/infrastructure/ic-category-table.js
+++ b/src/pages/infrastructure/ic-category-table.js
@@ -26,7 +26,6 @@ import moment from 'moment'
import IconToggleButton from "../../common/buttons/icon-toggle-button";
import { updateCheckedICs, openDeleteModal, openEditModal } from "../../store/icSlice";
import { stateLabelStyle } from "./styles";
-import { currentUser } from "../../localStorage";
//a Table of IC components of specific category from props.category
//titled with props.title
@@ -35,6 +34,8 @@ const ICCategoryTable = (props) => {
const ics = useSelector(state => state.infrastructure.ICsArray);
const [isGenericDisplayed, setIsGenericDisplayed] = useState(false);
+ const { user: currentUser } = useSelector((state) => state.auth);
+
const modifyUptimeColumn = (uptime, component) => {
if (uptime >= 0) {
let momentDurationFormatSetup = require("moment-duration-format");
diff --git a/src/pages/infrastructure/ic-pages/default-ic-page.js b/src/pages/infrastructure/ic-pages/default-ic-page.js
index 674f6fb..17b75f0 100644
--- a/src/pages/infrastructure/ic-pages/default-ic-page.js
+++ b/src/pages/infrastructure/ic-pages/default-ic-page.js
@@ -15,18 +15,12 @@
* along with VILLASweb. If not, see
.
******************************************************************************/
-import React, { useEffect, useState } from 'react';
+import React, { useEffect } from 'react';
+import { useSelector } from "react-redux";
import {Col, Row} from "react-bootstrap";
import IconButton from '../../../common/buttons/icon-button';
-import ManagedICsTable from "./managed-ics-table";
-
import { useDispatch } from 'react-redux';
import { loadICbyId } from '../../../store/icSlice';
-import { sessionToken, currentUser } from '../../../localStorage';
-import { loadConfig } from '../../../store/configSlice';
-import { useSelector } from 'react-redux';
-import {refresh, rawDataTable} from "../ic"
-
import ICParamsTable from '../ic-params-table';
import RawDataTable from '../../../common/rawDataTable';
@@ -35,6 +29,8 @@ import { iconStyle, buttonStyle } from "../styles";
const DefaultICPage = (props) => {
const ic = props.ic;
+ const { user: currentUser, token: sessionToken } = useSelector((state) => state.auth);
+
const dispatch = useDispatch();
const refresh = () => {
diff --git a/src/pages/infrastructure/ic-pages/default-manager-page.js b/src/pages/infrastructure/ic-pages/default-manager-page.js
index 79324ad..2210c53 100644
--- a/src/pages/infrastructure/ic-pages/default-manager-page.js
+++ b/src/pages/infrastructure/ic-pages/default-manager-page.js
@@ -16,16 +16,12 @@
******************************************************************************/
import React, { useEffect, useState } from 'react';
+import { useSelector } from "react-redux";
import {Col, Row} from "react-bootstrap";
import IconButton from '../../../common/buttons/icon-button';
import ManagedICsTable from "./managed-ics-table";
-
import { useDispatch } from 'react-redux';
import { loadICbyId } from '../../../store/icSlice';
-import { sessionToken, currentUser } from '../../../localStorage';
-import { loadConfig } from '../../../store/configSlice';
-import { useSelector } from 'react-redux';
-import {refresh, rawDataTable} from "../ic"
import ICParamsTable from '../ic-params-table';
import RawDataTable from '../../../common/rawDataTable';
@@ -37,6 +33,8 @@ const DefaultManagerPage = (props) => {
const ics = useSelector((state) => state.infrastructure.ICsArray);
+ const { user: currentUser, token: sessionToken } = useSelector((state) => state.auth);
+
const dispatch = useDispatch();
const managedICs = ics.filter(managedIC => managedIC.category !== "manager" && managedIC.manager === ic.uuid);
diff --git a/src/pages/infrastructure/ic-pages/gateway-villas-node.js b/src/pages/infrastructure/ic-pages/gateway-villas-node.js
index 8e78223..e3808bf 100644
--- a/src/pages/infrastructure/ic-pages/gateway-villas-node.js
+++ b/src/pages/infrastructure/ic-pages/gateway-villas-node.js
@@ -1,13 +1,10 @@
import { useState } from "react";
+import { useSelector } from "react-redux";
import { useDispatch } from "react-redux";
-
import ICParamsTable from "../ic-params-table";
import RawDataTable from '../../../common/rawDataTable';
-
import { restartIC, shutdownIC, loadICbyId } from "../../../store/icSlice";
-import { sessionToken, currentUser } from "../../../localStorage";
import { buttonStyle, iconStyle } from "../styles";
-
import IconButton from "../../../common/buttons/icon-button";
import {Button, Col, Container, Row} from "react-bootstrap";
import ConfirmCommand from "../../../common/confirm-command";
@@ -20,6 +17,8 @@ const GatewayVillasNode = (props) => {
const [command, setCommand] = useState("");
const [isCommandConfirmed, setIsCommandConfirmed] = useState(false);
+ const { user: currentUser, token: sessionToken } = useSelector((state) => state.auth);
+
const sendControlCommand = () => {
switch(command){
case "restart":
diff --git a/src/pages/infrastructure/ic-pages/kubernetes-ic-page.js b/src/pages/infrastructure/ic-pages/kubernetes-ic-page.js
index 18873b9..80d8942 100644
--- a/src/pages/infrastructure/ic-pages/kubernetes-ic-page.js
+++ b/src/pages/infrastructure/ic-pages/kubernetes-ic-page.js
@@ -15,16 +15,11 @@
* along with VILLASweb. If not, see
.
******************************************************************************/
-import { useState, useEffect } from "react";
-import { Col, Row, Container, Table } from "react-bootstrap";
+import { Col, Row } from "react-bootstrap";
import IconButton from "../../../common/buttons/icon-button";
-import ManagedICsTable from "./managed-ics-table";
-import FileSaver from 'file-saver';
import RawDataTable from "../../../common/rawDataTable";
-import { downloadGraph } from "../../../utils/icUtils";
-import { sessionToken, currentUser } from "../../../localStorage";
import { useDispatch, useSelector } from "react-redux";
-import { loadAllICs, loadICbyId } from "../../../store/icSlice";
+import { loadICbyId } from "../../../store/icSlice";
import ICParamsTable from "../ic-params-table";
@@ -34,6 +29,8 @@ const KubernetesICPage = (props) => {
const dispatch = useDispatch();
+
+ const { user: currentUser, token: sessionToken } = useSelector((state) => state.auth);
const ic = props.ic;
const ics = useSelector((state) => state.infrastructure.ICsArray);
diff --git a/src/pages/infrastructure/ic-pages/manager-villas-node.js b/src/pages/infrastructure/ic-pages/manager-villas-node.js
index 6221c17..0446e77 100644
--- a/src/pages/infrastructure/ic-pages/manager-villas-node.js
+++ b/src/pages/infrastructure/ic-pages/manager-villas-node.js
@@ -15,16 +15,13 @@
* along with VILLASweb. If not, see
.
******************************************************************************/
-import { useState, useEffect } from "react";
+import { useDispatch, useSelector } from "react-redux";
import { Col, Row } from "react-bootstrap";
import IconButton from "../../../common/buttons/icon-button";
import ManagedICsTable from "./managed-ics-table";
-import FileSaver from 'file-saver';
import RawDataTable from "../../../common/rawDataTable";
import { downloadGraph } from "../../../utils/icUtils";
-import { sessionToken, currentUser } from "../../../localStorage";
-import { useDispatch, useSelector } from "react-redux";
-import { loadAllICs, loadICbyId } from "../../../store/icSlice";
+import { loadICbyId } from "../../../store/icSlice";
import ICParamsTable from "../ic-params-table";
@@ -32,6 +29,8 @@ import { iconStyle, buttonStyle } from "../styles";
const ManagerVillasNode = (props) => {
+ const { user: currentUser, token: sessionToken } = useSelector((state) => state.auth);
+
const dispatch = useDispatch();
const ic = props.ic;
diff --git a/src/pages/infrastructure/ic-pages/manager-villas-relay.js b/src/pages/infrastructure/ic-pages/manager-villas-relay.js
index 92f1d6f..f4f4c0e 100644
--- a/src/pages/infrastructure/ic-pages/manager-villas-relay.js
+++ b/src/pages/infrastructure/ic-pages/manager-villas-relay.js
@@ -15,12 +15,10 @@
* along with VILLASweb. If not, see
.
******************************************************************************/
-import { useState, useEffect } from "react";
import { Col, Row, Container } from "react-bootstrap";
import IconButton from "../../../common/buttons/icon-button";
import ManagedICsTable from "./managed-ics-table";
import RawDataTable from "../../../common/rawDataTable";
-import { sessionToken, currentUser } from "../../../localStorage";
import { useDispatch, useSelector } from "react-redux";
import { loadAllICs, loadICbyId } from "../../../store/icSlice";
@@ -32,6 +30,8 @@ const ManagerVillasRelay = (props) => {
const dispatch = useDispatch();
+ const { user: currentUser, token: sessionToken } = useSelector((state) => state.auth);
+
const ic = props.ic;
const ics = useSelector((state) => state.infrastructure.ICsArray);
diff --git a/src/pages/infrastructure/ic.js b/src/pages/infrastructure/ic.js
index d7b3d2a..51480d2 100644
--- a/src/pages/infrastructure/ic.js
+++ b/src/pages/infrastructure/ic.js
@@ -15,8 +15,7 @@
* along with VILLASweb. If not, see
.
******************************************************************************/
-import { useEffect, useRef } from "react";
-import { sessionToken, currentUser } from "../../localStorage";
+import { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { useParams } from 'react-router-dom';
import { loadAllICs, loadICbyId } from "../../store/icSlice";
@@ -34,6 +33,8 @@ const InfrastructureComponent = (props) => {
const id = params.ic;
const dispatch = useDispatch();
+ const { token: sessionToken } = useSelector((state) => state.auth);
+
const ic = useSelector(state => state.infrastructure.currentIC);
const isICLoading = useSelector(state => state.infrastructure.isCurrentICLoading);
diff --git a/src/pages/infrastructure/infrastructure.js b/src/pages/infrastructure/infrastructure.js
index 92d9018..af2a1fe 100644
--- a/src/pages/infrastructure/infrastructure.js
+++ b/src/pages/infrastructure/infrastructure.js
@@ -16,12 +16,10 @@
******************************************************************************/
import { useEffect, useState } from "react"
-import { useDispatch } from "react-redux";
-import { useSelector } from "react-redux";
+import { useDispatch, useSelector } from "react-redux";
import { loadAllICs, loadICbyId, addIC, sendActionToIC, closeDeleteModal, closeEditModal, editIC, deleteIC } from "../../store/icSlice";
import IconButton from "../../common/buttons/icon-button";
import ICCategoryTable from "./ic-category-table";
-import { sessionToken, currentUser } from "../../localStorage";
import ICActionBoard from "./ic-action-board";
import { buttonStyle, iconStyle } from "./styles";
import NewICDialog from "./dialogs/new-ic-dialog";
@@ -35,6 +33,8 @@ import NotificationsFactory from "../../common/data-managers/notifications-facto
const Infrastructure = (props) => {
const dispatch = useDispatch();
+ const { user: currentUser, token: sessionToken } = useSelector((state) => state.auth);
+
const ics = useSelector(state => state.infrastructure.ICsArray);
const externalICs = ics.filter(ic => ic.managedexternally === true);
diff --git a/src/pages/login/login-form.js b/src/pages/login/login-form.js
index d4cca3b..b40674d 100644
--- a/src/pages/login/login-form.js
+++ b/src/pages/login/login-form.js
@@ -15,27 +15,48 @@
* along with VILLASweb. If not, see
.
******************************************************************************/
-import React, { useState, useEffect } from 'react';
+import React, { useState } from 'react';
import { Form, Button, Col } from 'react-bootstrap';
import { useDispatch } from 'react-redux';
-import { login } from '../../store/userSlice';
import _ from 'lodash';
-import { sessionToken } from '../../localStorage';
import RecoverPassword from './recover-password';
+import NotificationsFactory from '../../common/data-managers/notifications-factory';
+import notificationsDataManager from '../../common/data-managers/notifications-data-manager';
+import { useAuthenticateUserMutation } from '../../store/apiSlice';
+import { setUser } from '../../store/authSlice';
-const LoginForm = ({loginMessage, config}) => {
+const LoginForm = ({config}) => {
+ const dispatch = useDispatch();
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
- const [forgottenPassword, setForgottenPassword] = useState(false)
+ const [forgottenPassword, setForgottenPassword] = useState(false);
+ const [loginMessage, setLoginMessage] = useState('');
+ const [authenticationRequest] = useAuthenticateUserMutation();
//this variable is used to disable login button if either username or password is empty
const isInputValid = username !== '' && password !== '';
- const dispatch = useDispatch();
-
const loginEvent = (event) => {
event.preventDefault();
- dispatch(login({username, password}))
+ authenticateUser();
+ }
+
+ const authenticateUser = async () => {
+ try {
+ const res = await authenticationRequest({mechanism: "internal", username: username, password: password});
+ if(res.error) {
+ setLoginMessage(res.error.data.message);
+ } else {
+ dispatch(setUser({user: res.data.user, token: res.data.token}));
+ setLoginMessage('');
+ }
+ } catch (err) {
+ if(err.data){
+ notificationsDataManager.addNotification(NotificationsFactory.UPDATE_ERROR(err.data.message));
+ } else {
+ console.log('Error', err);
+ }
+ }
}
const villasLogin = (
diff --git a/src/pages/login/login.js b/src/pages/login/login.js
index 5190136..115f50b 100644
--- a/src/pages/login/login.js
+++ b/src/pages/login/login.js
@@ -36,10 +36,9 @@ const Login = (props) => {
const {data: config} = useGetConfigQuery();
- const currentUser = useSelector(state => state.user.currentUser);
- const loginMessage = useSelector(state => state.user.loginMessage);
+ const { isAuthenticated } = useSelector((state) => state.auth);
- return currentUser == null ?
+ return !isAuthenticated ?
(
@@ -52,7 +51,7 @@ const Login = (props) => {
Login
-
+
diff --git a/src/pages/login/logout.js b/src/pages/login/logout.js
index d6b2741..83e9c8d 100644
--- a/src/pages/login/logout.js
+++ b/src/pages/login/logout.js
@@ -18,7 +18,7 @@
import React, {useEffect} from 'react';
import { Redirect } from 'react-router-dom';
import { useDispatch } from 'react-redux'
-import { logout } from '../../store/userSlice';
+import { deleteUser } from '../../store/authSlice';
const Logout = () => {
@@ -26,7 +26,7 @@ const Logout = () => {
useEffect(() => {
let isMounted = true;
- if(isMounted) dispatch(logout());
+ if(isMounted) dispatch(deleteUser());
return () => {isMounted = false};
}, []);
diff --git a/src/pages/scenarios/scenario.js b/src/pages/scenarios/scenario.js
index 86283e1..ed63521 100644
--- a/src/pages/scenarios/scenario.js
+++ b/src/pages/scenarios/scenario.js
@@ -16,14 +16,13 @@
******************************************************************************/
import { useParams } from "react-router-dom/cjs/react-router-dom.min";
+import { useSelector } from "react-redux";
import { useGetScenarioByIdQuery } from "../../store/apiSlice";
import IconButton from "../../common/buttons/icon-button";
-import { currentUser, sessionToken } from "../../localStorage";
import IconToggleButton from "../../common/buttons/icon-toggle-button";
import ConfigsTable from "./tables/configs-table";
import DashboardsTable from "./tables/dashboards-table";
import ResultsTable from "./tables/results-table";
-import { tableHeadingStyle } from "./styles";
import UsersTable from "./tables/users-table";
import {
useUpdateScenarioMutation,
@@ -34,6 +33,8 @@ const Scenario = (props) => {
const params = useParams();
const id = params.scenario;
+ const { user: currentUser, token: sessionToken } = useSelector((state) => state.auth);
+
const { data: fetchedScenarios, isLoading: isScenarioLoading, refetch: refetchScenario } = useGetScenarioByIdQuery(id);
const scenario = fetchedScenarios?.scenario;
diff --git a/src/pages/scenarios/scenarios.js b/src/pages/scenarios/scenarios.js
index 51d138c..42e96fb 100644
--- a/src/pages/scenarios/scenarios.js
+++ b/src/pages/scenarios/scenarios.js
@@ -16,11 +16,9 @@
******************************************************************************/
import { useState } from "react";
-import { useDispatch } from "react-redux";
import IconButton from "../../common/buttons/icon-button";
import { Table, ButtonColumn, DataColumn, LinkColumn } from "../../common/table";
import { buttonStyle, iconStyle } from "./styles";
-import { currentUser } from "../../localStorage";
import NewScenarioDialog from "./dialogs/new-scenario";
import ImportScenarioDialog from "./dialogs/import-scenario";
import DeleteDialog from "../../common/dialogs/delete-dialog";
@@ -34,12 +32,14 @@ import {
useGetConfigsQuery,
useGetDashboardsQuery,
} from "../../store/apiSlice";
+import { useSelector } from "react-redux";
const Scenarios = (props) => {
const { data , error, refetch: refetchScenarios } = useGetScenariosQuery();
const scenarios = data?.scenarios;
- const dispatch = useDispatch();
+
+ const { user: currentUser, token: sessionToken } = useSelector((state) => state.auth);
const [modalScenario, setModalScenario] = useState({name: 'error'});
const [isNewModalOpened, setIsNewModalOpened] = useState(false);
diff --git a/src/pages/scenarios/tables/configs-table.js b/src/pages/scenarios/tables/configs-table.js
index 2b0806b..bb171b0 100644
--- a/src/pages/scenarios/tables/configs-table.js
+++ b/src/pages/scenarios/tables/configs-table.js
@@ -16,10 +16,10 @@
******************************************************************************/
import { useState, useEffect } from "react";
+import { useSelector } from "react-redux";
import IconButton from "../../../common/buttons/icon-button";
import { Table, ButtonColumn, CheckboxColumn, DataColumn } from "../../../common/table";
import { tableHeadingStyle, buttonStyle, iconStyle } from "../styles";
-import { currentUser, sessionToken } from "../../../localStorage";
import NewDialog from "../../../common/dialogs/new-dialog";
import ImportConfigDialog from "../dialogs/import-config";
import DeleteDialog from "../../../common/dialogs/delete-dialog";
@@ -56,6 +56,8 @@ const ConfigsTable = ({scenario, ics}) => {
const [checkedConfigsIDs, setCheckedConfigsIDs] = useState([]);
const [areAllConfigsChecked, setAreAllConfigsChecked] = useState(false);
+ const { user: currentUser, token: sessionToken } = useSelector((state) => state.auth);
+
useEffect(() => {
if(configs.length > 0) {
configs.forEach(config => {
diff --git a/src/pages/scenarios/tables/dashboards-table.js b/src/pages/scenarios/tables/dashboards-table.js
index f6ac81b..f50eac9 100644
--- a/src/pages/scenarios/tables/dashboards-table.js
+++ b/src/pages/scenarios/tables/dashboards-table.js
@@ -16,10 +16,10 @@
******************************************************************************/
import { useState } from "react";
+import { useSelector } from "react-redux";
import IconButton from "../../../common/buttons/icon-button";
import { Table, ButtonColumn, LinkColumn, DataColumn } from "../../../common/table";
import { buttonStyle, tableHeadingStyle, iconStyle } from "../styles";
-import { currentUser, sessionToken } from "../../../localStorage";
import { InputGroup, Form } from "react-bootstrap";
import { useGetDashboardsQuery } from "../../../store/apiSlice";
import {Button} from "react-bootstrap";
@@ -46,6 +46,8 @@ const DashboardsTable = ({scenario}) => {
const [updateDashboard] = useUpdateDashboardMutation();
const [addWidgetToDashboard] = useAddWidgetMutation();
+ const { user: currentUser, token: sessionToken } = useSelector((state) => state.auth);
+
const [triggerGetWidgets, { isLoading: isWidgetsLoading, data: widgets, error: widgetsError }] = useLazyGetWidgetsQuery();
const dashboards = fetchedDashboards ? fetchedDashboards.dashboards : [];
diff --git a/src/pages/scenarios/tables/results-table.js b/src/pages/scenarios/tables/results-table.js
index 02e43e3..f0ff497 100644
--- a/src/pages/scenarios/tables/results-table.js
+++ b/src/pages/scenarios/tables/results-table.js
@@ -19,8 +19,6 @@ import { useState, useEffect } from "react";
import IconButton from "../../../common/buttons/icon-button";
import { Table, ButtonColumn, DataColumn, LinkbuttonColumn } from "../../../common/table";
import { buttonStyle, tableHeadingStyle, iconStyle } from "../styles";
-import { currentUser, sessionToken } from "../../../localStorage";
-import { InputGroup, Form } from "react-bootstrap";
import DeleteDialog from "../../../common/dialogs/delete-dialog";
import ResultConfigDialog from "../dialogs/result-configs-dialog";
import ResultPythonDialog from "../dialogs/result-python-dialog";
@@ -34,12 +32,8 @@ import {
useAddResultMutation,
useDeleteResultMutation,
useGetFilesQuery,
- useAddFileMutation,
useLazyDownloadFileQuery,
- useUpdateFileMutation,
- useDeleteFileMutation,
} from "../../../store/apiSlice";
-import { set } from "lodash";
import JSZip from 'jszip';
const ResultsTable = (props) => {
diff --git a/src/pages/scenarios/tables/users-table.js b/src/pages/scenarios/tables/users-table.js
index dda72a0..ccfb06c 100644
--- a/src/pages/scenarios/tables/users-table.js
+++ b/src/pages/scenarios/tables/users-table.js
@@ -16,10 +16,10 @@
******************************************************************************/
import { useState } from "react";
+import { useSelector } from "react-redux";
import IconButton from "../../../common/buttons/icon-button";
import { Table, ButtonColumn, DataColumn } from "../../../common/table";
import { buttonStyle, tableHeadingStyle } from "../styles";
-import { currentUser } from "../../../localStorage";
import { InputGroup, Form } from "react-bootstrap";
import DeleteDialog from "../../../common/dialogs/delete-dialog";
import NotificationsFactory from "../../../common/data-managers/notifications-factory";
@@ -36,6 +36,8 @@ const UsersTable = (props) => {
const [usernameToAdd, setUsernameToAdd] = useState("");
const [usernameToDelete, setUsernameToDelete] = useState("");
+ const { user: currentUser, token: sessionToken } = useSelector((state) => state.auth);
+
const addUser = async () => {
if(usernameToAdd.trim() === ''){
notificationsDataManager.addNotification(NotificationsFactory.LOAD_ERROR('Please, enter correct username'));
diff --git a/src/pages/users/users.js b/src/pages/users/users.js
index 8d98374..b5890de 100644
--- a/src/pages/users/users.js
+++ b/src/pages/users/users.js
@@ -1,4 +1,5 @@
import { useState } from "react";
+import { useSelector } from "react-redux";
import { Dropdown, DropdownButton } from 'react-bootstrap';
import { Table, ButtonColumn, CheckboxColumn, DataColumn } from "../../common/table";
import Icon from "../../common/icon";
@@ -8,7 +9,6 @@ import EditUserDialog from "./dialogs/edit-user";
import UsersToScenarioDialog from "./dialogs/users-to-scenario";
import DeleteDialog from "../../common/dialogs/delete-dialog";
import { buttonStyle, iconStyle } from "./styles";
-import {currentUser} from '../../localStorage';
import NotificationsFactory from "../../common/data-managers/notifications-factory";
import notificationsDataManager from "../../common/data-managers/notifications-data-manager";
import {
@@ -22,6 +22,8 @@ import {
const Users = ({}) => {
+ const { user: currentUser, token: sessionToken } = useSelector((state) => state.auth);
+
const {data: fetchedUsers, refetch: refetchUsers} = useGetUsersQuery();
const users = fetchedUsers ? fetchedUsers.users : [];
const { data: fetchedScenarios } = useGetScenariosQuery();
diff --git a/src/store/apiSlice.js b/src/store/apiSlice.js
index 4361ab6..dac5b23 100644
--- a/src/store/apiSlice.js
+++ b/src/store/apiSlice.js
@@ -1,8 +1,18 @@
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
import { sessionToken } from '../localStorage';
+import { widgetEndpoints } from './endpoints/widget-endpoints';
+import { scenarioEndpoints } from './endpoints/scenario-endpoints';
+import { dashboardEndpoints } from './endpoints/dashboard-endpoints';
+import { icEndpoints } from './endpoints/ic-endpoints';
+import { configEndpoints } from './endpoints/config-endpoints';
+import { userEndpoints } from './endpoints/user-endpoints';
+import { fileEndpoints } from './endpoints/file-endpoints';
+import { signalEndpoints } from './endpoints/signal-endpoints';
+import { resultEndpoints } from './endpoints/result-endpoints';
+import { authEndpoints } from './endpoints/auth-endpoints';
export const apiSlice = createApi({
- reducerPath: 'scenarios',
+ reducerPath: 'api',
baseQuery: fetchBaseQuery({
baseUrl: '/api/v2',
prepareHeaders: (headers) => {
@@ -14,244 +24,16 @@ export const apiSlice = createApi({
},
}),
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',
- })
+ ...widgetEndpoints(builder),
+ ...icEndpoints(builder),
+ ...fileEndpoints(builder),
+ ...configEndpoints(builder),
+ ...scenarioEndpoints(builder),
+ ...dashboardEndpoints(builder),
+ ...userEndpoints(builder),
+ ...resultEndpoints(builder),
+ ...signalEndpoints(builder),
+ ...authEndpoints(builder),
}),
});
@@ -276,31 +58,26 @@ export const {
useGetSignalsQuery,
useAddSignalMutation,
useDeleteSignalMutation,
-
useGetResultsQuery,
useAddResultMutation,
useDeleteResultMutation,
-
useGetUsersQuery,
useGetUserByIdQuery,
useAddUserMutation,
useUpdateUserMutation,
useDeleteUserMutation,
-
useGetFilesQuery,
useAddFileMutation,
useLazyDownloadFileQuery,
useUpdateFileMutation,
useDeleteFileMutation,
-
useGetDashboardQuery,
useUpdateDashboardMutation,
-
useSendActionMutation,
-
useAddWidgetMutation,
useLazyGetWidgetsQuery,
useUpdateWidgetMutation,
useDeleteWidgetMutation,
useGetConfigQuery,
+ useAuthenticateUserMutation,
} = apiSlice;
diff --git a/src/store/authSlice.js b/src/store/authSlice.js
new file mode 100644
index 0000000..b0cf1f1
--- /dev/null
+++ b/src/store/authSlice.js
@@ -0,0 +1,72 @@
+/**
+ * This file is part of VILLASweb.
+ *
+ * VILLASweb is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * VILLASweb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with VILLASweb. If not, see
.
+ ******************************************************************************/
+
+import { createSlice } from '@reduxjs/toolkit';
+import { apiSlice } from './apiSlice';
+import { sessionToken, currentUser } from '../localStorage';
+
+const initialState = {
+ user: currentUser,
+ token: sessionToken,
+ isAuthenticated: sessionToken && currentUser,
+ error: null,
+};
+
+const authSlice = createSlice({
+ name: 'auth',
+ initialState,
+ reducers: {
+ setUser: (state, action) => {
+ console.log("setting up storage", action.payload.user, action.payload.token)
+ localStorage.setItem('currentUser', JSON.stringify(action.payload.user));
+ localStorage.setItem('token', action.payload.token);
+ state.user = action.payload.user;
+ state.token = action.payload.token;
+ state.isAuthenticated = true;
+ state.error = null;
+ },
+ deleteUser: (state) => {
+ state.user = null;
+ state.user = null;
+ state.token = null;
+ state.isAuthenticated = false;
+ state.error = null;
+ localStorage.clear();
+ }
+ },
+ extraReducers: (builder) => {
+ builder.addMatcher(
+ apiSlice.endpoints.authenticateUser.matchFulfilled,
+ (state, { payload }) => {
+ state.user = payload.user;
+ state.token = payload.token;
+ state.isAuthenticated = true;
+ state.error = null;
+ }
+ );
+ builder.addMatcher(
+ apiSlice.endpoints.authenticateUser.matchRejected,
+ (state, { error }) => {
+ state.error = error;
+ }
+ );
+ },
+});
+
+export const { setUser, deleteUser } = authSlice.actions;
+
+export default authSlice.reducer;
\ No newline at end of file
diff --git a/src/store/endpoints/auth-endpoints.js b/src/store/endpoints/auth-endpoints.js
new file mode 100644
index 0000000..6facff4
--- /dev/null
+++ b/src/store/endpoints/auth-endpoints.js
@@ -0,0 +1,26 @@
+/**
+ * This file is part of VILLASweb.
+ *
+ * VILLASweb is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * VILLASweb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with VILLASweb. If not, see
.
+ ******************************************************************************/
+
+export const authEndpoints = (builder) => ({
+ authenticateUser: builder.mutation({
+ query: ({ mechanism, ...loginRequest }) => ({
+ url: `authenticate/${mechanism}`,
+ method: 'POST',
+ body: loginRequest,
+ }),
+ }),
+});
diff --git a/src/store/endpoints/config-endpoints.js b/src/store/endpoints/config-endpoints.js
new file mode 100644
index 0000000..7141d1e
--- /dev/null
+++ b/src/store/endpoints/config-endpoints.js
@@ -0,0 +1,38 @@
+/**
+ * This file is part of VILLASweb.
+ *
+ * VILLASweb is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * VILLASweb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with VILLASweb. If not, see
.
+ ******************************************************************************/
+
+export const configEndpoints = (builder) => ({
+ getConfigs: builder.query({
+ query: (scenarioID) => `configs?scenarioID=${scenarioID}`,
+ }),
+ addComponentConfig: builder.mutation({
+ query: (config) => ({
+ url: 'configs',
+ method: 'POST',
+ body: config,
+ }),
+ }),
+ deleteComponentConfig: builder.mutation({
+ query: (configID) => ({
+ url: `configs/${configID}`,
+ method: 'DELETE',
+ }),
+ }),
+ getConfig: builder.query({
+ query: () => '/config',
+ }),
+});
diff --git a/src/store/endpoints/dashboard-endpoints.js b/src/store/endpoints/dashboard-endpoints.js
new file mode 100644
index 0000000..6b6b5fc
--- /dev/null
+++ b/src/store/endpoints/dashboard-endpoints.js
@@ -0,0 +1,45 @@
+/**
+ * This file is part of VILLASweb.
+ *
+ * VILLASweb is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * VILLASweb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with VILLASweb. If not, see
.
+ ******************************************************************************/
+
+export const dashboardEndpoints = (builder) => ({
+ getDashboards: builder.query({
+ query: (scenarioID) => `dashboards?scenarioID=${scenarioID}`,
+ }),
+ 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 },
+ }),
+ }),
+ getDashboard: builder.query({
+ query: (dashboardID) => `/dashboards/${dashboardID}`,
+ }),
+});
diff --git a/src/store/endpoints/file-endpoints.js b/src/store/endpoints/file-endpoints.js
new file mode 100644
index 0000000..7810b19
--- /dev/null
+++ b/src/store/endpoints/file-endpoints.js
@@ -0,0 +1,60 @@
+/**
+ * This file is part of VILLASweb.
+ *
+ * VILLASweb is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * VILLASweb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with VILLASweb. If not, see
.
+ ******************************************************************************/
+
+export const fileEndpoints = (builder) => ({
+ 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',
+ }),
+ }),
+});
diff --git a/src/store/endpoints/ic-endpoints.js b/src/store/endpoints/ic-endpoints.js
new file mode 100644
index 0000000..fdb2f0a
--- /dev/null
+++ b/src/store/endpoints/ic-endpoints.js
@@ -0,0 +1,29 @@
+/**
+ * This file is part of VILLASweb.
+ *
+ * VILLASweb is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * VILLASweb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with VILLASweb. If not, see
.
+ ******************************************************************************/
+
+export const icEndpoints = (builder) => ({
+ getICS: builder.query({
+ query: () => 'ic',
+ }),
+ sendAction: builder.mutation({
+ query: (params) => ({
+ url: `/ic/${params.icid}/action`,
+ method: 'POST',
+ body: [params],
+ }),
+ }),
+});
diff --git a/src/store/endpoints/result-endpoints.js b/src/store/endpoints/result-endpoints.js
new file mode 100644
index 0000000..b269cd9
--- /dev/null
+++ b/src/store/endpoints/result-endpoints.js
@@ -0,0 +1,38 @@
+/**
+ * This file is part of VILLASweb.
+ *
+ * VILLASweb is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * VILLASweb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with VILLASweb. If not, see
.
+ ******************************************************************************/
+
+export const resultEndpoints = (builder) => ({
+ 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',
+ }),
+ }),
+});
diff --git a/src/store/endpoints/scenario-endpoints.js b/src/store/endpoints/scenario-endpoints.js
new file mode 100644
index 0000000..b3e036d
--- /dev/null
+++ b/src/store/endpoints/scenario-endpoints.js
@@ -0,0 +1,60 @@
+/**
+ * This file is part of VILLASweb.
+ *
+ * VILLASweb is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * VILLASweb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with VILLASweb. If not, see
.
+ ******************************************************************************/
+
+export const scenarioEndpoints = (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,
+ }),
+ }),
+ getUsersOfScenario: builder.query({
+ query: (scenarioID) => `scenarios/${scenarioID}/users/`,
+ }),
+ addUserToScenario: builder.mutation({
+ query: ({ scenarioID, username }) => ({
+ url: `scenarios/${scenarioID}/user?username=${username}`,
+ method: 'PUT',
+ }),
+ }),
+ removeUserFromScenario: builder.mutation({
+ query: ({ scenarioID, username }) => ({
+ url: `scenarios/${scenarioID}/user/?username=${username}`,
+ method: 'DELETE',
+ }),
+ }),
+});
diff --git a/src/store/endpoints/signal-endpoints.js b/src/store/endpoints/signal-endpoints.js
new file mode 100644
index 0000000..544d969
--- /dev/null
+++ b/src/store/endpoints/signal-endpoints.js
@@ -0,0 +1,38 @@
+/**
+ * This file is part of VILLASweb.
+ *
+ * VILLASweb is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * VILLASweb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with VILLASweb. If not, see
.
+ ******************************************************************************/
+
+export const signalEndpoints = (builder) => ({
+ 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',
+ }),
+ }),
+});
diff --git a/src/store/endpoints/user-endpoints.js b/src/store/endpoints/user-endpoints.js
new file mode 100644
index 0000000..e958edd
--- /dev/null
+++ b/src/store/endpoints/user-endpoints.js
@@ -0,0 +1,45 @@
+/**
+ * This file is part of VILLASweb.
+ *
+ * VILLASweb is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * VILLASweb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with VILLASweb. If not, see
.
+ ******************************************************************************/
+
+export const userEndpoints = (builder) => ({
+ 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) => ({
+ url: `users/${user.id}`,
+ method: 'PUT',
+ body: { user },
+ }),
+ }),
+ deleteUser: builder.mutation({
+ query: (id) => ({
+ url: `users/${id}`,
+ method: 'DELETE',
+ }),
+ }),
+});
\ No newline at end of file
diff --git a/src/store/endpoints/widget-endpoints.js b/src/store/endpoints/widget-endpoints.js
new file mode 100644
index 0000000..9837ae4
--- /dev/null
+++ b/src/store/endpoints/widget-endpoints.js
@@ -0,0 +1,48 @@
+/**
+ * This file is part of VILLASweb.
+ *
+ * VILLASweb is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * VILLASweb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with VILLASweb. If not, see
.
+ ******************************************************************************/
+
+export const widgetEndpoints = (builder) => ({
+ 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',
+ }),
+ }),
+});
\ No newline at end of file
diff --git a/src/store/index.js b/src/store/index.js
index c4f6072..46133f8 100644
--- a/src/store/index.js
+++ b/src/store/index.js
@@ -20,9 +20,11 @@ import userReducer from './userSlice';
import icReducer from './icSlice';
import configReducer from './configSlice'
import { apiSlice } from "./apiSlice";
+import authReducer from './authSlice';
export const store = configureStore({
reducer: {
+ auth: authReducer,
user: userReducer,
infrastructure: icReducer,
config: configReducer,