Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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: <ServiceAvatar service={service} size="custom" className="h-5 w-5" />,
prefix: (
<ServiceAvatar service={service} size="custom" className="h-5 w-5" serviceAvatarRadius="sm" radius="none" />
),
suffix: <ServiceStateChip mode="running" environmentId={service.environment?.id} serviceId={service.id} />,
}))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export function ServiceAvatarSwitcher({ onChange, service }: ServiceAvatarSwitch
<InputSearch placeholder="Search..." className="mb-1" onChange={(value) => setSearchTerm(value)} autofocus />
{filteredIcons.length > 0 ? (
<div className="grid grid-cols-8 gap-2 text-sm text-neutral-subtle">
{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') {
Expand All @@ -52,18 +52,23 @@ export function ServiceAvatarSwitcher({ onChange, service }: ServiceAvatarSwitch
return (
<Popover.Close key={title}>
<Tooltip content={title}>
<img
<button
type="button"
className={clsx(
'h-[38px] max-h-[38px] w-[38px] max-w-[38px] cursor-pointer select-none rounded border p-2',
isSelected && 'border-brand-strong bg-surface-brand-subtle',
!isSelected && 'border-neutral transition hover:border-neutral-component'
)}
width="100%"
height="100%"
src={icon}
alt={title}
onClick={() => handleClick(uri)}
/>
>
<img
className={clsx('h-full w-full object-contain', className)}
width="100%"
height="100%"
src={icon}
alt={title}
/>
</button>
</Tooltip>
</Popover.Close>
)
Expand Down
Original file line number Diff line number Diff line change
@@ -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'
Expand All @@ -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<ComponentPropsWithoutRef<typeof Avatar>, 'fallback' | 'size'> {
size?: ComponentPropsWithoutRef<typeof Avatar>['size'] | 'custom'
serviceAvatarRadius?: ServiceAvatarRadius
service:
| {
icon_uri: string
Expand All @@ -22,7 +26,7 @@ export interface ServiceAvatarProps extends Omit<ComponentPropsWithoutRef<typeof
}

export const ServiceAvatar = forwardRef<ElementRef<typeof Avatar>, ServiceAvatarProps>(function ServiceAvatar(
{ service, size, className, ...props },
{ service, size, className, radius, serviceAvatarRadius = 'full', ...props },
ref
) {
const iconName = match(service)
Expand All @@ -40,6 +44,7 @@ export const ServiceAvatar = forwardRef<ElementRef<typeof Avatar>, ServiceAvatar
<Avatar
ref={ref}
size={size}
radius={radius}
className={className}
fallback={
serviceAvatar ? (
Expand All @@ -48,7 +53,11 @@ export const ServiceAvatar = forwardRef<ElementRef<typeof Avatar>, 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
)}
/>
) : (
<Icon name={iconName} height="100%" width="100%" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand All @@ -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' },
Expand All @@ -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' },
Expand All @@ -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' },
Expand All @@ -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<Record<IconURI, ServiceIcon>> = serviceIcons
35 changes: 12 additions & 23 deletions libs/domains/services/feature/src/lib/service-new/service-new.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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}`

Expand Down Expand Up @@ -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

Expand All @@ -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"
>
<img className="mt-1 select-none" width={24} height={24} src={icon} alt={title} />
<img className={twMerge('mt-1 select-none', iconClassName)} width={24} height={24} src={icon} alt={title} />
<span className="flex flex-1 flex-col gap-1">
<span className="inline-flex items-center gap-2 text-ssm font-medium text-neutral">
{title}
Expand Down Expand Up @@ -256,7 +257,7 @@ function CardOption({
})
}
>
<img className="mt-1 select-none" width={24} height={24} src={icon} alt={title} />
<img className={twMerge('mt-1 select-none', iconClassName)} width={24} height={24} src={icon} alt={title} />
<span>
<span className="inline-flex items-center gap-2 text-ssm font-medium text-neutral">
{title}
Expand Down Expand Up @@ -299,6 +300,7 @@ function CardService({
projectId,
environmentId,
cloudProvider,
icon_uri,
isTerraformFeatureFlag,
onUpgradePlanClick,
}: Omit<ServiceTemplateType, 'cloud_provider'> & {
Expand All @@ -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
Expand All @@ -331,7 +334,7 @@ function CardService({
<div className="flex w-full flex-col gap-8">
<div className="relative flex gap-6">
<img
className={twMerge('select-none', SERVICE_TEMPLATE_ICON_INVERT_DARK_TITLES.has(title) && 'dark:invert')}
className={twMerge('select-none', iconClassName)}
width={52}
height={52}
src={icon as string}
Expand Down Expand Up @@ -396,17 +399,10 @@ function CardService({
</div>
<span className="relative">
{typeof icon === 'string' ? (
<img
className={twMerge(
'max-h-10 w-14 select-none',
SERVICE_TEMPLATE_ICON_INVERT_DARK_TITLES.has(title) && 'dark:invert'
)}
src={icon}
alt={title}
/>
<img className={twMerge('max-h-10 w-14 select-none', iconClassName)} src={icon} alt={title} />
) : (
cloneElement(icon as ReactElement, {
className: twMerge('w-10', SERVICE_TEMPLATE_ICON_INVERT_DARK_TITLES.has(title) && 'dark:invert'),
className: twMerge('w-10', iconClassName),
})
)}
</span>
Expand Down Expand Up @@ -439,17 +435,10 @@ function CardService({
</div>
<div className="flex items-center">
{typeof icon === 'string' ? (
<img
className={twMerge(
'max-h-10 w-14 select-none',
SERVICE_TEMPLATE_ICON_INVERT_DARK_TITLES.has(title) && 'dark:invert'
)}
src={icon}
alt={title}
/>
<img className={twMerge('max-h-10 w-14 select-none', iconClassName)} src={icon} alt={title} />
) : (
cloneElement(icon as ReactElement, {
className: twMerge('w-10', SERVICE_TEMPLATE_ICON_INVERT_DARK_TITLES.has(title) && 'dark:invert'),
className: twMerge('w-10', iconClassName),
})
)}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,9 @@ function ServiceHeaderContent({ environment, serviceId, service }: ServiceHeader
<div className="flex items-center justify-between gap-2">
<div className="flex items-center gap-2">
<ServiceAvatar
border="solid"
size="sm"
radius="none"
serviceAvatarRadius="md"
service={
service.serviceType === 'JOB'
? {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ export function StatusChip({
'RECAP',
() => <ErrorIcon className={iconClass} />
)
.with('UNAVAILABLE', () => <WarningIcon />)
.with('UNAVAILABLE', () => <WarningIcon className={iconClass} />)
.exhaustive()

return (
Expand Down
Loading