2024-02-15 07:01:01 +00:00
|
|
|
import { useMemo } from 'react';
|
|
|
|
import { GroupBase } from 'react-select';
|
|
|
|
|
|
|
|
import { useCustomTemplates } from '@/react/portainer/templates/custom-templates/queries/useCustomTemplates';
|
|
|
|
import { useAppTemplates } from '@/react/portainer/templates/app-templates/queries/useAppTemplates';
|
|
|
|
import { TemplateType } from '@/react/portainer/templates/app-templates/types';
|
2024-05-06 05:08:03 +00:00
|
|
|
import { TemplateViewModel } from '@/react/portainer/templates/app-templates/view-model';
|
|
|
|
import { CustomTemplate } from '@/react/portainer/templates/custom-templates/types';
|
2024-02-15 07:01:01 +00:00
|
|
|
|
|
|
|
import { FormControl } from '@@/form-components/FormControl';
|
|
|
|
import { Select as ReactSelect } from '@@/form-components/ReactSelect';
|
|
|
|
|
|
|
|
import { SelectedTemplateValue } from './types';
|
|
|
|
|
|
|
|
export function TemplateSelector({
|
|
|
|
value,
|
|
|
|
onChange,
|
|
|
|
error,
|
|
|
|
}: {
|
|
|
|
value: SelectedTemplateValue;
|
2024-05-06 05:08:03 +00:00
|
|
|
onChange: (
|
|
|
|
template: TemplateViewModel | CustomTemplate | undefined,
|
|
|
|
type: 'app' | 'custom' | undefined
|
|
|
|
) => void;
|
2024-02-15 07:01:01 +00:00
|
|
|
error?: string;
|
|
|
|
}) {
|
2024-05-06 05:08:03 +00:00
|
|
|
const { options, getTemplate } = useOptions();
|
2024-02-15 07:01:01 +00:00
|
|
|
|
|
|
|
return (
|
|
|
|
<FormControl label="Template" inputId="template_selector" errors={error}>
|
|
|
|
<ReactSelect
|
|
|
|
inputId="template_selector"
|
|
|
|
formatGroupLabel={GroupLabel}
|
|
|
|
placeholder="Select an Edge stack template"
|
|
|
|
value={{
|
2024-05-06 05:08:03 +00:00
|
|
|
templateId: value.templateId,
|
2024-02-15 07:01:01 +00:00
|
|
|
type: value.type,
|
|
|
|
}}
|
|
|
|
onChange={(value) => {
|
|
|
|
if (!value) {
|
2024-05-06 05:08:03 +00:00
|
|
|
onChange(undefined, undefined);
|
2024-02-15 07:01:01 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-05-06 05:08:03 +00:00
|
|
|
const { templateId, type } = value;
|
|
|
|
if (!templateId || type === undefined) {
|
2024-02-15 07:01:01 +00:00
|
|
|
return;
|
|
|
|
}
|
2024-05-06 05:08:03 +00:00
|
|
|
onChange(getTemplate({ type, id: templateId }), type);
|
2024-02-15 07:01:01 +00:00
|
|
|
}}
|
|
|
|
options={options}
|
2024-04-11 00:11:38 +00:00
|
|
|
data-cy="edge-stacks-create-template-selector"
|
2024-02-15 07:01:01 +00:00
|
|
|
/>
|
|
|
|
</FormControl>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
function useOptions() {
|
|
|
|
const customTemplatesQuery = useCustomTemplates({
|
|
|
|
params: {
|
|
|
|
edge: true,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
const appTemplatesQuery = useAppTemplates({
|
|
|
|
select: (templates) =>
|
|
|
|
templates.filter(
|
|
|
|
(template) =>
|
|
|
|
template.Categories.includes('edge') &&
|
|
|
|
template.Type !== TemplateType.Container
|
|
|
|
),
|
|
|
|
});
|
|
|
|
|
|
|
|
const options = useMemo(
|
|
|
|
() =>
|
|
|
|
[
|
|
|
|
{
|
|
|
|
label: 'Edge App Templates',
|
|
|
|
options:
|
|
|
|
appTemplatesQuery.data?.map((template) => ({
|
|
|
|
label: `${template.Title} - ${template.Description}`,
|
2024-05-06 05:08:03 +00:00
|
|
|
|
|
|
|
templateId: template.Id,
|
2024-02-15 07:01:01 +00:00
|
|
|
type: 'app' as 'app' | 'custom',
|
|
|
|
})) || [],
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: 'Edge Custom Templates',
|
|
|
|
options:
|
|
|
|
customTemplatesQuery.data && customTemplatesQuery.data.length > 0
|
|
|
|
? customTemplatesQuery.data.map((template) => ({
|
|
|
|
label: `${template.Title} - ${template.Description}`,
|
2024-05-06 05:08:03 +00:00
|
|
|
|
|
|
|
templateId: template.Id,
|
2024-02-15 07:01:01 +00:00
|
|
|
type: 'custom' as 'app' | 'custom',
|
|
|
|
}))
|
|
|
|
: [
|
|
|
|
{
|
|
|
|
label: 'No edge custom templates available',
|
2024-05-06 05:08:03 +00:00
|
|
|
|
|
|
|
templateId: undefined,
|
|
|
|
type: undefined,
|
2024-02-15 07:01:01 +00:00
|
|
|
},
|
|
|
|
],
|
|
|
|
},
|
|
|
|
] as const,
|
|
|
|
[appTemplatesQuery.data, customTemplatesQuery.data]
|
|
|
|
);
|
|
|
|
|
|
|
|
return { options, getTemplate };
|
|
|
|
|
|
|
|
function getTemplate({ type, id }: { type: 'app' | 'custom'; id: number }) {
|
|
|
|
if (type === 'app') {
|
|
|
|
const template = appTemplatesQuery.data?.find(
|
|
|
|
(template) => template.Id === id
|
|
|
|
);
|
|
|
|
|
|
|
|
if (!template) {
|
|
|
|
throw new Error(`App template not found: ${id}`);
|
|
|
|
}
|
|
|
|
|
|
|
|
return template;
|
|
|
|
}
|
|
|
|
|
|
|
|
const template = customTemplatesQuery.data?.find(
|
|
|
|
(template) => template.Id === id
|
|
|
|
);
|
|
|
|
|
|
|
|
if (!template) {
|
|
|
|
throw new Error(`Custom template not found: ${id}`);
|
|
|
|
}
|
|
|
|
return template;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function GroupLabel({ label }: GroupBase<unknown>) {
|
|
|
|
return (
|
|
|
|
<span className="font-bold text-black th-dark:text-white th-highcontrast:text-white">
|
|
|
|
{label}
|
|
|
|
</span>
|
|
|
|
);
|
|
|
|
}
|