mirror of https://github.com/portainer/portainer
fix(helm): helm charts view bad icon aspect ratio EE-4451 (#7875)
parent
1100a2bd28
commit
368e6b2a44
|
@ -102,6 +102,9 @@ pr-icon {
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-nested-blue {
|
.icon-nested-blue {
|
||||||
|
@apply bg-blue-3 text-blue-8;
|
||||||
|
@apply th-dark:bg-gray-9 th-dark:text-blue-3;
|
||||||
|
@apply th-highcontrast:bg-gray-9 th-highcontrast:text-blue-3;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
@ -110,7 +113,6 @@ pr-icon {
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
background-color: var(--ui-blue-3);
|
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,22 +2,9 @@
|
||||||
<div ng-class="{ 'blocklist-item--selected': $ctrl.model.Selected }" class="blocklist-item template-item mx-[10px]" ng-click="$ctrl.onSelect($ctrl.model)">
|
<div ng-class="{ 'blocklist-item--selected': $ctrl.model.Selected }" class="blocklist-item template-item mx-[10px]" ng-click="$ctrl.onSelect($ctrl.model)">
|
||||||
<div class="blocklist-item-box">
|
<div class="blocklist-item-box">
|
||||||
<!-- helmchart-image -->
|
<!-- helmchart-image -->
|
||||||
<span ng-if="$ctrl.model.icon">
|
<span class="shrink-0">
|
||||||
<fallback-image
|
<fallback-image src="$ctrl.model.icon" fallback-icon="'svg-helm'" class-name="'blocklist-item-logo h-16 w-auto'" size="'3xl'"></fallback-image>
|
||||||
src="$ctrl.model.icon"
|
|
||||||
fallback-icon="'svg-helm'"
|
|
||||||
class-name="'blocklist-item-logo h-16 w-auto'"
|
|
||||||
fallback-class-name="'icon-nested-blue !h-12 !w-12 [&>*]:!h-8 [&>*]:!w-auto'"
|
|
||||||
fallback-mode="'primary'"
|
|
||||||
size="'xl'"
|
|
||||||
></fallback-image>
|
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<div class="widget-icon space-right" ng-if="!$ctrl.model.icon">
|
|
||||||
<pr-icon icon="'svg-helm'"></pr-icon>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- !helmchart-image -->
|
|
||||||
<!-- helmchart-details -->
|
<!-- helmchart-details -->
|
||||||
<div class="col-sm-12 helm-template-item-details">
|
<div class="col-sm-12 helm-template-item-details">
|
||||||
<!-- blocklist-item-line1 -->
|
<!-- blocklist-item-line1 -->
|
||||||
|
|
|
@ -24,13 +24,7 @@
|
||||||
<div class="col-sm-12" ng-if="$ctrl.state.chart">
|
<div class="col-sm-12" ng-if="$ctrl.state.chart">
|
||||||
<rd-widget>
|
<rd-widget>
|
||||||
<div class="toolBarTitle vertical-center pt-5 px-5 text-muted">
|
<div class="toolBarTitle vertical-center pt-5 px-5 text-muted">
|
||||||
<fallback-image
|
<fallback-image src="$ctrl.state.chart.icon" fallback-icon="'svg-helm'" class-name="'h-8 w-8'" size="'lg'"></fallback-image>
|
||||||
src="$ctrl.state.chart.icon"
|
|
||||||
fallback-icon="'svg-helm'"
|
|
||||||
class-name="'h-8 w-8'"
|
|
||||||
fallback-class-name="'icon-nested-blue'"
|
|
||||||
fallback-mode="'primary'"
|
|
||||||
></fallback-image>
|
|
||||||
{{ $ctrl.state.chart.name }}
|
{{ $ctrl.state.chart.name }}
|
||||||
</div>
|
</div>
|
||||||
<rd-widget-body classes="padding">
|
<rd-widget-body classes="padding">
|
||||||
|
|
|
@ -3,13 +3,7 @@
|
||||||
<div class="blocklist-item-box">
|
<div class="blocklist-item-box">
|
||||||
<!-- template-image -->
|
<!-- template-image -->
|
||||||
<div class="vertical-center justify-center min-w-[56px]">
|
<div class="vertical-center justify-center min-w-[56px]">
|
||||||
<fallback-image
|
<fallback-image src="$ctrl.model.Logo" fallback-icon="'svg-rocket'" class-name="'blocklist-item-logo'" size="'3xl'"></fallback-image>
|
||||||
src="$ctrl.model.Logo"
|
|
||||||
fallback-icon="'svg-rocket'"
|
|
||||||
class-name="'blocklist-item-logo'"
|
|
||||||
fallback-class-name="'!h-14 !w-14 [&>*]:!h-8 [&>*]:!w-auto icon-nested-blue'"
|
|
||||||
fallback-mode="'primary'"
|
|
||||||
></fallback-image>
|
|
||||||
</div>
|
</div>
|
||||||
<!-- !template-image -->
|
<!-- !template-image -->
|
||||||
<!-- template-details -->
|
<!-- template-details -->
|
||||||
|
|
|
@ -5,7 +5,7 @@ import Microsoft from '@/assets/ico/vendor/microsoft.svg?c';
|
||||||
import Google from '@/assets/ico/vendor/google.svg?c';
|
import Google from '@/assets/ico/vendor/google.svg?c';
|
||||||
import Github from '@/assets/ico/vendor/github.svg?c';
|
import Github from '@/assets/ico/vendor/github.svg?c';
|
||||||
|
|
||||||
import { BadgeIcon } from '@@/BoxSelector/BadgeIcon';
|
import { BadgeIcon } from '@@/BadgeIcon';
|
||||||
|
|
||||||
export const options = [
|
export const options = [
|
||||||
{
|
{
|
||||||
|
|
|
@ -30,7 +30,7 @@ import { TableColumnHeaderAngular } from '@@/datatables/TableHeaderCell';
|
||||||
import { DashboardItem } from '@@/DashboardItem';
|
import { DashboardItem } from '@@/DashboardItem';
|
||||||
import { SearchBar } from '@@/datatables/SearchBar';
|
import { SearchBar } from '@@/datatables/SearchBar';
|
||||||
import { FallbackImage } from '@@/FallbackImage';
|
import { FallbackImage } from '@@/FallbackImage';
|
||||||
import { BadgeIcon } from '@@/BoxSelector/BadgeIcon';
|
import { BadgeIcon } from '@@/BadgeIcon';
|
||||||
import { TeamsSelector } from '@@/TeamsSelector';
|
import { TeamsSelector } from '@@/TeamsSelector';
|
||||||
import { PortainerSelect } from '@@/form-components/PortainerSelect';
|
import { PortainerSelect } from '@@/form-components/PortainerSelect';
|
||||||
|
|
||||||
|
@ -88,8 +88,6 @@ export const componentsModule = angular
|
||||||
'alt',
|
'alt',
|
||||||
'size',
|
'size',
|
||||||
'className',
|
'className',
|
||||||
'fallbackMode',
|
|
||||||
'fallbackClassName',
|
|
||||||
'feather',
|
'feather',
|
||||||
])
|
])
|
||||||
)
|
)
|
||||||
|
@ -106,7 +104,7 @@ export const componentsModule = angular
|
||||||
'datatableSearchbar',
|
'datatableSearchbar',
|
||||||
r2a(SearchBar, ['data-cy', 'onChange', 'value', 'placeholder'])
|
r2a(SearchBar, ['data-cy', 'onChange', 'value', 'placeholder'])
|
||||||
)
|
)
|
||||||
.component('boxSelectorBadgeIcon', r2a(BadgeIcon, ['featherIcon', 'icon']))
|
.component('badgeIcon', r2a(BadgeIcon, ['featherIcon', 'icon', 'size']))
|
||||||
.component(
|
.component(
|
||||||
'accessControlPanel',
|
'accessControlPanel',
|
||||||
r2a(withUIRouter(withReactQuery(withCurrentUser(AccessControlPanel))), [
|
r2a(withUIRouter(withReactQuery(withCurrentUser(AccessControlPanel))), [
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { Edit } from 'react-feather';
|
||||||
import { FeatureId } from '@/portainer/feature-flags/enums';
|
import { FeatureId } from '@/portainer/feature-flags/enums';
|
||||||
import Openldap from '@/assets/ico/vendor/openldap.svg?c';
|
import Openldap from '@/assets/ico/vendor/openldap.svg?c';
|
||||||
|
|
||||||
import { BadgeIcon } from '@@/BoxSelector/BadgeIcon';
|
import { BadgeIcon } from '@@/BadgeIcon';
|
||||||
|
|
||||||
const SERVER_TYPES = {
|
const SERVER_TYPES = {
|
||||||
CUSTOM: 0,
|
CUSTOM: 0,
|
||||||
|
|
|
@ -7,7 +7,7 @@ import Proget from '@/assets/ico/vendor/proget.svg?c';
|
||||||
import Azure from '@/assets/ico/vendor/azure.svg?c';
|
import Azure from '@/assets/ico/vendor/azure.svg?c';
|
||||||
import Gitlab from '@/assets/ico/vendor/gitlab.svg?c';
|
import Gitlab from '@/assets/ico/vendor/gitlab.svg?c';
|
||||||
|
|
||||||
import { BadgeIcon } from '@@/BoxSelector/BadgeIcon';
|
import { BadgeIcon } from '@@/BadgeIcon';
|
||||||
|
|
||||||
export const options = [
|
export const options = [
|
||||||
{
|
{
|
||||||
|
|
|
@ -5,7 +5,7 @@ import Microsoft from '@/assets/ico/vendor/microsoft.svg?c';
|
||||||
import Ldap from '@/assets/ico/ldap.svg?c';
|
import Ldap from '@/assets/ico/ldap.svg?c';
|
||||||
import OAuth from '@/assets/ico/oauth.svg?c';
|
import OAuth from '@/assets/ico/oauth.svg?c';
|
||||||
|
|
||||||
import { BadgeIcon } from '@@/BoxSelector/BadgeIcon';
|
import { BadgeIcon } from '@@/BadgeIcon';
|
||||||
|
|
||||||
export const options = [
|
export const options = [
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { DownloadCloud, UploadCloud } from 'react-feather';
|
||||||
|
|
||||||
import { FeatureId } from '@/portainer/feature-flags/enums';
|
import { FeatureId } from '@/portainer/feature-flags/enums';
|
||||||
|
|
||||||
import { BadgeIcon } from '@@/BoxSelector/BadgeIcon';
|
import { BadgeIcon } from '@@/BadgeIcon';
|
||||||
|
|
||||||
export const options = [
|
export const options = [
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
import { Meta } from '@storybook/react';
|
||||||
|
|
||||||
|
import { BadgeIcon, BadgeSize, Props } from './BadgeIcon';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
component: BadgeIcon,
|
||||||
|
title: 'Components/BadgeIcon',
|
||||||
|
argTypes: {
|
||||||
|
size: {
|
||||||
|
control: {
|
||||||
|
type: 'select',
|
||||||
|
options: ['md', 'lg', 'xl', '2xl', '3xl'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
icon: {
|
||||||
|
control: {
|
||||||
|
type: 'select',
|
||||||
|
options: ['edit', 'info', 'smile', 'users'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} as Meta<Props>;
|
||||||
|
|
||||||
|
// : JSX.IntrinsicAttributes & PropsWithChildren<Props>
|
||||||
|
function Template({
|
||||||
|
size = '3xl',
|
||||||
|
icon = 'edit',
|
||||||
|
}: {
|
||||||
|
size?: BadgeSize;
|
||||||
|
icon: string;
|
||||||
|
}) {
|
||||||
|
return <BadgeIcon icon={icon} size={size} featherIcon />;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Example = Template.bind({});
|
|
@ -0,0 +1,45 @@
|
||||||
|
import clsx from 'clsx';
|
||||||
|
|
||||||
|
import { Icon, IconProps } from '@@/Icon';
|
||||||
|
|
||||||
|
export type BadgeSize = 'md' | 'lg' | 'xl' | '2xl' | '3xl';
|
||||||
|
|
||||||
|
export interface Props extends IconProps {
|
||||||
|
size?: BadgeSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function BadgeIcon({ icon, featherIcon, size = '3xl' }: Props) {
|
||||||
|
const sizeClasses = iconSizeToClasses(size);
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={clsx(
|
||||||
|
sizeClasses,
|
||||||
|
`badge-icon
|
||||||
|
bg-blue-3 text-blue-8
|
||||||
|
th-dark:bg-gray-9 th-dark:text-blue-3
|
||||||
|
rounded-full
|
||||||
|
inline-flex items-center justify-center
|
||||||
|
`
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<Icon icon={icon} feather={featherIcon} className="feather !flex" />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function iconSizeToClasses(size: BadgeSize) {
|
||||||
|
switch (size) {
|
||||||
|
case 'md':
|
||||||
|
return 'h-6 w-6 text-md';
|
||||||
|
case 'lg':
|
||||||
|
return 'h-8 w-8 text-lg';
|
||||||
|
case 'xl':
|
||||||
|
return 'h-10 w-10 text-xl';
|
||||||
|
case '2xl':
|
||||||
|
return 'h-12 w-12 text-2xl';
|
||||||
|
case '3xl':
|
||||||
|
return 'h-14 w-14 text-3xl';
|
||||||
|
default:
|
||||||
|
return 'h-14 w-14 text-3xl';
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
export { BadgeIcon } from './BadgeIcon';
|
|
@ -1,19 +0,0 @@
|
||||||
import { Icon, IconProps } from '@@/Icon';
|
|
||||||
|
|
||||||
type Props = IconProps;
|
|
||||||
|
|
||||||
export function BadgeIcon({ icon, featherIcon }: Props) {
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={`badge-icon
|
|
||||||
text-3xl h-14 w-14
|
|
||||||
bg-blue-3 text-blue-8
|
|
||||||
th-dark:bg-gray-9 th-dark:text-blue-3
|
|
||||||
rounded-full
|
|
||||||
inline-flex items-center justify-center
|
|
||||||
`}
|
|
||||||
>
|
|
||||||
<Icon icon={icon} feather={featherIcon} className="feather !flex" />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -2,7 +2,8 @@ import { Edit, FileText, Globe, Upload } from 'react-feather';
|
||||||
|
|
||||||
import GitIcon from '@/assets/ico/git.svg?c';
|
import GitIcon from '@/assets/ico/git.svg?c';
|
||||||
|
|
||||||
import { BadgeIcon } from '../BadgeIcon';
|
import { BadgeIcon } from '@@/BadgeIcon';
|
||||||
|
|
||||||
import { BoxSelectorOption } from '../types';
|
import { BoxSelectorOption } from '../types';
|
||||||
|
|
||||||
export const editor: BoxSelectorOption<'editor'> = {
|
export const editor: BoxSelectorOption<'editor'> = {
|
||||||
|
|
|
@ -1,18 +1,15 @@
|
||||||
import clsx from 'clsx';
|
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
import { Icon, IconMode, IconSize } from './Icon';
|
import { BadgeIcon, BadgeSize } from './BadgeIcon/BadgeIcon';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
// props for the image to load
|
// props for the image to load
|
||||||
src: string; // a link to an external image
|
src: string; // a link to an external image
|
||||||
fallbackIcon: string;
|
fallbackIcon: string;
|
||||||
alt?: string;
|
alt?: string;
|
||||||
size?: IconSize;
|
size?: BadgeSize;
|
||||||
className?: string;
|
className?: string;
|
||||||
// additional fallback icon props
|
// additional fallback badge props
|
||||||
fallbackMode?: IconMode;
|
|
||||||
fallbackClassName?: string;
|
|
||||||
feather?: boolean;
|
feather?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,22 +19,18 @@ export function FallbackImage({
|
||||||
alt,
|
alt,
|
||||||
size,
|
size,
|
||||||
className,
|
className,
|
||||||
fallbackMode,
|
|
||||||
fallbackClassName,
|
|
||||||
feather,
|
feather,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const [error, setError] = useState(false);
|
const [error, setError] = useState(false);
|
||||||
|
|
||||||
const classes = clsx(className, { [`icon-${size}`]: size });
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setError(false);
|
setError(false);
|
||||||
}, [src]);
|
}, [src]);
|
||||||
|
|
||||||
if (!error) {
|
if (!error && src) {
|
||||||
return (
|
return (
|
||||||
<img
|
<img
|
||||||
className={classes}
|
className={className}
|
||||||
src={src}
|
src={src}
|
||||||
alt={alt}
|
alt={alt}
|
||||||
onError={() => setError(true)}
|
onError={() => setError(true)}
|
||||||
|
@ -46,13 +39,5 @@ export function FallbackImage({
|
||||||
}
|
}
|
||||||
|
|
||||||
// fallback icon if there is an error loading the image
|
// fallback icon if there is an error loading the image
|
||||||
return (
|
return <BadgeIcon icon={fallbackIcon} featherIcon={feather} size={size} />;
|
||||||
<Icon
|
|
||||||
icon={fallbackIcon}
|
|
||||||
feather={feather}
|
|
||||||
className={fallbackClassName}
|
|
||||||
size={size}
|
|
||||||
mode={fallbackMode}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { ownershipIcon } from '@/portainer/filters/filters';
|
||||||
import { Team } from '@/react/portainer/users/teams/types';
|
import { Team } from '@/react/portainer/users/teams/types';
|
||||||
|
|
||||||
import { BoxSelectorOption } from '@@/BoxSelector/types';
|
import { BoxSelectorOption } from '@@/BoxSelector/types';
|
||||||
import { BadgeIcon } from '@@/BoxSelector/BadgeIcon';
|
import { BadgeIcon } from '@@/BadgeIcon';
|
||||||
|
|
||||||
import { ResourceControlOwnership } from '../types';
|
import { ResourceControlOwnership } from '../types';
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue