mirror of
https://github.com/portainer/portainer.git
synced 2025-07-24 15:59:41 +02:00
feat(app): add ingress to app service form [EE-5569] (#9106)
This commit is contained in:
parent
8c16fbb8aa
commit
89c1d0e337
47 changed files with 1929 additions and 1181 deletions
|
@ -7,11 +7,13 @@ import { FormSectionTitle } from '../FormSectionTitle';
|
|||
|
||||
interface Props {
|
||||
title: ReactNode;
|
||||
titleSize?: 'sm' | 'md' | 'lg';
|
||||
isFoldable?: boolean;
|
||||
}
|
||||
|
||||
export function FormSection({
|
||||
title,
|
||||
titleSize = 'md',
|
||||
children,
|
||||
isFoldable = false,
|
||||
}: PropsWithChildren<Props>) {
|
||||
|
@ -19,7 +21,10 @@ export function FormSection({
|
|||
|
||||
return (
|
||||
<>
|
||||
<FormSectionTitle htmlFor={isFoldable ? `foldingButton${title}` : ''}>
|
||||
<FormSectionTitle
|
||||
htmlFor={isFoldable ? `foldingButton${title}` : ''}
|
||||
titleSize={titleSize}
|
||||
>
|
||||
{isFoldable && (
|
||||
<button
|
||||
id={`foldingButton${title}`}
|
||||
|
|
|
@ -1,22 +1,43 @@
|
|||
import clsx from 'clsx';
|
||||
import { PropsWithChildren } from 'react';
|
||||
|
||||
interface Props {
|
||||
htmlFor?: string;
|
||||
titleSize?: 'sm' | 'md' | 'lg';
|
||||
}
|
||||
|
||||
const tailwindTitleSize = {
|
||||
sm: 'text-sm',
|
||||
md: 'text-base',
|
||||
lg: 'text-lg',
|
||||
};
|
||||
|
||||
export function FormSectionTitle({
|
||||
children,
|
||||
htmlFor,
|
||||
titleSize = 'md',
|
||||
}: PropsWithChildren<Props>) {
|
||||
if (htmlFor) {
|
||||
return (
|
||||
<label
|
||||
htmlFor={htmlFor}
|
||||
className="col-sm-12 form-section-title flex cursor-pointer items-center"
|
||||
className={clsx(
|
||||
'col-sm-12 mt-1 mb-2 flex cursor-pointer items-center pl-0 font-medium',
|
||||
tailwindTitleSize[titleSize]
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</label>
|
||||
);
|
||||
}
|
||||
return <div className="col-sm-12 form-section-title">{children}</div>;
|
||||
return (
|
||||
<div
|
||||
className={clsx(
|
||||
'col-sm-12 mt-1 mb-2 pl-0 font-medium',
|
||||
tailwindTitleSize[titleSize]
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { PropsWithChildren } from 'react';
|
||||
import clsx from 'clsx';
|
||||
|
||||
import { useInputGroupContext } from './InputGroup';
|
||||
|
||||
|
@ -7,5 +8,16 @@ export function InputGroupButtonWrapper({
|
|||
}: PropsWithChildren<unknown>) {
|
||||
useInputGroupContext();
|
||||
|
||||
return <span className="input-group-btn">{children}</span>;
|
||||
return (
|
||||
<span
|
||||
className={clsx(
|
||||
'input-group-btn [&>button]:!ml-0',
|
||||
// the button should be rounded at the end (right) if it's the last child and start (left) if it's the first child
|
||||
// if the button is in the middle of the group, it shouldn't be rounded
|
||||
'[&>button]:!rounded-none [&:last-child>button]:!rounded-r-[5px] [&:first-child>button]:!rounded-l-[5px]'
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -19,6 +19,14 @@
|
|||
overflow: hidden;
|
||||
}
|
||||
|
||||
.portainer-selector-root.sm .portainer-selector__placeholder {
|
||||
@apply text-xs;
|
||||
}
|
||||
|
||||
.portainer-selector-root.md .portainer-selector__placeholder {
|
||||
@apply text-sm;
|
||||
}
|
||||
|
||||
.portainer-selector__indicator-separator {
|
||||
display: none;
|
||||
}
|
||||
|
@ -27,6 +35,29 @@
|
|||
.portainer-selector-root .portainer-selector__control {
|
||||
border-color: var(--border-form-control-color);
|
||||
background-color: var(--bg-inputbox);
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
/* Match the same box shadow styles as the other portainer inputs, which are inherited from the bootstrap form-control class */
|
||||
.portainer-selector-root .portainer-selector__control--is-focused {
|
||||
border-color: #66afe9;
|
||||
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);
|
||||
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);
|
||||
transition: border-color ease-in-out 0.15s, -webkit-box-shadow ease-in-out 0.15s;
|
||||
}
|
||||
|
||||
.portainer-selector-root .portainer-selector__control--is-focused:hover {
|
||||
border-color: #66afe9;
|
||||
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);
|
||||
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);
|
||||
transition: border-color ease-in-out 0.15s, -webkit-box-shadow ease-in-out 0.15s;
|
||||
}
|
||||
|
||||
.portainer-selector-root.sm .portainer-selector__control {
|
||||
min-height: 30px;
|
||||
}
|
||||
|
||||
.portainer-selector-root.md .portainer-selector__control {
|
||||
min-height: 34px;
|
||||
}
|
||||
|
||||
|
@ -38,6 +69,11 @@
|
|||
color: var(--text-form-control-color);
|
||||
}
|
||||
|
||||
.portainer-selector-root.sm .portainer-selector__input-container {
|
||||
height: 20px;
|
||||
@apply text-xs;
|
||||
}
|
||||
|
||||
.portainer-selector-root .portainer-selector__dropdown-indicator {
|
||||
padding: 0 8px;
|
||||
}
|
||||
|
@ -56,6 +92,14 @@
|
|||
color: var(--single-value-option-text-color);
|
||||
}
|
||||
|
||||
.portainer-selector-root.sm .portainer-selector__single-value {
|
||||
@apply text-xs;
|
||||
}
|
||||
|
||||
.portainer-selector-root.md .portainer-selector__single-value {
|
||||
@apply text-sm;
|
||||
}
|
||||
|
||||
/* Menu colors */
|
||||
.portainer-selector__menu {
|
||||
--bg-multiselect-color: var(--white-color);
|
||||
|
@ -100,6 +144,10 @@
|
|||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.portainer-selector-root.sm .portainer-selector__menu .portainer-selector__option {
|
||||
@apply text-xs;
|
||||
}
|
||||
|
||||
.portainer-selector__menu-portal .portainer-selector__menu .portainer-selector__option:active,
|
||||
.portainer-selector__menu-portal .portainer-selector__menu .portainer-selector__option--is-focused,
|
||||
.portainer-selector-root .portainer-selector__menu .portainer-selector__option:active,
|
||||
|
|
|
@ -20,14 +20,22 @@ type RegularProps<
|
|||
Option = DefaultOption,
|
||||
IsMulti extends boolean = false,
|
||||
Group extends GroupBase<Option> = GroupBase<Option>
|
||||
> = { isCreatable?: false } & ReactSelectProps<Option, IsMulti, Group> &
|
||||
> = { isCreatable?: false; size?: 'sm' | 'md' } & ReactSelectProps<
|
||||
Option,
|
||||
IsMulti,
|
||||
Group
|
||||
> &
|
||||
RefAttributes<ReactSelectType<Option, IsMulti, Group>>;
|
||||
|
||||
type CreatableProps<
|
||||
Option = DefaultOption,
|
||||
IsMulti extends boolean = false,
|
||||
Group extends GroupBase<Option> = GroupBase<Option>
|
||||
> = { isCreatable: true } & ReactSelectCreatableProps<Option, IsMulti, Group>;
|
||||
> = { isCreatable: true; size?: 'sm' | 'md' } & ReactSelectCreatableProps<
|
||||
Option,
|
||||
IsMulti,
|
||||
Group
|
||||
>;
|
||||
|
||||
type Props<
|
||||
Option = DefaultOption,
|
||||
|
@ -41,12 +49,17 @@ export function Select<
|
|||
Option = DefaultOption,
|
||||
IsMulti extends boolean = false,
|
||||
Group extends GroupBase<Option> = GroupBase<Option>
|
||||
>({ className, isCreatable = false, ...props }: Props<Option, IsMulti, Group>) {
|
||||
>({
|
||||
className,
|
||||
isCreatable = false,
|
||||
size = 'md',
|
||||
...props
|
||||
}: Props<Option, IsMulti, Group>) {
|
||||
const Component = isCreatable ? ReactSelectCreatable : ReactSelect;
|
||||
|
||||
return (
|
||||
<Component
|
||||
className={clsx(className, 'portainer-selector-root')}
|
||||
className={clsx(className, 'portainer-selector-root', size)}
|
||||
classNamePrefix="portainer-selector"
|
||||
// eslint-disable-next-line react/jsx-props-no-spreading
|
||||
{...props}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue