store: add initial cockpit store
Co-authored-by: Gianluca Zuccarelli <gzuccare@redhat.com>
This commit is contained in:
parent
82f3f38e56
commit
f13ee49565
5 changed files with 122 additions and 20 deletions
|
|
@ -9,7 +9,7 @@ import { Provider } from 'react-redux';
|
|||
import { BrowserRouter } from 'react-router-dom';
|
||||
|
||||
import { Router } from './Router';
|
||||
import { store } from './store';
|
||||
import { onPremStore as store } from './store';
|
||||
|
||||
const Application = () => {
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import React from 'react';
|
|||
import { Provider } from 'react-redux';
|
||||
|
||||
import App from './App';
|
||||
import { store } from './store';
|
||||
import { serviceStore as store } from './store';
|
||||
|
||||
if (
|
||||
process.env.NODE_ENV === 'development' &&
|
||||
|
|
@ -16,12 +16,12 @@ if (
|
|||
serviceWorker: {
|
||||
url: '/beta/apps/image-builder/mockServiceWorker.js',
|
||||
options: {
|
||||
/*
|
||||
/*
|
||||
Service workers can only intercept requests made from within their scope.
|
||||
mockServiceWorker.js is served from /beta/apps/image-builder/, which becomes
|
||||
the worker's default scope. Set scope to '/' so that all requests are in scope
|
||||
the worker's default scope. Set scope to '/' so that all requests are in scope
|
||||
and can be intercepted. Note that the Service-Worker-Allowed header must
|
||||
be set to '/' for this to work, and is done in the webpack config.
|
||||
be set to '/' for this to work, and is done in the webpack config.
|
||||
*/
|
||||
scope: '../../../',
|
||||
},
|
||||
|
|
|
|||
53
src/store/cockpitApi.ts
Normal file
53
src/store/cockpitApi.ts
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
|
||||
|
||||
import {
|
||||
GetArchitecturesApiResponse,
|
||||
GetArchitecturesApiArg,
|
||||
GetBlueprintsApiArg,
|
||||
GetBlueprintsApiResponse,
|
||||
} from './imageBuilderApi';
|
||||
|
||||
const emptyCockpitApi = createApi({
|
||||
reducerPath: 'cockpitApi',
|
||||
baseQuery: fetchBaseQuery({ baseUrl: '/api' }),
|
||||
endpoints: () => ({}),
|
||||
});
|
||||
|
||||
export const cockpitApi = emptyCockpitApi.injectEndpoints({
|
||||
endpoints: (builder) => {
|
||||
return {
|
||||
getArchitectures: builder.query<
|
||||
GetArchitecturesApiResponse,
|
||||
GetArchitecturesApiArg
|
||||
>({
|
||||
query: (queryArg) => ({
|
||||
url: `/architectures/${queryArg.distribution}`,
|
||||
}),
|
||||
}),
|
||||
getBlueprints: builder.query<
|
||||
GetBlueprintsApiResponse,
|
||||
GetBlueprintsApiArg
|
||||
>({
|
||||
queryFn: () => {
|
||||
// TODO: Add cockpit file api support for reading in blueprints.
|
||||
// For now we're just hardcoding a dummy response
|
||||
// so we can render an empty table.
|
||||
return new Promise((resolve) => {
|
||||
resolve({
|
||||
data: {
|
||||
meta: { count: 0 },
|
||||
links: {
|
||||
first: '',
|
||||
last: '',
|
||||
},
|
||||
data: [],
|
||||
},
|
||||
});
|
||||
});
|
||||
},
|
||||
}),
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export const { useGetBlueprintsQuery, useGetArchitecturesQuery } = cockpitApi;
|
||||
|
|
@ -3,6 +3,7 @@ import { combineReducers, configureStore } from '@reduxjs/toolkit';
|
|||
import promiseMiddleware from 'redux-promise-middleware';
|
||||
|
||||
import { blueprintsSlice } from './BlueprintSlice';
|
||||
import { cockpitApi } from './cockpitApi';
|
||||
import { complianceApi } from './complianceApi';
|
||||
import { contentSourcesApi } from './contentSourcesApi';
|
||||
import { edgeApi } from './edgeApi';
|
||||
|
|
@ -19,7 +20,7 @@ import wizardSlice, {
|
|||
selectImageTypes,
|
||||
} from './wizardSlice';
|
||||
|
||||
export const reducer = combineReducers({
|
||||
export const serviceReducer = combineReducers({
|
||||
[contentSourcesApi.reducerPath]: contentSourcesApi.reducer,
|
||||
[edgeApi.reducerPath]: edgeApi.reducer,
|
||||
[imageBuilderApi.reducerPath]: imageBuilderApi.reducer,
|
||||
|
|
@ -31,6 +32,16 @@ export const reducer = combineReducers({
|
|||
blueprints: blueprintsSlice.reducer,
|
||||
});
|
||||
|
||||
export const onPremReducer = combineReducers({
|
||||
[cockpitApi.reducerPath]: cockpitApi.reducer,
|
||||
// TODO: add other endpoints so we can remove this.
|
||||
// It's still needed to get things to work.
|
||||
[imageBuilderApi.reducerPath]: imageBuilderApi.reducer,
|
||||
notifications: notificationsReducer,
|
||||
wizard: wizardSlice,
|
||||
blueprints: blueprintsSlice.reducer,
|
||||
});
|
||||
|
||||
startAppListening({
|
||||
actionCreator: changeArchitecture,
|
||||
effect: (action, listenerApi) => {
|
||||
|
|
@ -41,16 +52,19 @@ startAppListening({
|
|||
const architecture = action.payload;
|
||||
|
||||
// The response from the RTKQ getArchitectures hook
|
||||
const architecturesResponse =
|
||||
imageBuilderApi.endpoints.getArchitectures.select({
|
||||
distribution: distribution,
|
||||
})(state);
|
||||
const architecturesResponse = process.env.IS_ON_PREMISE
|
||||
? cockpitApi.endpoints.getArchitectures.select({
|
||||
distribution: distribution,
|
||||
})(state as onPremState)
|
||||
: imageBuilderApi.endpoints.getArchitectures.select({
|
||||
distribution: distribution,
|
||||
})(state as serviceState);
|
||||
|
||||
const allowedImageTypes = architecturesResponse?.data?.find(
|
||||
(elem) => elem.arch === architecture
|
||||
)?.image_types;
|
||||
|
||||
const filteredImageTypes = imageTypes.filter((imageType) =>
|
||||
const filteredImageTypes = imageTypes.filter((imageType: string) =>
|
||||
allowedImageTypes?.includes(imageType)
|
||||
);
|
||||
|
||||
|
|
@ -68,10 +82,13 @@ startAppListening({
|
|||
const architecture = selectArchitecture(state);
|
||||
|
||||
// The response from the RTKQ getArchitectures hook
|
||||
const architecturesResponse =
|
||||
imageBuilderApi.endpoints.getArchitectures.select({
|
||||
distribution: distribution,
|
||||
})(state);
|
||||
const architecturesResponse = process.env.IS_ON_PREMISE
|
||||
? cockpitApi.endpoints.getArchitectures.select({
|
||||
distribution: distribution,
|
||||
})(state as onPremState)
|
||||
: imageBuilderApi.endpoints.getArchitectures.select({
|
||||
distribution: distribution,
|
||||
})(state as serviceState);
|
||||
|
||||
const allowedImageTypes = architecturesResponse?.data?.find(
|
||||
(elem) => elem.arch === architecture
|
||||
|
|
@ -88,7 +105,7 @@ startAppListening({
|
|||
// Listener middleware must be prepended according to RTK docs:
|
||||
// https://redux-toolkit.js.org/api/createListenerMiddleware#basic-usage
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
||||
export const middleware = (getDefaultMiddleware: Function) =>
|
||||
export const serviceMiddleware = (getDefaultMiddleware: Function) =>
|
||||
getDefaultMiddleware()
|
||||
.prepend(listenerMiddleware.middleware)
|
||||
.concat(
|
||||
|
|
@ -100,9 +117,38 @@ export const middleware = (getDefaultMiddleware: Function) =>
|
|||
complianceApi.middleware
|
||||
);
|
||||
|
||||
export const store = configureStore({ reducer, middleware });
|
||||
// Listener middleware must be prepended according to RTK docs:
|
||||
// https://redux-toolkit.js.org/api/createListenerMiddleware#basic-usage
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
||||
export const onPremMiddleware = (getDefaultMiddleware: Function) =>
|
||||
getDefaultMiddleware().prepend(listenerMiddleware.middleware).concat(
|
||||
promiseMiddleware,
|
||||
// TODO: add other endpoints so we can remove this.
|
||||
// It's still needed to get things to work.
|
||||
imageBuilderApi.middleware,
|
||||
cockpitApi.middleware
|
||||
);
|
||||
|
||||
export const onPremStore = configureStore({
|
||||
reducer: onPremReducer,
|
||||
middleware: onPremMiddleware,
|
||||
});
|
||||
|
||||
export const serviceStore = configureStore({
|
||||
reducer: serviceReducer,
|
||||
middleware: serviceMiddleware,
|
||||
});
|
||||
|
||||
// we don't need to export these for now, they are just helpers
|
||||
// for some of the functions in this file
|
||||
type onPremState = ReturnType<typeof onPremStore.getState>;
|
||||
type serviceState = ReturnType<typeof serviceStore.getState>;
|
||||
|
||||
export const store = process.env.IS_ON_PREMISE ? onPremStore : serviceStore;
|
||||
|
||||
// Infer the `RootState` and `AppDispatch` types from the store itself
|
||||
export type RootState = ReturnType<typeof store.getState>;
|
||||
export type RootState = onPremState | serviceState;
|
||||
// Inferred type: {posts: PostsState, comments: CommentsState, users: UsersState}
|
||||
export type AppDispatch = typeof store.dispatch;
|
||||
export type AppDispatch =
|
||||
| typeof onPremStore.dispatch
|
||||
| typeof serviceStore.dispatch;
|
||||
|
|
|
|||
|
|
@ -8,7 +8,10 @@ import { createMemoryRouter, RouterProvider } from 'react-router-dom';
|
|||
import ImportImageWizard from '../Components/CreateImageWizard/ImportImageWizard';
|
||||
import LandingPage from '../Components/LandingPage/LandingPage';
|
||||
import ShareImageModal from '../Components/ShareImageModal/ShareImageModal';
|
||||
import { middleware, reducer } from '../store';
|
||||
import {
|
||||
serviceMiddleware as middleware,
|
||||
serviceReducer as reducer,
|
||||
} from '../store';
|
||||
import { resolveRelPath } from '../Utilities/path';
|
||||
|
||||
const defaultRoutes = [
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue