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 @@ -5,22 +5,17 @@ import { Banner } from '@qovery/shared/ui'
import { useSupportChat } from '@qovery/shared/util-hooks'
import { pluralize } from '@qovery/shared/util-js'

const FREE_TRIAL_ADD_CREDIT_CARD_MESSAGE =
'You are on a free trial. Add a credit card to unlock managed cluster creation. If you need help, please contact us.'

export function OrganizationFreeTrialBanner() {
const { organizationId = '' } = useParams({ strict: false })
const { pathname } = useLocation()
const {
isClusterCreationRestricted: hasRestriction,
isNoCreditCardRestriction,
isInActiveFreeTrial,
remainingTrialDays,
hasNoCreditCard,
} = useClusterCreationRestriction({
organizationId,
})
const { showChat } = useSupportChat()
const { showChat, showPylonForm } = useSupportChat()

const isOnOrganizationBillingSummaryPage = pathname.includes(
SETTINGS_URL(organizationId) + SETTINGS_BILLING_SUMMARY_URL
Expand All @@ -32,7 +27,7 @@ export function OrganizationFreeTrialBanner() {
return null
}

if (hasRestriction && !isNoCreditCardRestriction) {
if (hasRestriction) {
return (
<Banner color="red" buttonIconRight="arrow-right" buttonLabel="Contact us" onClickButton={() => showChat()}>
Deployments are restricted on your organization. Please contact support to resolve this issue.
Expand All @@ -41,11 +36,15 @@ export function OrganizationFreeTrialBanner() {
}

const days = (remainingTrialDays ?? 0) + 1
const expiryMessage = `Your free trial plan expires ${days} ${pluralize(days, 'day')} from now. If you need help, please contact us.`
const message = hasNoCreditCard && isNoCreditCardRestriction ? FREE_TRIAL_ADD_CREDIT_CARD_MESSAGE : expiryMessage
const message = `Your free trial plan expires ${days} ${pluralize(days, 'day')} from now. Activate your plan to keep full access to Qovery.`

return (
<Banner color="brand" buttonIconRight="arrow-right" buttonLabel="Need help" onClickButton={() => showChat()}>
<Banner
color="brand"
buttonIconRight="arrow-right"
buttonLabel="Activate my plan"
onClickButton={() => showPylonForm('ask-for-activation')}
>
{message}
</Banner>
)
Expand Down
52 changes: 26 additions & 26 deletions apps/console/src/routeTree.gen.ts

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@ const tabs = [
},
]

const terraformTab = {
id: 'terraform',
label: 'Terraform variables',
iconName: 'key' as IconName,
routeId:
'/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/variables/terraform',
}

const OutletLoader = () => (
<div className="flex h-64 items-center justify-center">
<LoaderSpinner className="w-6" />
Expand Down Expand Up @@ -74,7 +82,8 @@ function RouteComponent() {

if (shouldRedirect) return null

const activeTabId = tabs.find((tab) => matchRoute({ to: tab.routeId }))?.id
const serviceTabs = service?.serviceType === 'TERRAFORM' ? [...tabs, terraformTab] : tabs
const activeTabId = serviceTabs.find((tab) => matchRoute({ to: tab.routeId }))?.id

return (
<div className="container mx-auto flex min-h-page-container flex-col pb-16 pt-6">
Expand All @@ -96,6 +105,15 @@ function RouteComponent() {
<TabLabel label={tab.label} isNew={tab.id === 'external-secrets'} />
</Navbar.Item>
))}
{service?.serviceType === 'TERRAFORM' && (
<>
<div aria-hidden className="mx-4 h-5 border-l border-neutral" />
<Navbar.Item id={terraformTab.id} to={terraformTab.routeId}>
<Icon iconName={terraformTab.iconName} iconStyle="regular" />
<TabLabel label={terraformTab.label} />
</Navbar.Item>
</>
)}
</Navbar.Root>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createFileRoute, useParams } from '@tanstack/react-router'
import { createFileRoute } from '@tanstack/react-router'
import { Suspense } from 'react'
import { FormProvider, useForm, useFormContext } from 'react-hook-form'
import { match } from 'ts-pattern'
Expand All @@ -9,39 +9,32 @@ import {
} from '@qovery/domains/service-terraform/feature'
import { type Terraform } from '@qovery/domains/services/data-access'
import { type TerraformGeneralData, useEditService, useService } from '@qovery/domains/services/feature'
import { SettingsHeading } from '@qovery/shared/console-shared'
import { Button, LoaderSpinner, Section } from '@qovery/shared/ui'
import { Button, LoaderSpinner } from '@qovery/shared/ui'
import { useDocumentTitle } from '@qovery/shared/util-hooks'
import { buildEditServicePayload } from '@qovery/shared/util-services'

export const Route = createFileRoute(
'/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/settings/terraform-variables'
'/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/variables/terraform'
)({
component: RouteComponent,
})

const TerraformVariablesLoader = () => (
<div className="flex min-h-page-container items-center justify-center">
<LoaderSpinner />
<div className="flex h-64 items-center justify-center">
<LoaderSpinner className="w-6" />
</div>
)

const TerraformVariablesSettingsForm = ({ service }: { service: Terraform }) => {
const { organizationId = '', projectId = '', environmentId = '' } = Route.useParams()
const TerraformVariablesForm = ({ service }: { service: Terraform }) => {
const { organizationId, projectId, environmentId } = Route.useParams()
const { handleSubmit } = useFormContext<TerraformGeneralData>()
const { serializeForApi, tfVarFiles, errors } = useTerraformVariablesContext()

const { mutate: editService, isLoading: isLoadingEditService } = useEditService({
organizationId,
projectId,
environmentId,
})

if (service?.serviceType !== 'TERRAFORM') {
return null
}

const onSubmit = handleSubmit(() => {
// Edit the service with the updated variables and the updated order of tfvars files
const payload = buildEditServicePayload({
service,
request: {
Expand All @@ -59,57 +52,48 @@ const TerraformVariablesSettingsForm = ({ service }: { service: Terraform }) =>
})

return (
<>
<TerraformVariablesTable />
<div className="mt-10 flex justify-end">
<Button type="submit" size="lg" onClick={onSubmit} loading={isLoadingEditService} disabled={errors.size > 0}>
Save
</Button>
</div>
</>
<div className="bg-background">
<TerraformVariablesTable
className="rounded-none border-0"
headerActions={
<Button type="submit" size="md" onClick={onSubmit} loading={isLoadingEditService} disabled={errors.size > 0}>
Save
</Button>
}
/>
</div>
)
}

const TerraformVariablesContent = ({ service }: { service: Terraform }) => {
const methods = useForm<TerraformGeneralData>({
mode: 'onChange',
defaultValues: match(service)
.with({ serviceType: 'TERRAFORM' }, (s) => s)
.with({ serviceType: 'TERRAFORM' }, (terraformService) => terraformService)
.otherwise(() => ({})),
})

return (
<Section className="px-8 pb-8 pt-6">
<SettingsHeading
title="Terraform variables"
description="Select .tfvars files and configure variable values for your Terraform deployment"
/>
<div className="w-full">
<FormProvider {...methods}>
<TerraformVariablesProvider>
<TerraformVariablesSettingsForm service={service} />
</TerraformVariablesProvider>
</FormProvider>
</div>
</Section>
<FormProvider {...methods}>
<TerraformVariablesProvider>
<TerraformVariablesForm service={service} />
</TerraformVariablesProvider>
</FormProvider>
)
}

const TerraformVariablesWrapper = () => {
const { serviceId } = useParams({ strict: false })
const { data: service } = useService({ serviceId })
function RouteComponent() {
const { environmentId, serviceId } = Route.useParams()
const { data: service } = useService({ environmentId, serviceId, suspense: true })
useDocumentTitle('Terraform variables - Service')

if (service?.serviceType !== 'TERRAFORM') {
return null
}

return <TerraformVariablesContent service={service} />
}

function RouteComponent() {
return (
<Suspense fallback={<TerraformVariablesLoader />}>
<TerraformVariablesWrapper />
<TerraformVariablesContent service={service} />
</Suspense>
)
}
Loading
Loading