Skip to content

Commit

Permalink
Merge pull request #1022 from kubeshop/release/v1.16.7
Browse files Browse the repository at this point in the history
Release/v1.16.7
  • Loading branch information
topliceanurazvan authored Feb 26, 2024
2 parents f0fda90 + 5c89bc1 commit 41cab48
Show file tree
Hide file tree
Showing 33 changed files with 201 additions and 136 deletions.
1 change: 1 addition & 0 deletions packages/plugins/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
3 changes: 3 additions & 0 deletions packages/plugins/src/internal/Plugin.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -7,6 +8,8 @@ export class Plugin<T extends PluginState> {
public readonly [PluginInit]: (context: PluginScope<PluginScopeStateFor<T>>, config: T['config']) => void;
public readonly [PluginDetailsSymbol]: PluginDetails<T>;

public readonly overlay = new PluginOverlay();

public constructor(
config: PluginDetails<T>,
initFn: (tk: PluginScope<PluginScopeStateFor<T>>, config: PluginConfig<T['config']>) => void
Expand Down
32 changes: 32 additions & 0 deletions packages/plugins/src/internal/PluginOverlay.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import {PluginOverlayContext} from './symbols';
import {PluginProvider} from './types';

export class PluginOverlay {
private [PluginOverlayContext]: Record<string, any> = {};
private providerCreator: (() => PluginProvider<any>) | null = null;

public getContext() {
return this[PluginOverlayContext];
}

public setContext(context: Record<string, any> | ((oldContext: Record<string, any>) => Record<string, any>)) {
if (typeof context === 'function') {
this[PluginOverlayContext] = context(this[PluginOverlayContext]);
return;
}
this[PluginOverlayContext] = context;
}

public appendContext(context: Record<string, any>) {
this[PluginOverlayContext] = {...this[PluginOverlayContext], ...context};
}

public useProvider() {
if (!this.providerCreator) return null;
return this.providerCreator();
}

public provider(pc: typeof this.providerCreator) {
this.providerCreator = pc;
}
}
1 change: 1 addition & 0 deletions packages/plugins/src/internal/symbols.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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');
29 changes: 29 additions & 0 deletions packages/plugins/src/usePluginOverlay.ts
Original file line number Diff line number Diff line change
@@ -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<any>[]) => {
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<FC<PropsWithChildren<any>>>(
({children}) =>
createProviderTree(
plugins.filter((plugin): plugin is Plugin<any> => 'overlay' in plugin).map(plugin => plugin.overlay),
children
),
[createProviderTree]
);

return ProviderComponent;
};
32 changes: 17 additions & 15 deletions packages/web/src/AppRoot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand All @@ -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';
Expand All @@ -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: <Logo />}),
Expand All @@ -67,6 +65,8 @@ const AppRoot: React.FC = () => {
);
const [PluginProvider, {routes}] = usePluginSystem(plugins);

const PluginOverlayProvider = usePluginOverlay(plugins);

return (
<ErrorBoundary>
<TelemetryProvider
Expand All @@ -76,18 +76,20 @@ const AppRoot: React.FC = () => {
debug={env.debugTelemetry}
paused
>
<PluginProvider>
<Layout>
<Sider />
<StyledLayoutContentWrapper>
<Content>
<ErrorBoundary>
<App routes={routes} />
</ErrorBoundary>
</Content>
</StyledLayoutContentWrapper>
</Layout>
</PluginProvider>
<PluginOverlayProvider>
<PluginProvider>
<Layout>
<Sider />
<StyledLayoutContentWrapper>
<Content>
<ErrorBoundary>
<App routes={routes} />
</ErrorBoundary>
</Content>
</StyledLayoutContentWrapper>
</Layout>
</PluginProvider>
</PluginOverlayProvider>
</TelemetryProvider>
</ErrorBoundary>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ const LabelsSelect: React.FC<LabelsSelectProps> = 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]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,11 @@ const TestActionsDropdown: React.FC<ActionsDropdownProps> = 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]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,11 @@ const TestSuiteActionsDropdown: React.FC<ActionsDropdownProps> = 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]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,16 +73,18 @@ const EntityDetailsLayer: FC<PropsWithChildren<EntityDetailsLayerProps>> = ({
{
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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ const ExecutionDetailsLayer: FC<PropsWithChildren<ExecutionDetailsLayerProps>> =
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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ const LabelsFilter: React.FC<EntityFilters> = props => {
const {data} = useGetLabelsQuery(null, {
pollingInterval: PollingIntervals.default,
skip: !isClusterAvailable,
refetchOnMountOrArgChange: true,
});

const [isVisible, setIsVisible] = useState(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import {Branch, Path, Repository, SecretFormItem} from '@molecules';

import {useValidateRepositoryMutation} from '@services/repository';

import {useClusterDetailsPick} from '@store/clusterDetails';

import {StyledFormSpace} from '../TestConfigurationForm.styled';
import {Props} from '../utils';

Expand All @@ -16,17 +18,26 @@ const GitFormFields: React.FC<Partial<Props>> = props => {

const [validateRepository] = useValidateRepositoryMutation();

const {disableSecretCreation} = useClusterDetailsPick('disableSecretCreation');

useValidateRepository(getFieldValue, setValidationState, validateRepository);

return (
<StyledFormSpace size={24} direction="vertical">
<Repository message={validationState.message} status={validationState.uri} />
<SecretFormItem message={validationState.message} status={validationState.token} name="token" label="Git Token" />
<SecretFormItem
message={validationState.message}
status={validationState.token}
name="token"
label="Git Token"
disabled={disableSecretCreation}
/>
<SecretFormItem
message={validationState.message}
status={validationState.username}
name="username"
label="Git Username"
disabled={disableSecretCreation}
/>
<Branch message={validationState.message} status={validationState.branch} />
<Path testType={executorType} message={validationState.message} status={validationState.path} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import {Path, Repository, Revision, SecretFormItem} from '@molecules';

import {useValidateRepositoryMutation} from '@services/repository';

import {useClusterDetailsPick} from '@store/clusterDetails';

import {StyledFormSpace} from '../TestConfigurationForm.styled';
import {Props} from '../utils';

Expand All @@ -24,6 +26,8 @@ const SourceEdit: React.FC<Partial<Props>> = props => {
message: '',
});

const {disableSecretCreation} = useClusterDetailsPick('disableSecretCreation');

const [validateRepository] = useValidateRepositoryMutation();

useValidateRepository(getFieldValue, setValidationState, validateRepository);
Expand All @@ -38,7 +42,7 @@ const SourceEdit: React.FC<Partial<Props>> = props => {
setIsClearedValue={setIsClearedToken}
message={validationState.message}
status={validationState.token}
disabled={disabled}
disabled={disabled || disableSecretCreation}
/>
<SecretFormItem
name="username"
Expand All @@ -47,7 +51,7 @@ const SourceEdit: React.FC<Partial<Props>> = props => {
setIsClearedValue={setIsClearedUsername}
message={validationState.message}
status={validationState.username}
disabled={disabled}
disabled={disabled || disableSecretCreation}
/>
<Revision
message={validationState.message}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {Permissions, usePermission} from '@permissions/base';

import {useUpdateSourceMutation} from '@services/sources';

import {useClusterDetailsPick} from '@store/clusterDetails';
import {useSourcesPick} from '@store/sources';

import {displayDefaultNotificationFlow} from '@utils/notification';
Expand All @@ -28,6 +29,7 @@ const Authentication: React.FC = () => {
const [form] = Form.useForm<AuthenticationFormValues>();

const {current} = useSourcesPick('current');
const {disableSecretCreation} = useClusterDetailsPick('disableSecretCreation');

const [updateSource] = useUpdateSourceMutation();

Expand Down Expand Up @@ -77,20 +79,20 @@ const Authentication: React.FC = () => {
spacing={24}
form={form}
initialValues={defaults}
disabled={!mayEdit}
disabled={!mayEdit || disableSecretCreation}
wasTouched={Boolean((tokenSecret && isClearedToken) || (usernameSecret && isClearedUsername))}
onConfirm={onFinish}
onCancel={onCancel}
>
<SecretFormItem
name="username"
label="Git username"
label="Git Username"
isClearedValue={isClearedUsername}
setIsClearedValue={setIsClearedUsername}
/>
<SecretFormItem
name="token"
label="Git token"
label="Git Token"
isClearedValue={isClearedToken}
setIsClearedValue={setIsClearedToken}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ type AddSourceFormValues = {
};

const AddSourceModal: React.FC = () => {
const {namespace} = useClusterDetailsPick('namespace');
const {disableSecretCreation, namespace} = useClusterDetailsPick('disableSecretCreation', 'namespace');
const [form] = Form.useForm<AddSourceFormValues>();
const openDetails = useDashboardNavigate((name: string) => `/sources/${name}`);
const {close} = useModal();
Expand Down Expand Up @@ -94,13 +94,14 @@ const AddSourceModal: React.FC = () => {
<Form.Item label="Git repository URL" required name="uri" rules={[required]}>
<Input placeholder="e.g.: https://github.com/myCompany/myRepo.git" />
</Form.Item>
<Form.Item label="Git username" name="username">
<Input placeholder="e.g.: my-user-name" />
<Form.Item label="Git Username" name="username">
<Input placeholder="e.g.: my-user-name" disabled={disableSecretCreation} />
</Form.Item>
<Form.Item label="Git token" name="token">
<Form.Item label="Git Token" name="token">
<AntdInput.Password
placeholder="e.g.: some-token"
iconRender={visible => (visible ? <EyeOutlined /> : <EyeInvisibleOutlined />)}
disabled={disableSecretCreation}
/>
</Form.Item>
<Form.Item
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,11 @@ const TestSuiteCard: FC<TestSuiteCardProps> = ({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 (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ const TestSuitesList: React.FC = () => {
} = useGetTestSuitesQuery(filters || null, {
pollingInterval: PollingIntervals.everySecond,
skip: !isSystemAvailable,
refetchOnMountOrArgChange: true,
});
useTestSuitesSync({testSuites});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const TestExecutionArtifacts: React.FC<TestExecutionArtifactsProps> = props => {
const {data, isLoading, error} = useGetTestExecutionArtifactsQuery(id, {
skip: !isSystemAvailable,
pollingInterval: PollingIntervals.everyTwoSeconds,
refetchOnMountOrArgChange: true,
});

useEffect(() => {
Expand Down
Loading

0 comments on commit 41cab48

Please sign in to comment.