- {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 (
-
handleClick(uri)}
- />
+ >
+
+
)
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}
@@ -256,7 +257,7 @@ function CardOption({
})
}
>
-
+
{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' ? (
-

+

) : (
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 (