diff --git a/apps/console-v5/src/app/components/header/breadcrumbs/breadcrumbs.tsx b/apps/console-v5/src/app/components/header/breadcrumbs/breadcrumbs.tsx index b93a415ee6d..457cc4dcc07 100644 --- a/apps/console-v5/src/app/components/header/breadcrumbs/breadcrumbs.tsx +++ b/apps/console-v5/src/app/components/header/breadcrumbs/breadcrumbs.tsx @@ -91,7 +91,9 @@ export function Breadcrumbs() { to: '/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/overview', params: { organizationId, projectId, environmentId, serviceId: service.id }, }).href, - prefix: , + prefix: ( + + ), suffix: , })) diff --git a/libs/domains/services/feature/src/lib/service-avatar-switcher/service-avatar-switcher.tsx b/libs/domains/services/feature/src/lib/service-avatar-switcher/service-avatar-switcher.tsx index bfc78bd7985..72a2ada58b3 100644 --- a/libs/domains/services/feature/src/lib/service-avatar-switcher/service-avatar-switcher.tsx +++ b/libs/domains/services/feature/src/lib/service-avatar-switcher/service-avatar-switcher.tsx @@ -43,7 +43,7 @@ export function ServiceAvatarSwitcher({ onChange, service }: ServiceAvatarSwitch setSearchTerm(value)} autofocus /> {filteredIcons.length > 0 ? (
- {filteredIcons.map(({ icon, title, uri }) => { + {filteredIcons.map(({ icon, title, uri, className }) => { const isSelected = uri === service.icon_uri // XXX: corner case as application and container have the same icon, we want to hide one of them. if (uri === 'app://qovery-console/container') { @@ -52,18 +52,23 @@ export function ServiceAvatarSwitcher({ onChange, service }: ServiceAvatarSwitch return ( - {title} handleClick(uri)} - /> + > + {title} + ) diff --git a/libs/domains/services/feature/src/lib/service-avatar/service-avatar.tsx b/libs/domains/services/feature/src/lib/service-avatar/service-avatar.tsx index 21fdf73f223..961256a8ad9 100644 --- a/libs/domains/services/feature/src/lib/service-avatar/service-avatar.tsx +++ b/libs/domains/services/feature/src/lib/service-avatar/service-avatar.tsx @@ -1,3 +1,4 @@ +import clsx from 'clsx' import { type ComponentPropsWithoutRef, type ElementRef, forwardRef } from 'react' import { match } from 'ts-pattern' import { type AnyService } from '@qovery/domains/services/data-access' @@ -6,8 +7,11 @@ import { type IconURI, ServiceIcons } from '../service-icon/service-icon' // XXX: Todo remove `job_type` // https://qovery.atlassian.net/jira/software/projects/FRT/boards/23?selectedIssue=FRT-1427 +type ServiceAvatarRadius = 'none' | 'sm' | 'md' | 'full' + export interface ServiceAvatarProps extends Omit, 'fallback' | 'size'> { size?: ComponentPropsWithoutRef['size'] | 'custom' + serviceAvatarRadius?: ServiceAvatarRadius service: | { icon_uri: string @@ -22,7 +26,7 @@ export interface ServiceAvatarProps extends Omit, ServiceAvatarProps>(function ServiceAvatar( - { service, size, className, ...props }, + { service, size, className, radius, serviceAvatarRadius = 'full', ...props }, ref ) { const iconName = match(service) @@ -40,6 +44,7 @@ export const ServiceAvatar = forwardRef, ServiceAvatar , ServiceAvatar alt={service.serviceType} height="100%" width="100%" - className="max-h-full max-w-full rounded-full object-contain" + className={clsx( + 'max-h-full max-w-full object-contain', + `rounded-${serviceAvatarRadius}`, + serviceAvatar.className + )} /> ) : ( diff --git a/libs/domains/services/feature/src/lib/service-icon/service-icon.tsx b/libs/domains/services/feature/src/lib/service-icon/service-icon.tsx index 95daacd4861..06b39298323 100644 --- a/libs/domains/services/feature/src/lib/service-icon/service-icon.tsx +++ b/libs/domains/services/feature/src/lib/service-icon/service-icon.tsx @@ -39,6 +39,12 @@ import Svelte from 'devicon/icons/svelte/svelte-original.svg' import Terraform from 'devicon/icons/terraform/terraform-original.svg' import Vue from 'devicon/icons/vuejs/vuejs-original.svg' +type ServiceIcon = { + icon: string + title: string + className?: string +} + const Qovery = '/assets/logos/logo-icon.svg' const Datadog = '/assets/devicon/datadog.svg' const Crossplane = '/assets/devicon/crossplane.svg' @@ -53,7 +59,7 @@ const EC2 = '/assets/devicon/ec2.svg' const Lambda = '/assets/devicon/lambda.svg' const S3 = '/assets/devicon/s3.svg' -export const ServiceIcons = { +const serviceIcons = { 'app://qovery-console/lifecycle-job': { icon: '/assets/services/lifecycle-job.svg', title: 'LifecycleJob' }, 'app://qovery-console/cron-job': { icon: '/assets/services/cron-job.svg', title: 'CronJob' }, 'app://qovery-console/container': { icon: '/assets/services/application.svg', title: 'Container' }, @@ -67,17 +73,17 @@ export const ServiceIcons = { // Devicons 'app://qovery-console/apache': { icon: Apache, title: 'Apache' }, 'app://qovery-console/apacheairflow': { icon: ApacheAirflow, title: 'Apache Airflow' }, - 'app://qovery-console/apachekafka': { icon: ApacheKafka, title: 'Apache Kafka' }, + 'app://qovery-console/apachekafka': { icon: ApacheKafka, title: 'Apache Kafka', className: 'dark:invert' }, 'app://qovery-console/angular': { icon: Angular, title: 'Angular' }, 'app://qovery-console/aws': { icon: AWS, title: 'AWS' }, 'app://qovery-console/azure': { icon: Azure, title: 'Azure' }, - 'app://qovery-console/bash': { icon: Bash, title: 'Bash' }, + 'app://qovery-console/bash': { icon: Bash, title: 'Bash', className: 'dark:invert' }, 'app://qovery-console/cloudflare': { icon: Cloudflare, title: 'Cloudflare' }, 'app://qovery-console/couchbase': { icon: Couchbase, title: 'Couchbase' }, 'app://qovery-console/docker': { icon: Docker, title: 'Docker' }, 'app://qovery-console/elasticsearch': { icon: Elasticsearch, title: 'Elasticsearch' }, 'app://qovery-console/fastapi': { icon: FastAPI, title: 'FastAPI' }, - 'app://qovery-console/flask': { icon: Flask, title: 'Flask' }, + 'app://qovery-console/flask': { icon: Flask, title: 'Flask', className: 'dark:invert' }, 'app://qovery-console/gcp': { icon: GCP, title: 'GCP' }, 'app://qovery-console/golang': { icon: Golang, title: 'Golang' }, 'app://qovery-console/grafana': { icon: Grafana, title: 'Grafana' }, @@ -100,7 +106,7 @@ export const ServiceIcons = { 'app://qovery-console/react': { icon: React, title: 'React' }, 'app://qovery-console/redis': { icon: Redis, title: 'Redis' }, 'app://qovery-console/ruby': { icon: Ruby, title: 'Ruby' }, - 'app://qovery-console/rust': { icon: Rust, title: 'Rust' }, + 'app://qovery-console/rust': { icon: Rust, title: 'Rust', className: 'dark:invert' }, 'app://qovery-console/spring': { icon: Spring, title: 'Spring' }, 'app://qovery-console/svelte': { icon: Svelte, title: 'Svelte' }, 'app://qovery-console/terraform': { icon: Terraform, title: 'Terraform' }, @@ -116,10 +122,12 @@ export const ServiceIcons = { 'app://qovery-console/kubecost': { icon: Kubecost, title: 'Kubecost' }, 'app://qovery-console/qovery': { icon: Qovery, title: 'Qovery' }, 'app://qovery-console/scaleway': { icon: Scaleway, title: 'Scaleway' }, - 'app://qovery-console/temporal': { icon: Temporal, title: 'Temporal' }, + 'app://qovery-console/temporal': { icon: Temporal, title: 'Temporal', className: 'dark:invert' }, 'app://qovery-console/windmill': { icon: Windmill, title: 'Windmill' }, 'app://qovery-console/lambda': { icon: Lambda, title: 'Lambda' }, 'app://qovery-console/s3': { icon: S3, title: 'S3' }, } as const -export type IconURI = keyof typeof ServiceIcons +export type IconURI = keyof typeof serviceIcons + +export const ServiceIcons: Readonly> = serviceIcons diff --git a/libs/domains/services/feature/src/lib/service-new/service-new.tsx b/libs/domains/services/feature/src/lib/service-new/service-new.tsx index 224cf05a898..84e9305ac11 100644 --- a/libs/domains/services/feature/src/lib/service-new/service-new.tsx +++ b/libs/domains/services/feature/src/lib/service-new/service-new.tsx @@ -17,6 +17,7 @@ import { Badge, Button, ExternalLink, Heading, Icon, InputSearch, Link, Section import { useSupportChat } from '@qovery/shared/util-hooks' import { twMerge } from '@qovery/shared/util-js' import { TemplateIds } from '@qovery/shared/util-services' +import { ServiceIcons } from '../service-icon/service-icon' import { type ServiceTemplateOptionType, type ServiceTemplateType, @@ -26,8 +27,6 @@ import { const CloudFormationIcon = '/assets/devicon/cloudformation.svg' -const SERVICE_TEMPLATE_ICON_INVERT_DARK_TITLES = new Set(['Apache Kafka', 'Replibyte', 'Rust', 'Flask', 'Temporal']) - const getEnvironmentBasePath = (organizationId: string, projectId: string, environmentId: string) => `/organization/${organizationId}/project/${projectId}/environment/${environmentId}` @@ -196,12 +195,14 @@ function CardOption({ recommended, badge, template_id, + icon_uri, organizationId, projectId, environmentId, isTerraformFeatureFlag, onUpgradePlanClick, }: CardOptionProps) { + const iconClassName = ServiceIcons[icon_uri].className const pathSuffix = servicePathSuffix(type, parentSlug, slug) const to = pathSuffix ? getServicesPath(organizationId, projectId, environmentId, pathSuffix) : undefined @@ -216,7 +217,7 @@ function CardOption({ onKeyDown={(e) => e.key === 'Enter' && onUpgradePlanClick()} className="flex cursor-pointer items-start gap-3 rounded-sm border border-neutral bg-surface-neutral-subtle p-3 transition hover:bg-surface-neutral-componentHover" > - {title} + {title} {title} @@ -256,7 +257,7 @@ function CardOption({ }) } > - {title} + {title} {title} @@ -299,6 +300,7 @@ function CardService({ projectId, environmentId, cloudProvider, + icon_uri, isTerraformFeatureFlag, onUpgradePlanClick, }: Omit & { @@ -312,6 +314,7 @@ function CardService({ onUpgradePlanClick?: () => void }) { const [expanded, setExpanded] = useState(false) + const iconClassName = icon_uri ? ServiceIcons[icon_uri].className : undefined if (options && !slug) { return null @@ -331,7 +334,7 @@ function CardService({
{typeof icon === 'string' ? ( - {title} + {title} ) : ( cloneElement(icon as ReactElement, { - className: twMerge('w-10', SERVICE_TEMPLATE_ICON_INVERT_DARK_TITLES.has(title) && 'dark:invert'), + className: twMerge('w-10', iconClassName), }) )} @@ -439,17 +435,10 @@ function CardService({
{typeof icon === 'string' ? ( - {title} + {title} ) : ( cloneElement(icon as ReactElement, { - className: twMerge('w-10', SERVICE_TEMPLATE_ICON_INVERT_DARK_TITLES.has(title) && 'dark:invert'), + className: twMerge('w-10', iconClassName), }) )}
diff --git a/libs/domains/services/feature/src/lib/service-overview/service-header/service-header.tsx b/libs/domains/services/feature/src/lib/service-overview/service-header/service-header.tsx index 83f0dfdc992..be422ebe947 100644 --- a/libs/domains/services/feature/src/lib/service-overview/service-header/service-header.tsx +++ b/libs/domains/services/feature/src/lib/service-overview/service-header/service-header.tsx @@ -108,8 +108,9 @@ function ServiceHeaderContent({ environment, serviceId, service }: ServiceHeader
) - .with('UNAVAILABLE', () => ) + .with('UNAVAILABLE', () => ) .exhaustive() return (