diff --git a/app/src/actions/serviceActions.ts b/app/src/actions/serviceActions.ts deleted file mode 100644 index 284cfa4072..0000000000 --- a/app/src/actions/serviceActions.ts +++ /dev/null @@ -1,35 +0,0 @@ -/** - * This file contains all redux actions that can be executed on services - */ - -// Constants of action types for fetching services from server -export const LOAD_SERVICES_IN_PROGRESS = "LOAD_SERVICES_IN_PROGRESS"; -export const LOAD_SERVICES_SUCCESS = "LOAD_SERVICES_SUCCESS"; -export const LOAD_SERVICES_FAILURE = "LOAD_SERVICES_FAILURE"; - -// Constants of action types affecting UI -export const SET_SERVICES_COLUMNS = "SET_SERVICES_COLUMNS"; - -// Actions affecting fetching services from server - -export const loadServicesInProgress = () => ({ - type: LOAD_SERVICES_IN_PROGRESS, -}); - -// @ts-expect-error TS(7006): Parameter 'services' implicitly has an 'any' type. -export const loadServicesSuccess = (services) => ({ - type: LOAD_SERVICES_SUCCESS, - payload: { services }, -}); - -export const loadServicesFailure = () => ({ - type: LOAD_SERVICES_FAILURE, -}); - -// Actions affecting UI - -// @ts-expect-error TS(7006): Parameter 'updatedColumns' implicitly has an 'any'... Remove this comment to see the full error message -export const setServicesColumns = (updatedColumns) => ({ - type: SET_SERVICES_COLUMNS, - payload: { updatedColumns }, -}); diff --git a/app/src/components/shared/MainNav.tsx b/app/src/components/shared/MainNav.tsx index 74ea9607bd..c0f9d35245 100644 --- a/app/src/components/shared/MainNav.tsx +++ b/app/src/components/shared/MainNav.tsx @@ -23,7 +23,7 @@ import { setOffset } from "../../actions/tableActions"; import { getUserInformation } from "../../selectors/userInfoSelectors"; import { hasAccess } from "../../utils/utils"; import { fetchServers } from "../../thunks/serverThunks"; -import { fetchServices } from "../../thunks/serviceThunks"; +import { fetchServices } from "../../slices/serviceSlice"; import { fetchGroups } from "../../slices/groupSlice"; import { GlobalHotKeys } from "react-hotkeys"; import { availableHotkeys } from "../../configs/hotkeysConfig"; @@ -56,8 +56,6 @@ const MainNav = ({ loadingServers, // @ts-expect-error TS(7031): Binding element 'loadingServersIntoTable' implicit... Remove this comment to see the full error message loadingServersIntoTable, -// @ts-expect-error TS(7031): Binding element 'loadingServices' implicitly has a... Remove this comment to see the full error message - loadingServices, // @ts-expect-error TS(7031): Binding element 'loadingServicesIntoTable' implici... Remove this comment to see the full error message loadingServicesIntoTable, // @ts-expect-error TS(7031): Binding element 'loadingUsers' implicitly has an '... Remove this comment to see the full error message @@ -156,7 +154,7 @@ const MainNav = ({ resetOffset(); // Fetching services from server - loadingServices(); + dispatch(fetchServices()); // Load services into table loadingServicesIntoTable(); @@ -342,7 +340,6 @@ const mapDispatchToProps = (dispatch) => ({ loadingJobsIntoTable: () => dispatch(loadJobsIntoTable()), loadingServers: () => dispatch(fetchServers()), loadingServersIntoTable: () => dispatch(loadServersIntoTable()), - loadingServices: () => dispatch(fetchServices()), loadingServicesIntoTable: () => dispatch(loadServicesIntoTable()), loadingUsers: () => dispatch(fetchUsers()), loadingUsersIntoTable: () => dispatch(loadUsersIntoTable()), diff --git a/app/src/components/systems/Jobs.tsx b/app/src/components/systems/Jobs.tsx index d4de220e92..cdb2b2c203 100644 --- a/app/src/components/systems/Jobs.tsx +++ b/app/src/components/systems/Jobs.tsx @@ -16,7 +16,6 @@ import { loadServicesIntoTable, } from "../../thunks/tableThunks"; import { fetchServers } from "../../thunks/serverThunks"; -import { fetchServices } from "../../thunks/serviceThunks"; import { editTextFilter } from "../../actions/tableFilterActions"; import { setOffset } from "../../actions/tableActions"; import { styleNavClosed, styleNavOpen } from "../../utils/componentsUtils"; @@ -27,6 +26,7 @@ import { hasAccess } from "../../utils/utils"; import { getCurrentFilterResource } from "../../selectors/tableFilterSelectors"; import { useAppDispatch, useAppSelector } from "../../store"; import { fetchJobs } from "../../slices/jobSlice"; +import { fetchServices } from "../../slices/serviceSlice"; /** * This component renders the table view of jobs @@ -40,8 +40,6 @@ const Jobs = ({ loadingServers, // @ts-expect-error TS(7031): Binding element 'loadingServersIntoTable' implicit... Remove this comment to see the full error message loadingServersIntoTable, -// @ts-expect-error TS(7031): Binding element 'loadingServices' implicitly has a... Remove this comment to see the full error message - loadingServices, // @ts-expect-error TS(7031): Binding element 'loadingServicesIntoTable' implici... Remove this comment to see the full error message loadingServicesIntoTable, // @ts-expect-error TS(7031): Binding element 'resetTextFilter' implicitly has a... Remove this comment to see the full error message @@ -88,7 +86,7 @@ const Jobs = ({ resetOffset(); // Fetching services from server - loadingServices(); + dispatch(fetchServices()); // Load services into table loadingServicesIntoTable(); @@ -193,7 +191,6 @@ const mapDispatchToProps = (dispatch) => ({ loadingJobsIntoTable: () => dispatch(loadJobsIntoTable()), loadingServers: () => dispatch(fetchServers()), loadingServersIntoTable: () => dispatch(loadServersIntoTable()), - loadingServices: () => dispatch(fetchServices()), loadingServicesIntoTable: () => dispatch(loadServicesIntoTable()), resetTextFilter: () => dispatch(editTextFilter("")), resetOffset: () => dispatch(setOffset(0)), diff --git a/app/src/components/systems/Servers.tsx b/app/src/components/systems/Servers.tsx index 771475f62c..ff1392639e 100644 --- a/app/src/components/systems/Servers.tsx +++ b/app/src/components/systems/Servers.tsx @@ -16,7 +16,6 @@ import { loadServersIntoTable, loadServicesIntoTable, } from "../../thunks/tableThunks"; -import { fetchServices } from "../../thunks/serviceThunks"; import { editTextFilter } from "../../actions/tableFilterActions"; import { setOffset } from "../../actions/tableActions"; import { styleNavClosed, styleNavOpen } from "../../utils/componentsUtils"; @@ -26,6 +25,7 @@ import { getUserInformation } from "../../selectors/userInfoSelectors"; import { hasAccess } from "../../utils/utils"; import { getCurrentFilterResource } from "../../selectors/tableFilterSelectors"; import { useAppDispatch } from "../../store"; +import { fetchServices } from "../../slices/serviceSlice"; import { fetchJobs } from "../../slices/jobSlice"; /** @@ -42,8 +42,6 @@ const Servers = ({ loadingFilters, // @ts-expect-error TS(7031): Binding element 'loadingJobsIntoTable' implicitly ... Remove this comment to see the full error message loadingJobsIntoTable, -// @ts-expect-error TS(7031): Binding element 'loadingServices' implicitly has a... Remove this comment to see the full error message - loadingServices, // @ts-expect-error TS(7031): Binding element 'loadingServicesIntoTable' implici... Remove this comment to see the full error message loadingServicesIntoTable, // @ts-expect-error TS(7031): Binding element 'resetTextFilter' implicitly has a... Remove this comment to see the full error message @@ -83,7 +81,7 @@ const Servers = ({ resetOffset(); // Fetching services from server - loadingServices(); + dispatch(fetchServices()); // Load services into table loadingServicesIntoTable(); @@ -189,7 +187,6 @@ const mapDispatchToProps = (dispatch) => ({ loadingServers: () => dispatch(fetchServers()), loadingServersIntoTable: () => dispatch(loadServersIntoTable()), loadingJobsIntoTable: () => dispatch(loadJobsIntoTable()), - loadingServices: () => dispatch(fetchServices()), loadingServicesIntoTable: () => dispatch(loadServicesIntoTable()), resetTextFilter: () => dispatch(editTextFilter("")), resetOffset: () => dispatch(setOffset(0)), diff --git a/app/src/components/systems/Services.tsx b/app/src/components/systems/Services.tsx index 46bd300473..1a455e681d 100644 --- a/app/src/components/systems/Services.tsx +++ b/app/src/components/systems/Services.tsx @@ -7,14 +7,13 @@ import TableFilters from "../shared/TableFilters"; import Table from "../shared/Table"; import MainNav from "../shared/MainNav"; import Notifications from "../shared/Notifications"; -import { servicesTemplateMap } from "../../configs/tableConfigs/servicesTableConfig"; +import { servicesTemplateMap } from "../../configs/tableConfigs/servicesTableMap"; import { fetchFilters } from "../../thunks/tableFilterThunks"; import { loadJobsIntoTable, loadServersIntoTable, loadServicesIntoTable, } from "../../thunks/tableThunks"; -import { fetchServices } from "../../thunks/serviceThunks"; import { fetchServers } from "../../thunks/serverThunks"; import { getTotalServices } from "../../selectors/serviceSelector"; import { editTextFilter } from "../../actions/tableFilterActions"; @@ -25,19 +24,16 @@ import Footer from "../Footer"; import { getUserInformation } from "../../selectors/userInfoSelectors"; import { hasAccess } from "../../utils/utils"; import { getCurrentFilterResource } from "../../selectors/tableFilterSelectors"; -import { useAppDispatch } from "../../store"; +import { useAppDispatch, useAppSelector } from "../../store"; import { fetchJobs } from "../../slices/jobSlice"; +import { fetchServices } from "../../slices/serviceSlice"; /** * This component renders the table view of services */ const Services = ({ -// @ts-expect-error TS(7031): Binding element 'loadingServices' implicitly has a... Remove this comment to see the full error message - loadingServices, // @ts-expect-error TS(7031): Binding element 'loadingServicesIntoTable' implici... Remove this comment to see the full error message loadingServicesIntoTable, -// @ts-expect-error TS(7031): Binding element 'services' implicitly has an 'any'... Remove this comment to see the full error message - services, // @ts-expect-error TS(7031): Binding element 'loadingFilters' implicitly has an... Remove this comment to see the full error message loadingFilters, // @ts-expect-error TS(7031): Binding element 'loadingJobsIntoTable' implicitly ... Remove this comment to see the full error message @@ -59,9 +55,16 @@ const Services = ({ const dispatch = useAppDispatch(); const [displayNavigation, setNavigation] = useState(false); + const services = useAppSelector(state => getTotalServices(state)); + + // TODO: Get rid of the wrappers when modernizing redux is done + const fetchServicesWrapper = () => { + dispatch(fetchServices()) + } + const loadServices = async () => { // Fetching services from server - await loadingServices(); + await dispatch(fetchServices()); // Load services into table loadingServicesIntoTable(); @@ -158,7 +161,7 @@ const Services = ({
{/* Include filters component */} @@ -176,7 +179,6 @@ const Services = ({ // Getting state data out of redux store // @ts-expect-error TS(7006): Parameter 'state' implicitly has an 'any' type. const mapStateToProps = (state) => ({ - services: getTotalServices(state), user: getUserInformation(state), currentFilterType: getCurrentFilterResource(state), }); @@ -186,7 +188,6 @@ const mapStateToProps = (state) => ({ const mapDispatchToProps = (dispatch) => ({ // @ts-expect-error TS(7006): Parameter 'resource' implicitly has an 'any' type. loadingFilters: (resource) => dispatch(fetchFilters(resource)), - loadingServices: () => dispatch(fetchServices()), loadingServicesIntoTable: () => dispatch(loadServicesIntoTable()), loadingJobsIntoTable: () => dispatch(loadJobsIntoTable()), loadingServers: () => dispatch(fetchServers()), diff --git a/app/src/components/systems/partials/ServicesActionsCell.tsx b/app/src/components/systems/partials/ServicesActionsCell.tsx index c8585caed7..ec9d96b962 100644 --- a/app/src/components/systems/partials/ServicesActionsCell.tsx +++ b/app/src/components/systems/partials/ServicesActionsCell.tsx @@ -1,10 +1,11 @@ import React from "react"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; -import { fetchServices, restartService } from "../../../thunks/serviceThunks"; import { loadServicesIntoTable } from "../../../thunks/tableThunks"; import { getUserInformation } from "../../../selectors/userInfoSelectors"; import { hasAccess } from "../../../utils/utils"; +import { useAppDispatch } from "../../../store"; +import { fetchServices, restartService } from "../../../slices/serviceSlice"; /** * This component renders the action cells of services in the table view @@ -20,10 +21,11 @@ const ServicesActionCell = ({ user, }) => { const { t } = useTranslation(); + const dispatch = useAppDispatch(); const onClickRestart = async () => { - await restartService(row.hostname, row.name); - await loadServices(); + await dispatch(restartService({host: row.hostname, serviceType: row.name})); + await dispatch(fetchServices()); loadServicesIntoTable(); }; @@ -49,7 +51,6 @@ const mapStateToProps = (state) => ({ // mapping actions to dispatch // @ts-expect-error TS(7006): Parameter 'dispatch' implicitly has an 'any' type. const mapDispatchToProps = (dispatch) => ({ - loadServices: () => dispatch(fetchServices()), loadServicesIntoTable: () => dispatch(loadServicesIntoTable()), }); diff --git a/app/src/configs/tableConfigs/servicesTableConfig.ts b/app/src/configs/tableConfigs/servicesTableConfig.ts index ea0ba9bf04..d51973081b 100644 --- a/app/src/configs/tableConfigs/servicesTableConfig.ts +++ b/app/src/configs/tableConfigs/servicesTableConfig.ts @@ -1,7 +1,3 @@ -import MeanRunTimeCell from "../../components/systems/partials/MeanRunTimeCell"; -import MeanQueueTimeCell from "../../components/systems/partials/MeanQueueTimeCell"; -import ServicesActionCell from "../../components/systems/partials/ServicesActionsCell"; - /** * Config that contains the columns and further information regarding services. These are the information that never or hardly changes. * That's why it is hard coded here and not fetched from server. @@ -73,14 +69,3 @@ export const servicesTableConfig = { category: "systems", multiSelect: false, }; - -/** - * This map contains the mapping between the template strings above and the corresponding react component. - * This helps to render different templates of cells more dynamically. Even empty needed, because Table component - * uses template map. - */ -export const servicesTemplateMap = { - MeanRunTimeCell: MeanRunTimeCell, - MeanQueueTimeCell: MeanQueueTimeCell, - ServicesActionsCell: ServicesActionCell, -}; diff --git a/app/src/configs/tableConfigs/servicesTableMap.ts b/app/src/configs/tableConfigs/servicesTableMap.ts new file mode 100644 index 0000000000..e0c0ca4726 --- /dev/null +++ b/app/src/configs/tableConfigs/servicesTableMap.ts @@ -0,0 +1,14 @@ +import MeanRunTimeCell from "../../components/systems/partials/MeanRunTimeCell"; +import MeanQueueTimeCell from "../../components/systems/partials/MeanQueueTimeCell"; +import ServicesActionCell from "../../components/systems/partials/ServicesActionsCell"; + +/** + * This map contains the mapping between the template strings above and the corresponding react component. + * This helps to render different templates of cells more dynamically. Even empty needed, because Table component + * uses template map. + */ +export const servicesTemplateMap = { + MeanRunTimeCell: MeanRunTimeCell, + MeanQueueTimeCell: MeanQueueTimeCell, + ServicesActionsCell: ServicesActionCell, +}; diff --git a/app/src/reducers/serviceReducer.ts b/app/src/reducers/serviceReducer.ts deleted file mode 100644 index c3d11a0acb..0000000000 --- a/app/src/reducers/serviceReducer.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { servicesTableConfig } from "../configs/tableConfigs/servicesTableConfig"; -import { - LOAD_SERVICES_FAILURE, - LOAD_SERVICES_IN_PROGRESS, - LOAD_SERVICES_SUCCESS, - SET_SERVICES_COLUMNS, -} from "../actions/serviceActions"; - -/** - * This file contains redux reducer for actions affecting the state of services - */ - -// Fill columns initially with columns defined in servicesTableConfig -const initialColumns = servicesTableConfig.columns.map((column) => ({ - ...column, - deactivated: false, -})); - -// Initial state of services in redux store -const initialState = { - isLoading: false, - results: [], - columns: initialColumns, - total: 0, - count: 0, - offset: 0, - limit: 0, -}; - -// Reducer for services -// @ts-expect-error TS(7006): Parameter 'action' implicitly has an 'any' type. -const services = (state = initialState, action) => { - const { type, payload } = action; - switch (type) { - case LOAD_SERVICES_IN_PROGRESS: { - return { - ...state, - isLoading: true, - }; - } - case LOAD_SERVICES_SUCCESS: { - const { services } = payload; - return { - ...state, - isLoading: false, - total: services.total, - count: services.count, - limit: services.limit, - offset: services.offset, - results: services.results, - }; - } - case LOAD_SERVICES_FAILURE: { - return { - ...state, - isLoading: false, - }; - } - case SET_SERVICES_COLUMNS: { - const { updatedColumns } = payload; - return { - ...state, - columns: updatedColumns, - }; - } - default: - return state; - } -}; - -export default services; diff --git a/app/src/selectors/serviceSelector.ts b/app/src/selectors/serviceSelector.ts index 7fff0eaf2e..9e9c0783ae 100644 --- a/app/src/selectors/serviceSelector.ts +++ b/app/src/selectors/serviceSelector.ts @@ -1,6 +1,7 @@ +import { RootState } from "../store"; + /** * This file contains selectors regarding services */ - -export const getServices = (state: any) => state.services.results; -export const getTotalServices = (state: any) => state.services.total; +export const getServices = (state: RootState) => state.services.results; +export const getTotalServices = (state: RootState) => state.services.total; diff --git a/app/src/slices/serviceSlice.ts b/app/src/slices/serviceSlice.ts new file mode 100644 index 0000000000..16e21b52c2 --- /dev/null +++ b/app/src/slices/serviceSlice.ts @@ -0,0 +1,119 @@ +import { PayloadAction, SerializedError, createAsyncThunk, createSlice } from '@reduxjs/toolkit' +import { servicesTableConfig } from "../configs/tableConfigs/servicesTableConfig"; +import axios from 'axios'; +import { getURLParams } from '../utils/resourceUtils'; + +/** + * This file contains redux reducer for actions affecting the state of services + */ +type Service = { + completed: number, + hostname: string, + meanQueueTime: number, + meanRunTime: number, + name: string, + nodeName: string, + queued: number, + running: number, + status: string, +} + +type ServiceState = { + status: 'uninitialized' | 'loading' | 'succeeded' | 'failed', + error: SerializedError | null, + results: Service[], + columns: any, // TODO: proper typing, derive from `initialColumns` + total: number, + count: number, + offset: number, + limit: number, +} + +// Fill columns initially with columns defined in servicesTableConfig +const initialColumns = servicesTableConfig.columns.map((column) => ({ + ...column, + deactivated: false, +})); + +// Initial state of services in redux store +const initialState: ServiceState = { + status: 'uninitialized', + error: null, + results: [], + columns: initialColumns, + total: 0, + count: 0, + offset: 0, + limit: 0, +}; + +// fetch services from server +export const fetchServices = createAsyncThunk('services/fetchServices', async (_, { getState }) => { + const state = getState(); + let params = getURLParams(state); + // Just make the async request here, and return the response. + // This will automatically dispatch a `pending` action first, + // and then `fulfilled` or `rejected` actions based on the promise. + const res = await axios.get("/admin-ng/services/services.json", { params: params }); + return res.data; +}); + +// restarts a service after initiated by user +export const restartService = createAsyncThunk('services/fetchServices', async (params: {host: any, serviceType: any}) => { + const { host, serviceType } = params + let data = new URLSearchParams(); + data.append("host", host); + data.append("serviceType", serviceType); + + axios + .post("/services/sanitize", data) + .then((response) => { + console.log(response); + }) + .catch((response) => { + console.log(response); + }); +}); + +const serviceSlice = createSlice({ + name: 'services', + initialState, + reducers: { + setServiceColumns(state, action: PayloadAction< + ServiceState["columns"] + >) { + state.columns = action.payload.updatedColumns; + }, + }, + // These are used for thunks + extraReducers: builder => { + builder + .addCase(fetchServices.pending, (state) => { + state.status = 'loading'; + }) + .addCase(fetchServices.fulfilled, (state, action: PayloadAction<{ + total: ServiceState["total"], + count: ServiceState["count"], + limit: ServiceState["limit"], + offset: ServiceState["offset"], + results: ServiceState["results"], + }>) => { + state.status = 'succeeded'; + const acls = action.payload; + state.total = acls.total; + state.count = acls.count; + state.limit = acls.limit; + state.offset = acls.offset; + state.results = acls.results; + }) + .addCase(fetchServices.rejected, (state, action) => { + state.status = 'failed'; + state.error = action.error; + }); + } +}); + +export const { setServiceColumns } = serviceSlice.actions; + +// Export the slice reducer as the default export +export default serviceSlice.reducer; diff --git a/app/src/store.ts b/app/src/store.ts index 8ec2e92979..dc478cc0b6 100644 --- a/app/src/store.ts +++ b/app/src/store.ts @@ -11,7 +11,7 @@ import series from "./slices/seriesSlice"; import recordings from "./reducers/recordingReducer"; import jobs from "./slices/jobSlice"; import servers from "./reducers/serverReducer"; -import services from "./reducers/serviceReducer"; +import services from "./slices/serviceSlice"; import users from "./reducers/userReducers"; import groups from "./slices/groupSlice"; import acls from "./slices/aclSlice"; diff --git a/app/src/thunks/serviceThunks.ts b/app/src/thunks/serviceThunks.ts deleted file mode 100644 index 5716bdb880..0000000000 --- a/app/src/thunks/serviceThunks.ts +++ /dev/null @@ -1,45 +0,0 @@ -import axios from "axios"; -import { - loadServicesFailure, - loadServicesInProgress, - loadServicesSuccess, -} from "../actions/serviceActions"; -import { getURLParams } from "../utils/resourceUtils"; - -// fetch services from server -// @ts-expect-error TS(7006): Parameter 'dispatch' implicitly has an 'any' type. -export const fetchServices = () => async (dispatch, getState) => { - try { - dispatch(loadServicesInProgress()); - - const state = getState(); - let params = getURLParams(state); - - // /services.json?limit=0&offset=0&filter={filter}&sort={sort} - let data = await axios.get("/admin-ng/services/services.json", { - params: params, - }); - - const services = await data.data; - dispatch(loadServicesSuccess(services)); - } catch (e) { - dispatch(loadServicesFailure()); - } -}; - -// restarts a service after initiated by user -// @ts-expect-error TS(7006): Parameter 'host' implicitly has an 'any' type. -export const restartService = async (host, serviceType) => { - let data = new URLSearchParams(); - data.append("host", host); - data.append("serviceType", serviceType); - - axios - .post("/services/sanitize", data) - .then((response) => { - console.log(response); - }) - .catch((response) => { - console.log(response); - }); -}; diff --git a/app/src/thunks/tableFilterThunks.ts b/app/src/thunks/tableFilterThunks.ts index a01ea0d7a3..0165c5ba90 100644 --- a/app/src/thunks/tableFilterThunks.ts +++ b/app/src/thunks/tableFilterThunks.ts @@ -9,7 +9,7 @@ import axios from "axios"; import { relativeDateSpanToFilterValue } from "../utils/dateUtils"; import { setOffset } from "../actions/tableActions"; import { fetchEvents } from "../slices/eventSlice"; -import { fetchServices } from "./serviceThunks"; +import { fetchServices } from "../slices/serviceSlice"; /** * This file contains methods/thunks used to query the REST-API of Opencast to get the filters of a certain resource type. diff --git a/app/src/thunks/tableThunks.ts b/app/src/thunks/tableThunks.ts index 758ccedd0f..5979e82011 100644 --- a/app/src/thunks/tableThunks.ts +++ b/app/src/thunks/tableThunks.ts @@ -37,7 +37,7 @@ import { import { fetchRecordings } from "./recordingThunks"; import { fetchJobs, setJobColumns } from "../slices/jobSlice"; import { fetchServers } from "./serverThunks"; -import { fetchServices } from "./serviceThunks"; +import { fetchServices, setServiceColumns } from "../slices/serviceSlice"; import { fetchUsers } from "./userThunks"; import { fetchGroups } from "../slices/groupSlice"; import { fetchThemes, setThemeColumns } from "../slices/themeSlice"; @@ -46,7 +46,6 @@ import { setServerColumns } from "../actions/serverActions"; import { setUserColumns } from "../actions/userActions"; import { setGroupColumns } from "../slices/groupSlice"; import { fetchAcls, setAclColumns } from "../slices/aclSlice"; -import { setServicesColumns } from "../actions/serviceActions"; /** * This file contains methods/thunks used to manage the table in the main view and its state changes @@ -628,7 +627,7 @@ export const changeColumnSelection = (updatedColumns) => async ( break; } case "services": { - await dispatch(setServicesColumns(updatedColumns)); + await dispatch(setServiceColumns(updatedColumns)); dispatch(loadServicesIntoTable()); break; }