diff --git a/packages/plugins/index.ts b/packages/plugins/index.ts index 0fc0f7adb..dcab3c0f4 100644 --- a/packages/plugins/index.ts +++ b/packages/plugins/index.ts @@ -5,4 +5,5 @@ export * from './src/utils'; export * from './src/StoreProvider'; export * from './src/PluginResolver'; export * from './src/usePluginSystem'; +export * from './src/usePluginOverlay'; export type {Plugin, PluginEntry} from './src/internal/Plugin'; diff --git a/packages/plugins/src/internal/Plugin.ts b/packages/plugins/src/internal/Plugin.ts index 6f157b331..2465bc8c4 100644 --- a/packages/plugins/src/internal/Plugin.ts +++ b/packages/plugins/src/internal/Plugin.ts @@ -1,3 +1,4 @@ +import {PluginOverlay} from './PluginOverlay'; import type {PluginScope} from './PluginScope'; import {PluginDetails as PluginDetailsSymbol, PluginInit} from './symbols'; import type {PluginConfig, PluginConfigInput, PluginDetails, PluginScopeStateFor, PluginState} from './types'; @@ -7,6 +8,8 @@ export class Plugin { public readonly [PluginInit]: (context: PluginScope>, config: T['config']) => void; public readonly [PluginDetailsSymbol]: PluginDetails; + public readonly overlay = new PluginOverlay(); + public constructor( config: PluginDetails, initFn: (tk: PluginScope>, config: PluginConfig) => void diff --git a/packages/plugins/src/internal/PluginOverlay.ts b/packages/plugins/src/internal/PluginOverlay.ts new file mode 100644 index 000000000..88c08392d --- /dev/null +++ b/packages/plugins/src/internal/PluginOverlay.ts @@ -0,0 +1,32 @@ +import {PluginOverlayContext} from './symbols'; +import {PluginProvider} from './types'; + +export class PluginOverlay { + private [PluginOverlayContext]: Record = {}; + private providerCreator: (() => PluginProvider) | null = null; + + public getContext() { + return this[PluginOverlayContext]; + } + + public setContext(context: Record | ((oldContext: Record) => Record)) { + if (typeof context === 'function') { + this[PluginOverlayContext] = context(this[PluginOverlayContext]); + return; + } + this[PluginOverlayContext] = context; + } + + public appendContext(context: Record) { + this[PluginOverlayContext] = {...this[PluginOverlayContext], ...context}; + } + + public useProvider() { + if (!this.providerCreator) return null; + return this.providerCreator(); + } + + public provider(pc: typeof this.providerCreator) { + this.providerCreator = pc; + } +} diff --git a/packages/plugins/src/internal/symbols.ts b/packages/plugins/src/internal/symbols.ts index 5f9e6d8f0..dd5c5e568 100644 --- a/packages/plugins/src/internal/symbols.ts +++ b/packages/plugins/src/internal/symbols.ts @@ -20,3 +20,4 @@ export const PluginScopeScheduleUpdate = Symbol.for('schedule informing about ch export const PluginScopeEmitChange = Symbol.for('inform about data change'); export const PluginScopeSubscribeChange = Symbol.for('subscribe to data change'); export const PluginScopeListeners = Symbol.for('subscription listeners list'); +export const PluginOverlayContext = Symbol.for('context used only for overlay'); diff --git a/packages/plugins/src/usePluginOverlay.ts b/packages/plugins/src/usePluginOverlay.ts new file mode 100644 index 000000000..ceaa12545 --- /dev/null +++ b/packages/plugins/src/usePluginOverlay.ts @@ -0,0 +1,29 @@ +import {FC, PropsWithChildren, ReactElement, createElement, useCallback} from 'react'; + +import {Plugin, PluginEntry} from './internal/Plugin'; +import {PluginOverlay} from './internal/PluginOverlay'; + +export const usePluginOverlay = (plugins: PluginEntry[]) => { + const createProviderTree = useCallback((overlays: PluginOverlay[], children: ReactElement): ReactElement => { + if (overlays.length === 0) { + return children; + } + + const lastOverlay = overlays[overlays.length - 1]; + const provider = lastOverlay.useProvider(); + const newChildren = provider ? createElement(provider.type, provider.props, children) : children; + + return createProviderTree(overlays.slice(0, -1), newChildren); + }, []); + + const ProviderComponent = useCallback>>( + ({children}) => + createProviderTree( + plugins.filter((plugin): plugin is Plugin => 'overlay' in plugin).map(plugin => plugin.overlay), + children + ), + [createProviderTree] + ); + + return ProviderComponent; +}; diff --git a/packages/web/src/AppRoot.tsx b/packages/web/src/AppRoot.tsx index 64fd06716..7e96839ee 100644 --- a/packages/web/src/AppRoot.tsx +++ b/packages/web/src/AppRoot.tsx @@ -3,7 +3,7 @@ import {useMemo} from 'react'; import {Layout} from 'antd'; import {Content} from 'antd/lib/layout/layout'; -import {usePluginSystem} from '@testkube/plugins'; +import {usePluginOverlay, usePluginSystem} from '@testkube/plugins'; import {ReactComponent as Logo} from '@assets/testkube-symbol-color.svg'; @@ -26,7 +26,6 @@ import ModalPlugin from '@plugins/modal/plugin'; import PermissionsPlugin from '@plugins/permissions/plugin'; import PromoBannersPlugin from '@plugins/promo-banners/plugin'; import RouterPlugin from '@plugins/router/plugin'; -import RtkResetOnApiChangePlugin from '@plugins/rtk-reset-on-api-change/plugin'; import RtkPlugin from '@plugins/rtk/plugin'; import SettingsPlugin from '@plugins/settings/plugin'; import SiderCloudMigratePlugin from '@plugins/sider-cloud-migrate/plugin'; @@ -51,7 +50,6 @@ const AppRoot: React.FC = () => { ConfigPlugin.configure({slackUrl: externalLinks.slack}), RouterPlugin.configure({baseUrl: env.basename || ''}), PermissionsPlugin.configure({resolver: new BasePermissionsResolver()}), - RtkResetOnApiChangePlugin, RtkPlugin, ModalPlugin, SiderLogoPlugin.configure({logo: }), @@ -67,6 +65,8 @@ const AppRoot: React.FC = () => { ); const [PluginProvider, {routes}] = usePluginSystem(plugins); + const PluginOverlayProvider = usePluginOverlay(plugins); + return ( { debug={env.debugTelemetry} paused > - - - - - - - - - - - - + + + + + + + + + + + + + + ); diff --git a/packages/web/src/components/molecules/LabelsSelect/LabelsSelect.tsx b/packages/web/src/components/molecules/LabelsSelect/LabelsSelect.tsx index 68b14832c..f683dbfb7 100644 --- a/packages/web/src/components/molecules/LabelsSelect/LabelsSelect.tsx +++ b/packages/web/src/components/molecules/LabelsSelect/LabelsSelect.tsx @@ -51,6 +51,7 @@ const LabelsSelect: React.FC = props => { const {data, isFetching} = useGetLabelsQuery(null, { pollingInterval: PollingIntervals.default, skip: Boolean(options) || !isClusterAvailable, + refetchOnMountOrArgChange: true, }); const formattedValue = useMemo(() => (value || []).map(label => ({label, value: label})), [value]); diff --git a/packages/web/src/components/molecules/TestActionsDropdown/TestActionsDropdown.tsx b/packages/web/src/components/molecules/TestActionsDropdown/TestActionsDropdown.tsx index 199376396..9a0a3e064 100644 --- a/packages/web/src/components/molecules/TestActionsDropdown/TestActionsDropdown.tsx +++ b/packages/web/src/components/molecules/TestActionsDropdown/TestActionsDropdown.tsx @@ -39,7 +39,11 @@ const TestActionsDropdown: React.FC = props => { const {data: metrics, refetch} = useGetTestExecutionMetricsQuery( {id: name, last: 7, limit: 13}, - {skip: !isInViewport || !isSystemAvailable, pollingInterval: PollingIntervals.halfMin} + { + skip: !isInViewport || !isSystemAvailable, + pollingInterval: PollingIntervals.halfMin, + refetchOnMountOrArgChange: true, + } ); const executions: ExecutionMetrics[] = useMemo(() => metrics?.executions ?? [], [metrics]); diff --git a/packages/web/src/components/molecules/TestSuiteActionsDropdown/TestSuiteActionsDropdown.tsx b/packages/web/src/components/molecules/TestSuiteActionsDropdown/TestSuiteActionsDropdown.tsx index 7ef497335..88ec4b04e 100644 --- a/packages/web/src/components/molecules/TestSuiteActionsDropdown/TestSuiteActionsDropdown.tsx +++ b/packages/web/src/components/molecules/TestSuiteActionsDropdown/TestSuiteActionsDropdown.tsx @@ -39,7 +39,11 @@ const TestSuiteActionsDropdown: React.FC = props => { const {data: metrics, refetch} = useGetTestSuiteExecutionMetricsQuery( {id: name, last: 7, limit: 13}, - {skip: !isInViewport || !isSystemAvailable, pollingInterval: PollingIntervals.halfMin} + { + skip: !isInViewport || !isSystemAvailable, + pollingInterval: PollingIntervals.halfMin, + refetchOnMountOrArgChange: true, + } ); const executions: ExecutionMetrics[] = useMemo(() => metrics?.executions ?? [], [metrics]); diff --git a/packages/web/src/components/organisms/EntityDetails/EntityDetailsLayer.tsx b/packages/web/src/components/organisms/EntityDetails/EntityDetailsLayer.tsx index 5d72814cc..e5842e3f3 100644 --- a/packages/web/src/components/organisms/EntityDetails/EntityDetailsLayer.tsx +++ b/packages/web/src/components/organisms/EntityDetails/EntityDetailsLayer.tsx @@ -73,16 +73,18 @@ const EntityDetailsLayer: FC> = ({ { pollingInterval: PollingIntervals.long, skip: !isSystemAvailable || daysFilterValue === undefined, + refetchOnMountOrArgChange: true, } ); const {data: rawMetrics, refetch: refetchMetrics} = useGetMetrics( {id, last: daysFilterValue}, - {skip: !isSystemAvailable} + {skip: !isSystemAvailable, refetchOnMountOrArgChange: true} ); const {data: rawDetails, error} = useGetEntityDetails(id, { pollingInterval: PollingIntervals.long, skip: !isSystemAvailable, + refetchOnMountOrArgChange: true, }); const isV2 = isTestSuiteV2(rawDetails); diff --git a/packages/web/src/components/organisms/EntityDetails/ExecutionDetailsLayer.tsx b/packages/web/src/components/organisms/EntityDetails/ExecutionDetailsLayer.tsx index f421dfc2f..94c1f275a 100644 --- a/packages/web/src/components/organisms/EntityDetails/ExecutionDetailsLayer.tsx +++ b/packages/web/src/components/organisms/EntityDetails/ExecutionDetailsLayer.tsx @@ -55,6 +55,7 @@ const ExecutionDetailsLayer: FC> = const {data: rawFetchedData, error} = useGetExecutionDetails(execId!, { pollingInterval: PollingIntervals.everySecond, skip: !isClusterAvailable || !execId || (data?.id === execId && isExecutionFinished(data)), + refetchOnMountOrArgChange: true, }); const fetchedData = rawFetchedData?.id === execId ? rawFetchedData : null; const isV2 = isTestSuiteV2Execution(fetchedData); diff --git a/packages/web/src/components/organisms/EntityView/EntityViewFilters/LabelsFilter/LabelsFilters.tsx b/packages/web/src/components/organisms/EntityView/EntityViewFilters/LabelsFilter/LabelsFilters.tsx index bd78bd0a1..08d015dff 100644 --- a/packages/web/src/components/organisms/EntityView/EntityViewFilters/LabelsFilter/LabelsFilters.tsx +++ b/packages/web/src/components/organisms/EntityView/EntityViewFilters/LabelsFilter/LabelsFilters.tsx @@ -36,6 +36,7 @@ const LabelsFilter: React.FC = props => { const {data} = useGetLabelsQuery(null, { pollingInterval: PollingIntervals.default, skip: !isClusterAvailable, + refetchOnMountOrArgChange: true, }); const [isVisible, setIsVisible] = useState(false); diff --git a/packages/web/src/components/pages/TestSuites/TestSuitesList/TestSuiteCard.tsx b/packages/web/src/components/pages/TestSuites/TestSuitesList/TestSuiteCard.tsx index b04e9bd26..044eccbfe 100644 --- a/packages/web/src/components/pages/TestSuites/TestSuitesList/TestSuiteCard.tsx +++ b/packages/web/src/components/pages/TestSuites/TestSuitesList/TestSuiteCard.tsx @@ -26,7 +26,11 @@ const TestSuiteCard: FC = ({item: {testSuite, latestExecutio const {data: metrics} = useGetTestSuiteExecutionMetricsQuery( {id: testSuite.name, last: 7, limit: 13}, - {skip: !isInViewport || !isSystemAvailable, pollingInterval: PollingIntervals.halfMin} + { + skip: !isInViewport || !isSystemAvailable, + pollingInterval: PollingIntervals.halfMin, + refetchOnMountOrArgChange: true, + } ); return ( diff --git a/packages/web/src/components/pages/TestSuites/TestSuitesList/TestSuitesList.tsx b/packages/web/src/components/pages/TestSuites/TestSuitesList/TestSuitesList.tsx index 89f8f7ee8..c279c5945 100644 --- a/packages/web/src/components/pages/TestSuites/TestSuitesList/TestSuitesList.tsx +++ b/packages/web/src/components/pages/TestSuites/TestSuitesList/TestSuitesList.tsx @@ -44,6 +44,7 @@ const TestSuitesList: React.FC = () => { } = useGetTestSuitesQuery(filters || null, { pollingInterval: PollingIntervals.everySecond, skip: !isSystemAvailable, + refetchOnMountOrArgChange: true, }); useTestSuitesSync({testSuites}); diff --git a/packages/web/src/components/pages/Tests/TestDetails/TestExecution/TestExecutionArtifacts.tsx b/packages/web/src/components/pages/Tests/TestDetails/TestExecution/TestExecutionArtifacts.tsx index 697f2397a..7115edcb6 100644 --- a/packages/web/src/components/pages/Tests/TestDetails/TestExecution/TestExecutionArtifacts.tsx +++ b/packages/web/src/components/pages/Tests/TestDetails/TestExecution/TestExecutionArtifacts.tsx @@ -30,6 +30,7 @@ const TestExecutionArtifacts: React.FC = props => { const {data, isLoading, error} = useGetTestExecutionArtifactsQuery(id, { skip: !isSystemAvailable, pollingInterval: PollingIntervals.everyTwoSeconds, + refetchOnMountOrArgChange: true, }); useEffect(() => { diff --git a/packages/web/src/components/pages/Tests/TestsList/TestCard.tsx b/packages/web/src/components/pages/Tests/TestsList/TestCard.tsx index 703a34f66..dc48f0b0d 100644 --- a/packages/web/src/components/pages/Tests/TestsList/TestCard.tsx +++ b/packages/web/src/components/pages/Tests/TestsList/TestCard.tsx @@ -26,7 +26,11 @@ const TestCard: FC = ({item: {test, latestExecution}, onClick}) = const {data: metrics} = useGetTestExecutionMetricsQuery( {id: test.name, last: 7, limit: 13}, - {skip: !isInViewport || !isSystemAvailable, pollingInterval: PollingIntervals.halfMin} + { + skip: !isInViewport || !isSystemAvailable, + pollingInterval: PollingIntervals.halfMin, + refetchOnMountOrArgChange: true, + } ); return ( diff --git a/packages/web/src/components/pages/Tests/TestsList/TestsList.tsx b/packages/web/src/components/pages/Tests/TestsList/TestsList.tsx index c1333db2c..f76c1ddc9 100644 --- a/packages/web/src/components/pages/Tests/TestsList/TestsList.tsx +++ b/packages/web/src/components/pages/Tests/TestsList/TestsList.tsx @@ -51,6 +51,7 @@ const TestsList: React.FC = () => { } = useGetTestsQuery(filters, { pollingInterval: PollingIntervals.everySecond, skip: !isSystemAvailable, + refetchOnMountOrArgChange: true, }); useTestsSync({tests}); diff --git a/packages/web/src/components/pages/Webhooks/WebhooksList/WebhooksList.tsx b/packages/web/src/components/pages/Webhooks/WebhooksList/WebhooksList.tsx index 810601afa..642ea3546 100644 --- a/packages/web/src/components/pages/Webhooks/WebhooksList/WebhooksList.tsx +++ b/packages/web/src/components/pages/Webhooks/WebhooksList/WebhooksList.tsx @@ -36,7 +36,11 @@ const WebhooksList: FC = () => { data: webhooks, error, isLoading, - } = useGetWebhooksQuery(null, {pollingInterval: PollingIntervals.everyTwoSeconds, skip: !isClusterAvailable}); + } = useGetWebhooksQuery(null, { + pollingInterval: PollingIntervals.everyTwoSeconds, + skip: !isClusterAvailable, + refetchOnMountOrArgChange: true, + }); const mayCreate = usePermission(Permissions.createEntity); diff --git a/packages/web/src/plugins/cluster-status/plugin.tsx b/packages/web/src/plugins/cluster-status/plugin.tsx index 3c3d75fde..3a5ecb200 100644 --- a/packages/web/src/plugins/cluster-status/plugin.tsx +++ b/packages/web/src/plugins/cluster-status/plugin.tsx @@ -5,18 +5,16 @@ import {createPlugin, data, external} from '@testkube/plugins'; import {SystemAccess, useSystemAccess} from '@hooks/useSystemAccess'; import type GeneralPlugin from '@plugins/general/plugin'; -import type RtkPlugin from '@plugins/rtk/plugin'; +import RtkPlugin from '@plugins/rtk/plugin'; import {configApi, useGetClusterConfigQuery} from '@services/config'; import {safeRefetch} from '@utils/fetchUtils'; const generalStub = external(); -const rtkStub = external(); export default createPlugin('dashboard/cluster-status') .needs(generalStub.data('useApiEndpoint')) - .needs(rtkStub.slots('rtkServices')) .define(data()('isClusterAvailable', 'isSystemAvailable', 'isTelemetryEnabled')) @@ -38,6 +36,6 @@ export default createPlugin('dashboard/cluster-status') }, [apiEndpoint]); }) - .init(tk => { - tk.slots.rtkServices.add(configApi); - }); + .init(); + +RtkPlugin.overlay.appendContext({configApi}); diff --git a/packages/web/src/plugins/executors/plugin.tsx b/packages/web/src/plugins/executors/plugin.tsx index 833ac71a3..568af3d42 100644 --- a/packages/web/src/plugins/executors/plugin.tsx +++ b/packages/web/src/plugins/executors/plugin.tsx @@ -9,7 +9,7 @@ import ExecutorsList from '@pages/Executors/ExecutorsList/ExecutorsList'; import type ClusterStatusPlugin from '@plugins/cluster-status/plugin'; import type GeneralPlugin from '@plugins/general/plugin'; -import type RtkPlugin from '@plugins/rtk/plugin'; +import RtkPlugin from '@plugins/rtk/plugin'; import {executorsApi, useGetExecutorsQuery} from '@services/executors'; @@ -26,13 +26,11 @@ import {PollingIntervals} from '@utils/numbers'; const generalStub = external(); const clusterStatusStub = external(); -const rtkStub = external(); export default createPlugin('dashboard/executors') .needs(clusterStatusStub.data('useSystemAccess', 'SystemAccess')) .needs(generalStub.slots('siderItems')) .needs(generalStub.data('useApiEndpoint')) - .needs(rtkStub.slots('rtkServices')) .route('/executors', ) .route('/executors/:id', ) @@ -60,6 +58,7 @@ export default createPlugin('dashboard/executors') }) .init(tk => { - tk.slots.rtkServices.add(executorsApi); tk.slots.siderItems.add({path: '/executors', icon: ExecutorsIcon, title: 'Executors'}, {order: -80}); }); + +RtkPlugin.overlay.appendContext({executorsApi}); diff --git a/packages/web/src/plugins/labels/plugin.tsx b/packages/web/src/plugins/labels/plugin.tsx index 35cb00393..5d9200449 100644 --- a/packages/web/src/plugins/labels/plugin.tsx +++ b/packages/web/src/plugins/labels/plugin.tsx @@ -1,14 +1,9 @@ -import {createPlugin, external} from '@testkube/plugins'; +import {createPlugin} from '@testkube/plugins'; -import type RtkPlugin from '@plugins/rtk/plugin'; +import RtkPlugin from '@plugins/rtk/plugin'; import {labelsApi} from '@services/labels'; -const rtkStub = external(); +export default createPlugin('oss/labels').init(); -export default createPlugin('oss/labels') - .needs(rtkStub.slots('rtkServices')) - - .init(tk => { - tk.slots.rtkServices.add(labelsApi); - }); +RtkPlugin.overlay.appendContext({labelsApi}); diff --git a/packages/web/src/plugins/rtk-reset-on-api-change/hooks.ts b/packages/web/src/plugins/rtk-reset-on-api-change/hooks.ts deleted file mode 100644 index cd350e2bc..000000000 --- a/packages/web/src/plugins/rtk-reset-on-api-change/hooks.ts +++ /dev/null @@ -1,7 +0,0 @@ -import {createUseData, createUseSlot, createUseSlotFirst} from '@testkube/plugins'; - -import type plugin from './plugin'; - -export const useRtkResetOnApiChangePlugin = createUseData(); -export const useRtkResetOnApiChangeSlot = createUseSlot(); -export const useRtkResetOnApiChangeSlotFirst = createUseSlotFirst(); diff --git a/packages/web/src/plugins/rtk-reset-on-api-change/plugin.tsx b/packages/web/src/plugins/rtk-reset-on-api-change/plugin.tsx deleted file mode 100644 index 6d5b8fdf6..000000000 --- a/packages/web/src/plugins/rtk-reset-on-api-change/plugin.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import {useMemo} from 'react'; - -import {createPlugin, external} from '@testkube/plugins'; - -import type GeneralPlugin from '@plugins/general/plugin'; -import type RtkPlugin from '@plugins/rtk/plugin'; - -const generalStub = external(); -const rtkStub = external(); - -export default createPlugin('oss/rtk-reset-on-api-change') - .needs(generalStub.data('useApiEndpoint')) - .needs(rtkStub.data('resetRtkCache')) - - .provider(({useData}) => { - // Reset the in-memory API cache on API endpoint change - const {resetRtkCache, useApiEndpoint} = useData.pick('resetRtkCache', 'useApiEndpoint'); - useMemo(resetRtkCache, [useApiEndpoint()]); - }) - - .init(); diff --git a/packages/web/src/plugins/rtk/plugin.tsx b/packages/web/src/plugins/rtk/plugin.tsx index ee11db60c..499f4fcf2 100644 --- a/packages/web/src/plugins/rtk/plugin.tsx +++ b/packages/web/src/plugins/rtk/plugin.tsx @@ -1,9 +1,9 @@ -import {useMemo} from 'react'; +import {useRef} from 'react'; import {Provider as ReduxProvider} from 'react-redux'; -import {Store, configureStore} from '@reduxjs/toolkit'; +import {configureStore} from '@reduxjs/toolkit'; -import {createPlugin, data, slot} from '@testkube/plugins'; +import {createPlugin} from '@testkube/plugins'; export interface RtkService { reducerPath: string; @@ -13,37 +13,22 @@ export interface RtkService { } // TODO: Load base URL from the plugin instead of global scope -export default createPlugin('oss/rtk') - .order(-1) - - .define(slot()('rtkServices')) - .define(data()('rtkStore')) - .define(data<() => void>()('resetRtkCache')) - - .provider(({scope, useData, useSlot}) => { - const services = useSlot('rtkServices'); - scope.data.rtkStore = useMemo( - () => - configureStore({ - reducer: services.reduce((reducers, service) => ({...reducers, [service.reducerPath]: service.reducer}), {}), - middleware: getDefaultMiddleware => [ - ...getDefaultMiddleware(), - ...services.map(service => service.middleware), - ], - }), - [services] - ); - - return {type: ReduxProvider as any, props: {store: scope.data.rtkStore}}; - }) - - .init(tk => { - tk.data.resetRtkCache = () => { - tk.slots.rtkServices.all().forEach(service => { - const action = service.util?.resetApiState(); - if (action) { - tk.data.rtkStore?.dispatch(action); - } - }); - }; - }); +const rtkPlugin = createPlugin('oss/rtk').order(-1).init(); + +rtkPlugin.overlay.provider(() => { + const services = Object.values(rtkPlugin.overlay.getContext()) as RtkService[]; + + const store = useRef( + configureStore({ + reducer: services.reduce((reducers, service) => ({...reducers, [service.reducerPath]: service.reducer}), {}), + middleware: getDefaultMiddleware => [...getDefaultMiddleware(), ...services.map(service => service.middleware)], + }) + ); + + return { + type: ReduxProvider, + props: {store: store.current}, + }; +}); + +export default rtkPlugin; diff --git a/packages/web/src/plugins/test-sources/plugin.tsx b/packages/web/src/plugins/test-sources/plugin.tsx index 3e9d4abc8..15d7b88a6 100644 --- a/packages/web/src/plugins/test-sources/plugin.tsx +++ b/packages/web/src/plugins/test-sources/plugin.tsx @@ -9,7 +9,7 @@ import SourcesList from '@pages/Sources/SourcesList/SourcesList'; import type ClusterStatusPlugin from '@plugins/cluster-status/plugin'; import type GeneralPlugin from '@plugins/general/plugin'; -import type RtkPlugin from '@plugins/rtk/plugin'; +import RtkPlugin from '@plugins/rtk/plugin'; import {repositoryApi} from '@services/repository'; import {sourcesApi, useGetSourcesQuery} from '@services/sources'; @@ -21,13 +21,11 @@ import {PollingIntervals} from '@utils/numbers'; const generalStub = external(); const clusterStatusStub = external(); -const rtkStub = external(); export default createPlugin('oss/test-sources') .needs(clusterStatusStub.data('useSystemAccess', 'SystemAccess')) .needs(generalStub.slots('siderItems')) .needs(generalStub.data('useApiEndpoint')) - .needs(rtkStub.slots('rtkServices')) .route('/sources', ) .route('/sources/:id', ) @@ -55,8 +53,10 @@ export default createPlugin('oss/test-sources') }) .init(tk => { - tk.slots.rtkServices.add(sourcesApi); - tk.slots.rtkServices.add(repositoryApi); - tk.slots.siderItems.add({path: '/sources', icon: SourcesIcon, title: 'Sources'}, {order: -20}); }); + +RtkPlugin.overlay.appendContext({ + sourcesApi, + repositoryApi, +}); diff --git a/packages/web/src/plugins/tests-and-test-suites/plugin.tsx b/packages/web/src/plugins/tests-and-test-suites/plugin.tsx index 374c6def7..1537ba799 100644 --- a/packages/web/src/plugins/tests-and-test-suites/plugin.tsx +++ b/packages/web/src/plugins/tests-and-test-suites/plugin.tsx @@ -23,7 +23,7 @@ import TestsList from '@pages/Tests/TestsList'; import type ExecutorsPlugin from '@plugins/executors/plugin'; import type GeneralPlugin from '@plugins/general/plugin'; -import type RtkPlugin from '@plugins/rtk/plugin'; +import RtkPlugin from '@plugins/rtk/plugin'; import {testSuitesApi} from '@services/testSuites'; import {testsApi} from '@services/tests'; @@ -64,14 +64,12 @@ import {decomposeVariables} from '@utils/variables'; const generalStub = external(); const executorsStub = external(); -const rtkStub = external(); // TODO: Split export default createPlugin('oss/tests-and-test-suites') .needs(generalStub.slots('siderItems')) .needs(generalStub.data('useApiEndpoint')) .needs(executorsStub.data('useExecutors')) - .needs(rtkStub.slots('rtkServices')) // Backwards compatibility .route('/tests/executions/:id', ) @@ -142,9 +140,6 @@ export default createPlugin('oss/tests-and-test-suites') .data({useLogOutput, useLogOutputPick, useLogOutputField, useLogOutputSync}) .init(tk => { - tk.slots.rtkServices.add(testSuitesApi); - tk.slots.rtkServices.add(testsApi); - // TODO: Instead of using tk.sync, use all the necessities directly in the plugin components tk.data.setExecutionTab = tk.sync(() => { const entityId = tk.data.useEntityDetails(x => x.id); @@ -233,3 +228,8 @@ export default createPlugin('oss/tests-and-test-suites') {order: -60, enabled: () => Boolean(getDecomposedVars()?.length)} ); }); + +RtkPlugin.overlay.appendContext({ + testsApi, + testSuitesApi, +}); diff --git a/packages/web/src/plugins/triggers/plugin.tsx b/packages/web/src/plugins/triggers/plugin.tsx index d3da5e201..ce2525a4b 100644 --- a/packages/web/src/plugins/triggers/plugin.tsx +++ b/packages/web/src/plugins/triggers/plugin.tsx @@ -6,7 +6,7 @@ import TriggerDetails from '@pages/Triggers/TriggerDetails'; import TriggersList from '@pages/Triggers/TriggersList'; import type GeneralPlugin from '@plugins/general/plugin'; -import type RtkPlugin from '@plugins/rtk/plugin'; +import RtkPlugin from '@plugins/rtk/plugin'; import {triggersApi} from '@services/triggers'; @@ -19,12 +19,10 @@ import { } from '@store/triggers'; const generalStub = external(); -const rtkStub = external(); export default createPlugin('oss/triggers') .needs(generalStub.slots('siderItems')) .needs(generalStub.data('useApiEndpoint')) - .needs(rtkStub.slots('rtkServices')) .route('/triggers', ) .route('/triggers/:id', ) @@ -36,6 +34,9 @@ export default createPlugin('oss/triggers') .data({useTriggers, useTriggersPick, useTriggersField, useTriggersSync}) .init(tk => { - tk.slots.rtkServices.add(triggersApi); tk.slots.siderItems.add({path: '/triggers', icon: TriggersIcon, title: 'Triggers'}, {order: -60}); }); + +RtkPlugin.overlay.appendContext({ + triggersApi, +}); diff --git a/packages/web/src/plugins/webhooks/plugin.tsx b/packages/web/src/plugins/webhooks/plugin.tsx index 397dd8536..ee5ffea86 100644 --- a/packages/web/src/plugins/webhooks/plugin.tsx +++ b/packages/web/src/plugins/webhooks/plugin.tsx @@ -6,7 +6,7 @@ import WebhookDetails from '@pages/Webhooks/WebhookDetails/WebhookDetails'; import WebhooksList from '@pages/Webhooks/WebhooksList'; import type GeneralPlugin from '@plugins/general/plugin'; -import type RtkPlugin from '@plugins/rtk/plugin'; +import RtkPlugin from '@plugins/rtk/plugin'; import {webhooksApi} from '@services/webhooks'; @@ -19,12 +19,10 @@ import { } from '@store/webhooks'; const generalStub = external(); -const rtkStub = external(); export default createPlugin('oss/webhooks') .needs(generalStub.slots('siderItems')) .needs(generalStub.data('useApiEndpoint')) - .needs(rtkStub.slots('rtkServices')) .route('/webhooks', ) .route('/webhooks/:id', ) @@ -37,7 +35,9 @@ export default createPlugin('oss/webhooks') .data({useWebhooks, useWebhooksPick, useWebhooksField, useWebhooksSync}) .init(tk => { - tk.slots.rtkServices.add(webhooksApi); - tk.slots.siderItems.add({path: '/webhooks', icon: WebhooksIcon, title: 'Webhooks'}, {order: -40}); }); + +RtkPlugin.overlay.appendContext({ + webhooksApi, +});