1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-08-04 21:35:23 +02:00

feat(edge/templates): introduce custom templates [EE-6208] (#10561)

This commit is contained in:
Chaim Lev-Ari 2023-11-15 10:45:07 +02:00 committed by GitHub
parent a0f583a17d
commit 68950fbb24
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
81 changed files with 2047 additions and 334 deletions

View file

@ -23,7 +23,7 @@ export function BlocklistItem<T extends ElementType>({
type="button"
className={clsx(
className,
'blocklist-item flex items-stretch overflow-hidden bg-transparent w-full !ml-0 text-left',
'blocklist-item flex items-stretch overflow-hidden bg-transparent w-full !ml-0 no-link text-left',
{
'blocklist-item--selected': isSelected,
}

View file

@ -1,4 +1,5 @@
import { PropsWithChildren } from 'react';
import { PropsWithChildren, useEffect, useMemo } from 'react';
import { useTransitionHook } from '@uirouter/react';
import { BROWSER_OS_PLATFORM } from '@/react/constants';
@ -6,6 +7,10 @@ import { CodeEditor } from '@@/CodeEditor';
import { Tooltip } from '@@/Tip/Tooltip';
import { FormSectionTitle } from './form-components/FormSectionTitle';
import { FormError } from './form-components/FormError';
import { confirm } from './modals/confirm';
import { ModalType } from './modals';
import { buildConfirmButton } from './modals/utils';
const otherEditorConfig = {
tooltip: (
@ -91,6 +96,8 @@ export function WebEditorForm({
</div>
)}
{error && <FormError>{error}</FormError>}
<div className="form-group">
<div className="col-sm-12 col-lg-12">
<CodeEditor
@ -104,11 +111,59 @@ export function WebEditorForm({
/>
</div>
</div>
<div className="form-group">
<div className="col-sm-12 col-lg-12">{error}</div>
</div>
</div>
</div>
);
}
export function usePreventExit(
initialValue: string,
value: string,
check: boolean
) {
const isChanged = useMemo(
() => cleanText(initialValue) !== cleanText(value),
[initialValue, value]
);
const preventExit = check && isChanged;
// when navigating away from the page with unsaved changes, show a portainer prompt to confirm
useTransitionHook('onBefore', {}, async () => {
if (!preventExit) {
return true;
}
const confirmed = await confirm({
modalType: ModalType.Warn,
title: 'Are you sure?',
message:
'You currently have unsaved changes in the text editor. Are you sure you want to leave?',
confirmButton: buildConfirmButton('Yes', 'danger'),
});
return confirmed;
});
// when reloading or exiting the page with unsaved changes, show a browser prompt to confirm
useEffect(() => {
function handler(event: BeforeUnloadEvent) {
if (!preventExit) {
return undefined;
}
event.preventDefault();
// eslint-disable-next-line no-param-reassign
event.returnValue = '';
return '';
}
// if the form is changed, then set the onbeforeunload
window.addEventListener('beforeunload', handler);
return () => {
window.removeEventListener('beforeunload', handler);
};
}, [preventExit]);
}
function cleanText(value: string) {
return value.replace(/(\r\n|\n|\r)/gm, '');
}

View file

@ -1,13 +1,16 @@
import { PropsWithChildren } from 'react';
import { AutomationTestingProps } from '@/types';
import { LoadingButton } from '@@/buttons';
interface Props {
import { FormSection } from './FormSection';
interface Props extends AutomationTestingProps {
submitLabel: string;
loadingText: string;
isLoading: boolean;
isValid: boolean;
'data-cy'?: string;
}
export function FormActions({
@ -19,20 +22,22 @@ export function FormActions({
'data-cy': dataCy,
}: PropsWithChildren<Props>) {
return (
<div className="form-group">
<div className="col-sm-12">
<LoadingButton
className="!ml-0"
loadingText={loadingText}
isLoading={isLoading}
disabled={!isValid}
data-cy={dataCy}
>
{submitLabel}
</LoadingButton>
<FormSection title="Actions">
<div className="form-group">
<div className="col-sm-12">
<LoadingButton
className="!ml-0"
loadingText={loadingText}
isLoading={isLoading}
disabled={!isValid}
data-cy={dataCy}
>
{submitLabel}
</LoadingButton>
{children}
{children}
</div>
</div>
</div>
</FormSection>
);
}