mirror of
https://github.com/portainer/portainer.git
synced 2025-08-02 20:35:25 +02:00
feat(ingress): autodetect ingress controllers EE-673 (#7712)
This commit is contained in:
parent
c96551e410
commit
89eda13eb3
48 changed files with 1252 additions and 1047 deletions
29
app/react/components/Badge/Badge.stories.tsx
Normal file
29
app/react/components/Badge/Badge.stories.tsx
Normal file
|
@ -0,0 +1,29 @@
|
|||
import { Meta } from '@storybook/react';
|
||||
|
||||
import { Badge, Props } from './Badge';
|
||||
|
||||
export default {
|
||||
component: Badge,
|
||||
title: 'Components/Badge',
|
||||
argTypes: {
|
||||
type: {
|
||||
control: {
|
||||
type: 'select',
|
||||
options: ['success', 'danger', 'warn', 'info'],
|
||||
},
|
||||
},
|
||||
},
|
||||
} as Meta<Props>;
|
||||
|
||||
// : JSX.IntrinsicAttributes & PropsWithChildren<Props>
|
||||
function Template({ type = 'success' }: Props) {
|
||||
const message = {
|
||||
success: 'success badge',
|
||||
danger: 'danger badge',
|
||||
warn: 'warn badge',
|
||||
info: 'info badge',
|
||||
};
|
||||
return <Badge type={type}>{message[type]}</Badge>;
|
||||
}
|
||||
|
||||
export const Example = Template.bind({});
|
59
app/react/components/Badge/Badge.tsx
Normal file
59
app/react/components/Badge/Badge.tsx
Normal file
|
@ -0,0 +1,59 @@
|
|||
import clsx from 'clsx';
|
||||
import { PropsWithChildren } from 'react';
|
||||
|
||||
type BadgeType = 'success' | 'danger' | 'warn' | 'info';
|
||||
|
||||
export interface Props {
|
||||
type?: BadgeType;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
// this component is used in tables and lists in portainer. It looks like this:
|
||||
// https://www.figma.com/file/g5TUMngrblkXM7NHSyQsD1/New-UI?node-id=76%3A2
|
||||
export function Badge({ type, className, children }: PropsWithChildren<Props>) {
|
||||
const baseClasses =
|
||||
'flex w-fit items-center !text-xs font-medium rounded-full px-2 py-0.5';
|
||||
const typeClasses = getClasses(type);
|
||||
|
||||
return (
|
||||
<span className={clsx(baseClasses, typeClasses, className)}>
|
||||
{children}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
// classes in full to prevent a dev server bug, where tailwind doesn't render the interpolated classes
|
||||
function getClasses(type: BadgeType | undefined) {
|
||||
switch (type) {
|
||||
case 'success':
|
||||
return clsx(
|
||||
`text-success-9 bg-success-2`,
|
||||
`th-dark:text-success-3 th-dark:bg-success-10`,
|
||||
`th-highcontrast:text-success-3 th-highcontrast:bg-success-10`
|
||||
);
|
||||
case 'warn':
|
||||
return clsx(
|
||||
`text-warning-9 bg-warning-2`,
|
||||
`th-dark:text-warning-3 th-dark:bg-warning-10`,
|
||||
`th-highcontrast:text-warning-3 th-highcontrast:bg-warning-10`
|
||||
);
|
||||
case 'danger':
|
||||
return clsx(
|
||||
`text-error-9 bg-error-2`,
|
||||
`th-dark:text-error-3 th-dark:bg-error-10`,
|
||||
`th-highcontrast:text-error-3 th-highcontrast:bg-error-10`
|
||||
);
|
||||
case 'info':
|
||||
return clsx(
|
||||
`text-blue-9 bg-blue-2`,
|
||||
`th-dark:text-blue-3 th-dark:bg-blue-10`,
|
||||
`th-highcontrast:text-blue-3 th-highcontrast:bg-blue-10`
|
||||
);
|
||||
default:
|
||||
return clsx(
|
||||
`text-blue-9 bg-blue-2`,
|
||||
`th-dark:text-blue-3 th-dark:bg-blue-10`,
|
||||
`th-highcontrast:text-blue-3 th-highcontrast:bg-blue-10`
|
||||
);
|
||||
}
|
||||
}
|
1
app/react/components/Badge/index.ts
Normal file
1
app/react/components/Badge/index.ts
Normal file
|
@ -0,0 +1 @@
|
|||
export { Badge } from './Badge';
|
|
@ -54,6 +54,7 @@ interface Props<
|
|||
initialTableState?: Partial<TableState<D>>;
|
||||
isLoading?: boolean;
|
||||
totalCount?: number;
|
||||
description?: JSX.Element;
|
||||
}
|
||||
|
||||
export function Datatable<
|
||||
|
@ -74,6 +75,7 @@ export function Datatable<
|
|||
initialTableState = {},
|
||||
isLoading,
|
||||
totalCount = dataset.length,
|
||||
description,
|
||||
}: Props<D, TSettings>) {
|
||||
const [searchBarValue, setSearchBarValue] = useSearchBarState(storageKey);
|
||||
|
||||
|
@ -145,6 +147,7 @@ export function Datatable<
|
|||
label={titleOptions.title}
|
||||
icon={titleOptions.icon}
|
||||
featherIcon={titleOptions.featherIcon}
|
||||
description={description}
|
||||
>
|
||||
<SearchBar value={searchBarValue} onChange={setGlobalFilter} />
|
||||
{renderTableActions && (
|
||||
|
|
|
@ -20,8 +20,8 @@ export function SearchBar({
|
|||
const [searchValue, setSearchValue] = useDebounce(value, onChange);
|
||||
|
||||
return (
|
||||
<div className="searchBar items-center flex">
|
||||
<Search className="searchIcon feather" />
|
||||
<div className="searchBar items-center flex min-w-[90px]">
|
||||
<Search className="searchIcon feather shrink-0" />
|
||||
<input
|
||||
type="text"
|
||||
className="searchInput"
|
||||
|
|
|
@ -22,7 +22,7 @@ export function TableHeaderCell({
|
|||
render,
|
||||
onSortClick,
|
||||
isSorted,
|
||||
isSortedDesc,
|
||||
isSortedDesc = true,
|
||||
canFilter,
|
||||
renderFilter,
|
||||
}: Props) {
|
||||
|
@ -55,7 +55,7 @@ function SortWrapper({
|
|||
children,
|
||||
onClick = () => {},
|
||||
isSorted,
|
||||
isSortedDesc,
|
||||
isSortedDesc = true,
|
||||
}: PropsWithChildren<SortWrapperProps>) {
|
||||
if (!canSort) {
|
||||
return <>{children}</>;
|
||||
|
@ -93,7 +93,7 @@ export function TableColumnHeaderAngular({
|
|||
canSort,
|
||||
isSorted,
|
||||
colTitle,
|
||||
isSortedDesc,
|
||||
isSortedDesc = true,
|
||||
}: TableColumnHeaderAngularProps) {
|
||||
return (
|
||||
<div className="flex flex-row flex-nowrap h-full">
|
||||
|
|
|
@ -6,6 +6,7 @@ interface Props {
|
|||
icon?: ReactNode | ComponentType<unknown>;
|
||||
featherIcon?: boolean;
|
||||
label: string;
|
||||
description?: JSX.Element;
|
||||
}
|
||||
|
||||
export function TableTitle({
|
||||
|
@ -13,23 +14,27 @@ export function TableTitle({
|
|||
featherIcon,
|
||||
label,
|
||||
children,
|
||||
description,
|
||||
}: PropsWithChildren<Props>) {
|
||||
return (
|
||||
<div className="toolBar">
|
||||
<div className="toolBarTitle">
|
||||
{icon && (
|
||||
<div className="widget-icon">
|
||||
<Icon
|
||||
icon={icon}
|
||||
feather={featherIcon}
|
||||
className="space-right feather"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div className="toolBar flex-col">
|
||||
<div className="flex gap-1 p-0 w-full items-center">
|
||||
<div className="toolBarTitle">
|
||||
{icon && (
|
||||
<div className="widget-icon">
|
||||
<Icon
|
||||
icon={icon}
|
||||
feather={featherIcon}
|
||||
className="space-right feather"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{label}
|
||||
{label}
|
||||
</div>
|
||||
{children}
|
||||
</div>
|
||||
{children}
|
||||
{description && description}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue