1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-07-24 15:59:41 +02:00

feat(system): path to upgrade standalone to BE [EE-4071] (#8095)

This commit is contained in:
Chaim Lev-Ari 2022-12-11 08:58:22 +02:00 committed by GitHub
parent 756ac034ec
commit 5cbf52377d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
73 changed files with 1374 additions and 421 deletions

View file

@ -0,0 +1,22 @@
.close {
color: var(--button-close-color);
opacity: var(--button-opacity);
padding: 0;
cursor: pointer;
background: transparent;
border: 0;
appearance: none;
font-size: 21px;
font-weight: bold;
line-height: 1;
text-shadow: 0 1px 0 #fff;
filter: alpha(opacity=20);
}
.close:hover,
.close:focus {
color: var(--button-close-color);
opacity: var(--button-opacity-hover);
}

View file

@ -0,0 +1,21 @@
import clsx from 'clsx';
import styles from './CloseButton.module.css';
export function CloseButton({
onClose,
className,
}: {
onClose: () => void;
className?: string;
}) {
return (
<button
type="button"
className={clsx(styles.close, className, 'absolute top-2 right-2')}
onClick={() => onClose()}
>
×
</button>
);
}

View file

@ -0,0 +1,20 @@
.modal-dialog {
width: 450px;
display: inline-block;
text-align: left;
vertical-align: middle;
}
.modal-content {
background-color: var(--bg-modal-content-color);
padding: 20px;
position: relative;
border: 1px solid rgba(0, 0, 0, 0.2);
border-radius: 6px;
outline: 0;
box-shadow: 0 5px 15px rgb(0 0 0 / 50%);
}

View file

@ -0,0 +1,53 @@
import { DialogContent, DialogOverlay } from '@reach/dialog';
import clsx from 'clsx';
import { createContext, PropsWithChildren, useContext } from 'react';
import { CloseButton } from './CloseButton';
import styles from './Modal.module.css';
const Context = createContext<boolean | null>(null);
Context.displayName = 'ModalContext';
export function useModalContext() {
const context = useContext(Context);
if (!context) {
throw new Error('should be nested under Modal');
}
return context;
}
interface Props {
onDismiss?(): void;
'aria-label'?: string;
'aria-labelledby'?: string;
}
export function Modal({
children,
onDismiss,
'aria-label': ariaLabel,
'aria-labelledby': ariaLabelledBy,
}: PropsWithChildren<Props>) {
return (
<Context.Provider value>
<DialogOverlay
isOpen
className="flex items-center justify-center z-50"
onDismiss={onDismiss}
role="dialog"
>
<DialogContent
aria-label={ariaLabel}
aria-labelledby={ariaLabelledBy}
className={clsx(styles.modalDialog, 'p-0 bg-transparent')}
>
<div className={clsx(styles.modalContent, 'relative')}>
{children}
{onDismiss && <CloseButton onClose={onDismiss} />}
</div>
</DialogContent>
</DialogOverlay>
</Context.Provider>
);
}

View file

@ -0,0 +1,4 @@
.modal-body {
padding: 10px 0px;
border-bottom: none;
}

View file

@ -0,0 +1,9 @@
import { PropsWithChildren } from 'react';
import { useModalContext } from './Modal';
import styles from './ModalBody.module.css';
export function ModalBody({ children }: PropsWithChildren<unknown>) {
useModalContext();
return <div className={styles.modalBody}>{children}</div>;
}

View file

@ -0,0 +1,5 @@
.modal-footer {
padding: 10px 0px;
border-top: none;
display: flex;
}

View file

@ -0,0 +1,15 @@
import clsx from 'clsx';
import { PropsWithChildren } from 'react';
import { useModalContext } from './Modal';
import styles from './ModalFooter.module.css';
export function ModalFooter({ children }: PropsWithChildren<unknown>) {
useModalContext();
return (
<div className={clsx(styles.modalFooter, 'flex justify-end')}>
{children}
</div>
);
}

View file

@ -0,0 +1,19 @@
.modal-header {
margin-bottom: 10px;
padding: 0px;
border-bottom: none;
}
.background-error {
padding-top: 55px;
background-image: url(~assets/images/icon-error.svg);
background-repeat: no-repeat;
background-position: top left;
}
.background-warning {
padding-top: 55px;
background-image: url(~assets/images/icon-warning.svg);
background-repeat: no-repeat;
background-position: top left;
}

View file

@ -0,0 +1,33 @@
import clsx from 'clsx';
import { ReactNode } from 'react';
import { ModalType } from './types';
import { useModalContext } from './Modal';
import styles from './ModalHeader.module.css';
interface Props {
title: ReactNode;
modalType?: ModalType;
}
export function ModalHeader({ title, modalType }: Props) {
useModalContext();
return (
<div className={styles.modalHeader}>
{modalType && (
<div
className={clsx({
[styles.backgroundError]: modalType === ModalType.Destructive,
[styles.backgroundWarning]: modalType === ModalType.Warn,
})}
/>
)}
{typeof title === 'string' ? (
<h5 className="font-bold">{title}</h5>
) : (
title
)}
</div>
);
}

View file

@ -0,0 +1,18 @@
import { Modal as MainComponent } from './Modal';
import { ModalHeader } from './ModalHeader';
import { ModalBody } from './ModalBody';
import { ModalFooter } from './ModalFooter';
interface WithSubComponents {
Header: typeof ModalHeader;
Body: typeof ModalBody;
Footer: typeof ModalFooter;
}
const Modal = MainComponent as typeof MainComponent & WithSubComponents;
Modal.Header = ModalHeader;
Modal.Body = ModalBody;
Modal.Footer = ModalFooter;
export { Modal };

View file

@ -0,0 +1,6 @@
export type OnSubmit<TResult> = (result?: TResult) => void;
export enum ModalType {
Warn = 'warning',
Destructive = 'error',
}