mirror of
https://github.com/portainer/portainer.git
synced 2025-08-09 15:55:23 +02:00
refactor(edge/stacks): migrate create view to react [EE-2223] (#11575)
Some checks are pending
ci / build_images (map[arch:amd64 platform:linux version:]) (push) Waiting to run
ci / build_images (map[arch:amd64 platform:windows version:1809]) (push) Waiting to run
ci / build_images (map[arch:amd64 platform:windows version:ltsc2022]) (push) Waiting to run
ci / build_images (map[arch:arm platform:linux version:]) (push) Waiting to run
ci / build_images (map[arch:arm64 platform:linux version:]) (push) Waiting to run
ci / build_images (map[arch:ppc64le platform:linux version:]) (push) Waiting to run
ci / build_images (map[arch:s390x platform:linux version:]) (push) Waiting to run
ci / build_manifests (push) Blocked by required conditions
/ triage (push) Waiting to run
Lint / Run linters (push) Waiting to run
Test / test-client (push) Waiting to run
Test / test-server (map[arch:amd64 platform:linux]) (push) Waiting to run
Test / test-server (map[arch:amd64 platform:windows version:1809]) (push) Waiting to run
Test / test-server (map[arch:amd64 platform:windows version:ltsc2022]) (push) Waiting to run
Test / test-server (map[arch:arm64 platform:linux]) (push) Waiting to run
Some checks are pending
ci / build_images (map[arch:amd64 platform:linux version:]) (push) Waiting to run
ci / build_images (map[arch:amd64 platform:windows version:1809]) (push) Waiting to run
ci / build_images (map[arch:amd64 platform:windows version:ltsc2022]) (push) Waiting to run
ci / build_images (map[arch:arm platform:linux version:]) (push) Waiting to run
ci / build_images (map[arch:arm64 platform:linux version:]) (push) Waiting to run
ci / build_images (map[arch:ppc64le platform:linux version:]) (push) Waiting to run
ci / build_images (map[arch:s390x platform:linux version:]) (push) Waiting to run
ci / build_manifests (push) Blocked by required conditions
/ triage (push) Waiting to run
Lint / Run linters (push) Waiting to run
Test / test-client (push) Waiting to run
Test / test-server (map[arch:amd64 platform:linux]) (push) Waiting to run
Test / test-server (map[arch:amd64 platform:windows version:1809]) (push) Waiting to run
Test / test-server (map[arch:amd64 platform:windows version:ltsc2022]) (push) Waiting to run
Test / test-server (map[arch:arm64 platform:linux]) (push) Waiting to run
This commit is contained in:
parent
f22aed34b5
commit
8a81d95253
64 changed files with 1878 additions and 1005 deletions
|
@ -2,7 +2,7 @@ import { useQueryClient, useMutation } from '@tanstack/react-query';
|
|||
|
||||
import axios, { parseAxiosError } from '@/portainer/services/axios';
|
||||
import { notifyError, notifySuccess } from '@/portainer/services/notifications';
|
||||
import { GitAuthModel, GitFormModel } from '@/react/portainer/gitops/types';
|
||||
import { GitAuthModel } from '@/react/portainer/gitops/types';
|
||||
import { useCurrentUser } from '@/react/hooks/useUser';
|
||||
import { UserId } from '@/portainer/users/types';
|
||||
|
||||
|
@ -82,9 +82,9 @@ export function useSaveCredentialsIfRequired() {
|
|||
}
|
||||
}
|
||||
|
||||
export async function saveGitCredentialsIfNeeded(
|
||||
export async function saveGitCredentialsIfNeeded<TGit extends GitAuthModel>(
|
||||
userId: UserId,
|
||||
gitModel: GitFormModel
|
||||
gitModel: TGit
|
||||
) {
|
||||
let credentialsId = gitModel.RepositoryGitCredentialID;
|
||||
let username = gitModel.RepositoryUsername;
|
||||
|
|
|
@ -2,7 +2,9 @@ import { VariableDefinition } from '../CustomTemplatesVariablesDefinitionField';
|
|||
|
||||
import { Values } from './CustomTemplatesVariablesField';
|
||||
|
||||
export function getDefaultValues(definitions: VariableDefinition[]): Values {
|
||||
export function getDefaultValues(
|
||||
definitions: VariableDefinition[] | undefined = []
|
||||
): Values {
|
||||
return definitions.map((v) => ({
|
||||
key: v.name,
|
||||
value: v.defaultValue,
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
import { useCallback } from 'react';
|
||||
import { FormikErrors } from 'formik';
|
||||
|
||||
import { GitFormModel } from '@/react/portainer/gitops/types';
|
||||
import { PathSelector } from '@/react/portainer/gitops/ComposePathField/PathSelector';
|
||||
import { dummyGitForm } from '@/react/portainer/gitops/RelativePathFieldset/utils';
|
||||
import { useValidation } from '@/react/portainer/gitops/RelativePathFieldset/useValidation';
|
||||
import { useEnableFsPath } from '@/react/portainer/gitops/RelativePathFieldset/useEnableFsPath';
|
||||
|
||||
import { SwitchField } from '@@/form-components/SwitchField';
|
||||
|
@ -15,27 +14,22 @@ import { useDocsUrl } from '@@/PageHeader/ContextHelp/ContextHelp';
|
|||
import { RelativePathModel, getPerDevConfigsFilterType } from './types';
|
||||
|
||||
interface Props {
|
||||
value: RelativePathModel;
|
||||
values: RelativePathModel;
|
||||
gitModel?: GitFormModel;
|
||||
onChange?: (value: Partial<RelativePathModel>) => void;
|
||||
onChange: (value: RelativePathModel) => void;
|
||||
isEditing?: boolean;
|
||||
hideEdgeConfigs?: boolean;
|
||||
errors?: FormikErrors<RelativePathModel>;
|
||||
}
|
||||
|
||||
export function RelativePathFieldset({
|
||||
value,
|
||||
values: value,
|
||||
gitModel,
|
||||
onChange,
|
||||
onChange = () => {},
|
||||
isEditing,
|
||||
hideEdgeConfigs,
|
||||
errors,
|
||||
}: Props) {
|
||||
const innerOnChange = useCallback(
|
||||
(value: Partial<RelativePathModel>) => onChange && onChange(value),
|
||||
[onChange]
|
||||
);
|
||||
|
||||
const { errors } = useValidation(value);
|
||||
|
||||
const { enableFsPath0, enableFsPath1, toggleFsPath } = useEnableFsPath(value);
|
||||
|
||||
const gitoptsEdgeConfigDocUrl = useDocsUrl(
|
||||
|
@ -63,7 +57,7 @@ export function RelativePathFieldset({
|
|||
checked={value.SupportRelativePath}
|
||||
onChange={(value) => {
|
||||
toggleFsPath(0, value);
|
||||
innerOnChange({ SupportRelativePath: value });
|
||||
handleChange({ SupportRelativePath: value });
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
@ -83,7 +77,7 @@ export function RelativePathFieldset({
|
|||
<div className="col-sm-12">
|
||||
<FormControl
|
||||
label="Local filesystem path"
|
||||
errors={errors.FilesystemPath}
|
||||
errors={errors?.FilesystemPath}
|
||||
>
|
||||
<Input
|
||||
name="FilesystemPath"
|
||||
|
@ -92,7 +86,7 @@ export function RelativePathFieldset({
|
|||
disabled={isEditing || !enableFsPath0}
|
||||
value={value.FilesystemPath}
|
||||
onChange={(e) =>
|
||||
innerOnChange({ FilesystemPath: e.target.value })
|
||||
handleChange({ FilesystemPath: e.target.value })
|
||||
}
|
||||
/>
|
||||
</FormControl>
|
||||
|
@ -124,7 +118,7 @@ export function RelativePathFieldset({
|
|||
checked={!!value.SupportPerDeviceConfigs}
|
||||
onChange={(value) => {
|
||||
toggleFsPath(1, value);
|
||||
innerOnChange({ SupportPerDeviceConfigs: value });
|
||||
handleChange({ SupportPerDeviceConfigs: value });
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
@ -147,7 +141,7 @@ export function RelativePathFieldset({
|
|||
<div className="col-sm-12">
|
||||
<FormControl
|
||||
label="Local filesystem path"
|
||||
errors={errors.FilesystemPath}
|
||||
errors={errors?.FilesystemPath}
|
||||
>
|
||||
<Input
|
||||
name="FilesystemPath"
|
||||
|
@ -156,7 +150,7 @@ export function RelativePathFieldset({
|
|||
disabled={isEditing || !enableFsPath1}
|
||||
value={value.FilesystemPath}
|
||||
onChange={(e) =>
|
||||
innerOnChange({ FilesystemPath: e.target.value })
|
||||
handleChange({ FilesystemPath: e.target.value })
|
||||
}
|
||||
/>
|
||||
</FormControl>
|
||||
|
@ -178,13 +172,13 @@ export function RelativePathFieldset({
|
|||
<div className="col-sm-12">
|
||||
<FormControl
|
||||
label="Directory"
|
||||
errors={errors.PerDeviceConfigsPath}
|
||||
errors={errors?.PerDeviceConfigsPath}
|
||||
inputId="per_device_configs_path_input"
|
||||
>
|
||||
<PathSelector
|
||||
value={value.PerDeviceConfigsPath || ''}
|
||||
onChange={(value) =>
|
||||
innerOnChange({ PerDeviceConfigsPath: value })
|
||||
handleChange({ PerDeviceConfigsPath: value })
|
||||
}
|
||||
placeholder="config"
|
||||
model={gitModel || dummyGitForm}
|
||||
|
@ -216,7 +210,7 @@ export function RelativePathFieldset({
|
|||
value={value.PerDeviceConfigsMatchType}
|
||||
data-cy="per-device-configs-match-type-select"
|
||||
onChange={(e) =>
|
||||
innerOnChange({
|
||||
handleChange({
|
||||
PerDeviceConfigsMatchType: getPerDevConfigsFilterType(
|
||||
e.target.value
|
||||
),
|
||||
|
@ -249,7 +243,7 @@ export function RelativePathFieldset({
|
|||
value={value.PerDeviceConfigsGroupMatchType}
|
||||
data-cy="per-device-configs-group-match-type-select"
|
||||
onChange={(e) =>
|
||||
innerOnChange({
|
||||
handleChange({
|
||||
PerDeviceConfigsGroupMatchType:
|
||||
getPerDevConfigsFilterType(e.target.value),
|
||||
})
|
||||
|
@ -301,4 +295,8 @@ export function RelativePathFieldset({
|
|||
)}
|
||||
</>
|
||||
);
|
||||
|
||||
function handleChange(newValue: Partial<RelativePathModel>) {
|
||||
onChange({ ...value, ...newValue });
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
import { useEffect, useState } from 'react';
|
||||
import { FormikErrors, yupToFormErrors } from 'formik';
|
||||
|
||||
import { RelativePathModel } from '@/react/portainer/gitops/types';
|
||||
import { relativePathValidation } from '@/react/portainer/gitops/RelativePathFieldset/validation';
|
||||
|
||||
export function useValidation(value: RelativePathModel) {
|
||||
const [errors, setErrors] = useState<FormikErrors<RelativePathModel>>({});
|
||||
|
||||
useEffect(() => {
|
||||
async function valide() {
|
||||
try {
|
||||
await relativePathValidation().validate(value, {
|
||||
strict: true,
|
||||
abortEarly: false,
|
||||
});
|
||||
setErrors({});
|
||||
} catch (error) {
|
||||
setErrors(yupToFormErrors(error));
|
||||
}
|
||||
}
|
||||
|
||||
valide();
|
||||
}, [value]);
|
||||
|
||||
return { errors };
|
||||
}
|
|
@ -1,22 +1,20 @@
|
|||
import angular from 'angular';
|
||||
|
||||
import { r2a } from '@/react-tools/react2angular';
|
||||
import { withUIRouter } from '@/react-tools/withUIRouter';
|
||||
import { withReactQuery } from '@/react-tools/withReactQuery';
|
||||
import { RelativePathFieldset } from '@/react/portainer/gitops/RelativePathFieldset/RelativePathFieldset';
|
||||
import { withFormValidation } from '@/react-tools/withFormValidation';
|
||||
|
||||
export const ngModule = angular
|
||||
.module('portainer.app.react.gitops', [])
|
||||
import { relativePathValidation } from './RelativePathFieldset/validation';
|
||||
|
||||
.component(
|
||||
'relativePathFieldset',
|
||||
r2a(withUIRouter(withReactQuery(RelativePathFieldset)), [
|
||||
'value',
|
||||
'gitModel',
|
||||
'onChange',
|
||||
'isEditing',
|
||||
'hideEdgeConfigs',
|
||||
])
|
||||
);
|
||||
export const ngModule = angular.module('portainer.app.react.gitops', []);
|
||||
|
||||
withFormValidation(
|
||||
ngModule,
|
||||
withUIRouter(withReactQuery(RelativePathFieldset)),
|
||||
'relativePathFieldset',
|
||||
['gitModel', 'hideEdgeConfigs', 'isEditing', 'onChange'],
|
||||
relativePathValidation
|
||||
);
|
||||
|
||||
export const gitopsModule = ngModule.name;
|
||||
|
|
|
@ -59,8 +59,6 @@ export interface GitFormModel extends GitAuthModel {
|
|||
RepositoryReferenceName?: string;
|
||||
AdditionalFiles?: string[];
|
||||
|
||||
SaveCredential?: boolean;
|
||||
NewCredentialName?: string;
|
||||
TLSSkipVerify?: boolean;
|
||||
|
||||
/**
|
||||
|
|
|
@ -78,6 +78,7 @@ export function useGenericRegistriesQuery<T = Registry[]>(
|
|||
export async function getRegistries() {
|
||||
try {
|
||||
const { data } = await axios.get<Registry[]>('/registries');
|
||||
|
||||
return data;
|
||||
} catch (e) {
|
||||
throw parseAxiosError(e as Error, 'Unable to retrieve registries');
|
||||
|
|
|
@ -12,19 +12,38 @@ import { buildUrl } from './build-url';
|
|||
|
||||
export function useAppTemplates<T = Array<TemplateViewModel>>({
|
||||
select,
|
||||
}: { select?: (templates: Array<TemplateViewModel>) => T } = {}) {
|
||||
const registriesQuery = useRegistries();
|
||||
enabled = true,
|
||||
}: {
|
||||
select?: (templates: Array<TemplateViewModel>) => T;
|
||||
enabled?: boolean;
|
||||
} = {}) {
|
||||
const registriesQuery = useRegistries({ enabled });
|
||||
|
||||
return useQuery(
|
||||
['templates'],
|
||||
() => getTemplatesWithRegistry(registriesQuery.data),
|
||||
{
|
||||
enabled: !!registriesQuery.data,
|
||||
enabled: !!registriesQuery.data && enabled,
|
||||
select,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
export function useAppTemplate(
|
||||
id: AppTemplate['id'] | undefined,
|
||||
{ enabled = true }: { enabled?: boolean } = {}
|
||||
) {
|
||||
const templateListQuery = useAppTemplates({ enabled: !!id && enabled });
|
||||
|
||||
const template = templateListQuery.data?.find((t) => t.Id === id);
|
||||
|
||||
return {
|
||||
data: template,
|
||||
isLoading: templateListQuery.isLoading,
|
||||
error: templateListQuery.error,
|
||||
};
|
||||
}
|
||||
|
||||
async function getTemplatesWithRegistry(
|
||||
registries: Array<Registry> | undefined
|
||||
) {
|
||||
|
|
|
@ -34,7 +34,7 @@ export function EdgeSettingsFieldset({
|
|||
{isGit && (
|
||||
<FormSection title="Advanced settings">
|
||||
<RelativePathFieldset
|
||||
value={values.RelativePathSettings}
|
||||
values={values.RelativePathSettings}
|
||||
gitModel={gitConfig}
|
||||
onChange={(newValues) =>
|
||||
setValues((values) => ({
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { SchemaOf, boolean, mixed, number, object } from 'yup';
|
||||
|
||||
import { staggerConfigValidation } from '@/react/edge/edge-stacks/components/StaggerFieldset';
|
||||
import { relativePathValidation } from '@/react/portainer/gitops/RelativePathFieldset/validation';
|
||||
import { EdgeTemplateSettings } from '@/react/portainer/templates/custom-templates/types';
|
||||
import { isBE } from '@/react/portainer/feature-flags/feature-flags.service';
|
||||
|
@ -14,6 +15,6 @@ export function edgeFieldsetValidation(): SchemaOf<EdgeTemplateSettings> {
|
|||
PrePullImage: boolean().default(false),
|
||||
RetryDeploy: boolean().default(false),
|
||||
PrivateRegistryId: number().default(undefined),
|
||||
StaggerConfig: mixed(),
|
||||
StaggerConfig: staggerConfigValidation(),
|
||||
});
|
||||
}
|
||||
|
|
|
@ -160,7 +160,7 @@ export function InnerForm({
|
|||
...values,
|
||||
EdgeSettings: applySetStateAction(
|
||||
edgeSetValues,
|
||||
values.EdgeSettings
|
||||
values.EdgeSettings!
|
||||
),
|
||||
}))
|
||||
}
|
||||
|
|
|
@ -167,7 +167,7 @@ export function InnerForm({
|
|||
setValues={(edgeValues) =>
|
||||
setFieldValue(
|
||||
'EdgeSettings',
|
||||
applySetStateAction(edgeValues, values.EdgeSettings)
|
||||
applySetStateAction(edgeValues, values.EdgeSettings!)
|
||||
)
|
||||
}
|
||||
gitConfig={values.Git}
|
||||
|
|
|
@ -17,9 +17,12 @@ export async function getCustomTemplate(id: CustomTemplate['Id']) {
|
|||
}
|
||||
}
|
||||
|
||||
export function useCustomTemplate(id?: CustomTemplate['Id']) {
|
||||
export function useCustomTemplate(
|
||||
id?: CustomTemplate['Id'],
|
||||
{ enabled = true }: { enabled?: boolean } = {}
|
||||
) {
|
||||
return useQuery(queryKeys.item(id!), () => getCustomTemplate(id!), {
|
||||
...withGlobalError('Unable to retrieve custom template'),
|
||||
enabled: !!id,
|
||||
enabled: !!id && enabled,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
import { UserId } from '@/portainer/users/types';
|
||||
import { StackType } from '@/react/common/stacks/types';
|
||||
import {
|
||||
StaggerConfig,
|
||||
getDefaultStaggerConfig,
|
||||
} from '@/react/edge/edge-stacks/components/StaggerFieldset.types';
|
||||
|
||||
import { ResourceControlResponse } from '../../access-control/types';
|
||||
import { RelativePathModel, RepoConfigResponse } from '../../gitops/types';
|
||||
|
@ -105,6 +109,12 @@ export type EdgeTemplateSettings = {
|
|||
PrivateRegistryId: RegistryId | undefined;
|
||||
|
||||
RelativePathSettings: RelativePathModel;
|
||||
|
||||
/**
|
||||
* StaggerConfig is the configuration for staggered update
|
||||
* required only on BE
|
||||
*/
|
||||
StaggerConfig: StaggerConfig;
|
||||
};
|
||||
|
||||
export type CustomTemplateFileContent = {
|
||||
|
@ -113,7 +123,9 @@ export type CustomTemplateFileContent = {
|
|||
|
||||
export const CustomTemplateKubernetesType = StackType.Kubernetes;
|
||||
|
||||
export function getDefaultEdgeTemplateSettings() {
|
||||
export function getDefaultEdgeTemplateSettings():
|
||||
| EdgeTemplateSettings
|
||||
| undefined {
|
||||
if (!isBE) {
|
||||
return undefined;
|
||||
}
|
||||
|
@ -123,5 +135,6 @@ export function getDefaultEdgeTemplateSettings() {
|
|||
RetryDeploy: false,
|
||||
PrivateRegistryId: undefined,
|
||||
RelativePathSettings: getDefaultRelativePathModel(),
|
||||
StaggerConfig: getDefaultStaggerConfig(),
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue