mirror of https://github.com/portainer/portainer
refactor(custom-templates): migrate common-fields to react [EE-6207] (#10445)
parent
1ad9488ca7
commit
6b5c24faff
@ -1,87 +0,0 @@
|
||||
<ng-form name="commonCustomTemplateForm">
|
||||
<!-- title-input -->
|
||||
<div class="form-group mb-0">
|
||||
<label for="template_title" class="col-sm-3 col-lg-2 control-label required text-left"> Title </label>
|
||||
<div class="col-sm-8">
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
ng-model="$ctrl.formValues.Title"
|
||||
ng-pattern="$ctrl.nameRegex"
|
||||
id="template_title"
|
||||
name="template_title"
|
||||
placeholder="e.g. mytemplate"
|
||||
auto-focus
|
||||
required
|
||||
/>
|
||||
<span class="help-block">
|
||||
<div ng-show="commonCustomTemplateForm.template_title.$invalid">
|
||||
<div class="small text-warning mt-2">
|
||||
<div ng-messages="commonCustomTemplateForm.template_title.$error">
|
||||
<p class="vertical-center" ng-message="required"> <pr-icon icon="'alert-triangle'" mode="'warning'"></pr-icon> Title is required. </p>
|
||||
<p class="vertical-center" ng-message="pattern">
|
||||
<pr-icon icon="'alert-triangle'" mode="'warning'"></pr-icon>
|
||||
{{ $ctrl.nameRegexError }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- !title-input -->
|
||||
|
||||
<!-- description-input -->
|
||||
<div class="form-group mb-0">
|
||||
<label for="description" class="col-sm-3 col-lg-2 control-label required text-left">Description</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="text" class="form-control" id="description" ng-model="$ctrl.formValues.Description" name="description" required />
|
||||
<span class="help-block">
|
||||
<div class="small text-warning mt-2">
|
||||
<div ng-show="commonCustomTemplateForm.description.$invalid">
|
||||
<div ng-messages="commonCustomTemplateForm.description.$error">
|
||||
<p class="vertical-center" ng-message="required"> <pr-icon icon="'alert-triangle'" mode="'warning'"></pr-icon> Description is required.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- !description-input -->
|
||||
|
||||
<!-- note-input -->
|
||||
<div class="form-group">
|
||||
<label for="note" class="col-sm-3 col-lg-2 control-label text-left">Note</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="text" class="form-control" id="note" ng-model="$ctrl.formValues.Note" />
|
||||
</div>
|
||||
</div>
|
||||
<!-- !note-input -->
|
||||
|
||||
<!-- icon-url-input -->
|
||||
<div class="form-group">
|
||||
<label for="icon-url" class="col-sm-3 col-lg-2 control-label text-left">Icon URL</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="text" class="form-control" id="icon-url" ng-model="$ctrl.formValues.Logo" />
|
||||
</div>
|
||||
</div>
|
||||
<!-- !icon-url-input -->
|
||||
|
||||
<!-- platform-input -->
|
||||
<div ng-if="$ctrl.showPlatformField" class="form-group">
|
||||
<label for="platform" class="col-sm-3 col-lg-2 control-label text-left">Platform</label>
|
||||
<div class="col-sm-8">
|
||||
<select class="form-control" ng-model="$ctrl.formValues.Platform" ng-options="+(opt.value) as opt.label for opt in $ctrl.platformTypes"> </select>
|
||||
</div>
|
||||
</div>
|
||||
<!-- !platform-input -->
|
||||
|
||||
<!-- platform-input -->
|
||||
<div ng-if="$ctrl.showTypeField" class="form-group">
|
||||
<label for="platform" class="col-sm-3 col-lg-2 control-label text-left">Type</label>
|
||||
<div class="col-sm-8">
|
||||
<select class="form-control" ng-model="$ctrl.formValues.Type" ng-options="+(opt.value) as opt.label for opt in $ctrl.templateTypes"> </select>
|
||||
</div>
|
||||
</div>
|
||||
<!-- !platform-input -->
|
||||
</ng-form>
|
@ -1,16 +0,0 @@
|
||||
class CustomTemplateCommonFieldsController {
|
||||
/* @ngInject */
|
||||
constructor() {
|
||||
this.platformTypes = [
|
||||
{ label: 'Linux', value: 1 },
|
||||
{ label: 'Windows', value: 2 },
|
||||
];
|
||||
|
||||
this.templateTypes = [
|
||||
{ label: 'Swarm', value: 1 },
|
||||
{ label: 'Standalone', value: 2 },
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
export default CustomTemplateCommonFieldsController;
|
@ -1,13 +0,0 @@
|
||||
import CustomTemplateCommonFieldsController from './customTemplateCommonFieldsController.js';
|
||||
|
||||
angular.module('portainer.app').component('customTemplateCommonFields', {
|
||||
templateUrl: './customTemplateCommonFields.html',
|
||||
controller: CustomTemplateCommonFieldsController,
|
||||
bindings: {
|
||||
formValues: '=',
|
||||
showPlatformField: '<',
|
||||
showTypeField: '<',
|
||||
nameRegex: '<',
|
||||
nameRegexError: '<',
|
||||
},
|
||||
});
|
@ -0,0 +1,106 @@
|
||||
import { SchemaOf, object, string } from 'yup';
|
||||
import { FormikErrors } from 'formik';
|
||||
|
||||
import { FormControl } from '@@/form-components/FormControl';
|
||||
import { Input } from '@@/form-components/Input';
|
||||
|
||||
interface Values {
|
||||
Title: string;
|
||||
Description: string;
|
||||
Note: string;
|
||||
Logo: string;
|
||||
}
|
||||
|
||||
export function CommonFields({
|
||||
values,
|
||||
onChange,
|
||||
errors,
|
||||
}: {
|
||||
values: Values;
|
||||
onChange: (values: Values) => void;
|
||||
errors?: FormikErrors<Values>;
|
||||
}) {
|
||||
return (
|
||||
<>
|
||||
<FormControl
|
||||
label="Title"
|
||||
required
|
||||
inputId="template-title"
|
||||
errors={errors?.Title}
|
||||
>
|
||||
<Input
|
||||
name="title"
|
||||
placeholder="e.g. mytemplate"
|
||||
id="template-title"
|
||||
required
|
||||
value={values.Title}
|
||||
onChange={(e) => {
|
||||
handleChange({ Title: e.target.value });
|
||||
}}
|
||||
/>
|
||||
</FormControl>
|
||||
|
||||
<FormControl
|
||||
label="Description"
|
||||
required
|
||||
inputId="template-description"
|
||||
errors={errors?.Description}
|
||||
>
|
||||
<Input
|
||||
name="description"
|
||||
id="template-description"
|
||||
required
|
||||
value={values.Description}
|
||||
onChange={(e) => {
|
||||
handleChange({ Description: e.target.value });
|
||||
}}
|
||||
/>
|
||||
</FormControl>
|
||||
|
||||
<FormControl label="Note" inputId="template-note" errors={errors?.Note}>
|
||||
<Input
|
||||
name="note"
|
||||
id="template-note"
|
||||
value={values.Note}
|
||||
onChange={(e) => {
|
||||
handleChange({ Note: e.target.value });
|
||||
}}
|
||||
/>
|
||||
</FormControl>
|
||||
|
||||
<FormControl label="Logo" inputId="template-logo" errors={errors?.Logo}>
|
||||
<Input
|
||||
name="logo"
|
||||
id="template-logo"
|
||||
value={values.Logo}
|
||||
onChange={(e) => {
|
||||
handleChange({ Logo: e.target.value });
|
||||
}}
|
||||
/>
|
||||
</FormControl>
|
||||
</>
|
||||
);
|
||||
|
||||
function handleChange(change: Partial<Values>) {
|
||||
onChange({ ...values, ...change });
|
||||
}
|
||||
}
|
||||
|
||||
export function validation({
|
||||
title,
|
||||
}: {
|
||||
title?: { pattern: string; error: string };
|
||||
} = {}): SchemaOf<Values> {
|
||||
let titleSchema = string().required('Title is required.');
|
||||
if (title?.pattern) {
|
||||
const pattern = new RegExp(title.pattern);
|
||||
titleSchema = titleSchema.matches(pattern, title.error);
|
||||
}
|
||||
|
||||
return object({
|
||||
Title: titleSchema,
|
||||
Description: string().required('Description is required.'),
|
||||
Note: string().default(''),
|
||||
Logo: string().default(''),
|
||||
});
|
||||
}
|
@ -1 +1,2 @@
|
||||
export { CustomTemplatesVariablesDefinitionField } from './CustomTemplatesVariablesDefinitionField';
|
||||
export type { VariableDefinition } from './CustomTemplatesVariablesDefinitionField';
|
||||
|
@ -0,0 +1,30 @@
|
||||
import { FormControl } from '@@/form-components/FormControl';
|
||||
import { Select } from '@@/form-components/Input';
|
||||
|
||||
import { Platform } from '../types';
|
||||
|
||||
const platformOptions = [
|
||||
{ label: 'Linux', value: Platform.LINUX },
|
||||
{ label: 'Windows', value: Platform.WINDOWS },
|
||||
];
|
||||
|
||||
export function PlatformField({
|
||||
onChange,
|
||||
value,
|
||||
}: {
|
||||
onChange: (platform: Platform) => void;
|
||||
value: Platform;
|
||||
}) {
|
||||
return (
|
||||
<FormControl label="Platform" required inputId="template-platform">
|
||||
<Select
|
||||
name="platform"
|
||||
id="template-platform"
|
||||
required
|
||||
options={platformOptions}
|
||||
value={value}
|
||||
onChange={(e) => onChange(parseInt(e.target.value, 10))}
|
||||
/>
|
||||
</FormControl>
|
||||
);
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
import { StackType } from '@/react/common/stacks/types';
|
||||
|
||||
import { FormControl } from '@@/form-components/FormControl';
|
||||
import { Select } from '@@/form-components/Input';
|
||||
|
||||
const typeOptions = [
|
||||
{ label: 'Swarm', value: StackType.DockerSwarm },
|
||||
{ label: 'Standalone', value: StackType.DockerCompose },
|
||||
];
|
||||
|
||||
export function TemplateTypeSelector({
|
||||
onChange,
|
||||
value,
|
||||
}: {
|
||||
onChange: (type: StackType) => void;
|
||||
value: StackType;
|
||||
}) {
|
||||
return (
|
||||
<FormControl label="Type" required inputId="template-type">
|
||||
<Select
|
||||
name="type"
|
||||
id="template-type"
|
||||
required
|
||||
options={typeOptions}
|
||||
value={value}
|
||||
onChange={(e) => onChange(parseInt(e.target.value, 10))}
|
||||
/>
|
||||
</FormControl>
|
||||
);
|
||||
}
|
Loading…
Reference in new issue