Skip to content
Draft
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
591 changes: 374 additions & 217 deletions apps/console-v5/src/routeTree.gen.ts

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { createFileRoute } from '@tanstack/react-router'
import { SettingsDeploymentRules } from '@qovery/domains/environments/feature'

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

function RouteComponent() {
return <SettingsDeploymentRules />
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { Outlet, createFileRoute, useParams } from '@tanstack/react-router'
import { Sidebar } from '@qovery/shared/ui'

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

function RouteComponent() {
const { organizationId, projectId, environmentId } = useParams({ strict: false })
const pathSettings = `/organization/${organizationId}/project/${projectId}/environment/${environmentId}/settings`
const deploymentRulesLink = {
title: 'Deployment rules',
to: `${pathSettings}/deployment-rules`,
icon: 'browsers' as const,
}

const LINKS_SETTINGS = [deploymentRulesLink]

return (
<div className="flex min-h-0 flex-1">
<aside className="relative min-h-[calc(100vh-2.75rem-4rem)] w-52 shrink-0 self-stretch border-r border-neutral">
<div className="sticky top-16">
<Sidebar.Root className="mt-6">
{LINKS_SETTINGS.map((link) => (
<Sidebar.Item key={link.to} to={link.to} icon={link.icon}>
{link.title}
</Sidebar.Item>
))}
</Sidebar.Root>
</div>
</aside>
<div className="min-w-0 flex-1">
<div className="container mx-auto px-0">
<Outlet />
</div>
</div>
</div>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ function RouteComponent() {

return (
<div className="flex min-h-0 flex-1">
<aside className="relative min-h-[calc(100vh-2.75rem-4rem)] w-52 shrink-0 self-stretch border-r border-neutral">
<aside className="border-neutral relative min-h-[calc(100vh-2.75rem-4rem)] w-52 shrink-0 self-stretch border-r">
<div className="sticky top-16">
<Sidebar.Root className="mt-6">
{LINKS_SETTINGS.map((link) => (
Expand Down
11 changes: 9 additions & 2 deletions apps/console-v5/src/routes/_authenticated/organization/route.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,12 @@ const ENVIRONMENT_TABS: NavigationTab[] = [
iconName: 'table-layout',
routeId: '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/overview',
},
{
id: 'settings',
label: 'Settings',
iconName: 'gear-complex',
routeId: '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/settings',
},
]

function createRoutePatternRegex(routeIdPattern: string): RegExp {
Expand Down Expand Up @@ -283,6 +289,7 @@ const fullWidthRouteIds: FileRouteTypes['id'][] = [
'/_authenticated/organization/$organizationId/cluster/$clusterId/cluster-logs',
'/_authenticated/organization/$organizationId/cluster/$clusterId/settings',
'/_authenticated/organization/$organizationId/project/$projectId/settings',
'/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/settings',
]

function useFullWidthLayout(): boolean {
Expand Down Expand Up @@ -322,14 +329,14 @@ function OrganizationRoute() {
}

return (
<div className="flex h-dvh w-full flex-col bg-background">
<div className="bg-background flex h-dvh w-full flex-col">
{/* TODO: Conflicts with body main:not(.h-screen, .layout-onboarding) */}
<div className="min-h-0 flex-1 overflow-auto">
<Suspense fallback={<MainLoader />}>
<>
<Header />

<div className="sticky top-0 z-header border-b border-neutral bg-background-secondary px-4">
<div className="z-header border-neutral bg-background-secondary sticky top-0 border-b px-4">
<Navbar.Root activeId={activeTabId} className="container relative top-[1px] mx-0 -mt-[1px]">
{navigationContext && <NavigationBar context={navigationContext} />}
</Navbar.Root>
Expand Down
1 change: 1 addition & 0 deletions libs/domains/environments/feature/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,4 @@ export * from './lib/hooks/use-lifecycle-template/use-lifecycle-template'
export * from './lib/hooks/use-deploy-all-services/use-deploy-all-services'
export * from './lib/hooks/use-service-count/use-service-count'
export * from './lib/environments-table/environments-table'
export * from './lib/settings-deployment-rules/settings-deployment-rules'
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
import { useParams } from '@tanstack/react-router'
import { type EnvironmentDeploymentRule } from 'qovery-typescript-axios'
import { useEffect, useState } from 'react'
import { Controller, type FieldValues, useForm } from 'react-hook-form'
import { NeedHelp } from '@qovery/shared/assistant/feature'
import { timezoneValues, weekdaysValues } from '@qovery/shared/enums'
import { BlockContent, Button, Heading, InputSelect, InputText, InputToggle, Section } from '@qovery/shared/ui'
import { dateToHours } from '@qovery/shared/util-dates'
import { useDeploymentRule } from '../hooks/use-deployment-rule/use-deployment-rule'
import { useEditDeploymentRule } from '../hooks/use-edit-deployment-rule/use-edit-deployment-rule'

export const handleSubmit = (data: FieldValues, environmentDeploymentRules?: EnvironmentDeploymentRule) => {
const cloneEnvironmentDeploymentRules = Object.assign({}, environmentDeploymentRules)
cloneEnvironmentDeploymentRules.auto_stop = data['auto_stop']
cloneEnvironmentDeploymentRules.weekdays = data['weekdays']
cloneEnvironmentDeploymentRules.start_time = `1970-01-01T${data['start_time']}:00.000Z`
cloneEnvironmentDeploymentRules.stop_time = `1970-01-01T${data['stop_time']}:00.000Z`

return cloneEnvironmentDeploymentRules
}

export const SettingsDeploymentRules = () => {
const { environmentId = '' } = useParams({ strict: false })
const [loading, setLoading] = useState(false)

const { data: environmentDeploymentRules } = useDeploymentRule({ environmentId })
const { mutateAsync: editEnvironmentDeploymentRule } = useEditDeploymentRule()

const methods = useForm({
mode: 'onChange',
})

const watchAutoStop = methods.watch('auto_stop')

useEffect(() => {
const startTime = environmentDeploymentRules?.start_time && dateToHours(environmentDeploymentRules?.start_time)
const stopTime = environmentDeploymentRules?.stop_time && dateToHours(environmentDeploymentRules?.stop_time)

methods.setValue('auto_stop', environmentDeploymentRules?.auto_stop)
methods.setValue('timezone', environmentDeploymentRules?.timezone || 'UTC')
methods.setValue('start_time', startTime)
methods.setValue('stop_time', stopTime)
methods.setValue('weekdays', environmentDeploymentRules?.weekdays)
}, [methods, environmentDeploymentRules])

const onSubmit = methods.handleSubmit(async (data) => {
if (data && environmentDeploymentRules) {
setLoading(true)
const cloneEnvironmentDeploymentRules = handleSubmit(data, environmentDeploymentRules)

await editEnvironmentDeploymentRule({
environmentId,
deploymentRuleId: environmentDeploymentRules?.id || '',
payload: cloneEnvironmentDeploymentRules,
})
setLoading(false)
}
})

return (
<div className="flex w-full flex-col justify-between">
<Section className="max-w-content-with-navigation-left p-8">
<div className="mb-8 flex w-full justify-between gap-2 border-b border-neutral">
<div className="flex w-full items-start justify-between gap-4 pb-6">
<div className="flex flex-col gap-2">
<Heading>Deployment rules</Heading>
<NeedHelp className="mt-2" />
</div>
</div>
</div>
<form onSubmit={onSubmit}>
<BlockContent title="Start & stop">
<div className="flex items-center gap-3">
<Controller
name="auto_stop"
control={methods.control}
render={({ field }) => (
<InputToggle
dataTestId="auto-stop"
value={field.value}
onChange={field.onChange}
title="Deploy on specific timeframe"
description="Your environment will be automatically started and stopped on a specific timeframe."
forceAlignTop
small
/>
)}
/>
</div>
{watchAutoStop && (
<>
<Controller
name="weekdays"
control={methods.control}
rules={{ required: 'Please enter minimum one day.' }}
render={({ field, fieldState: { error } }) => (
<InputSelect
dataTestId="weekdays"
label="Which days"
value={field.value}
options={weekdaysValues}
error={error?.message}
onChange={field.onChange}
className="mb-3 mt-5"
isMulti={true}
/>
)}
/>
<Controller
name="timezone"
control={methods.control}
render={({ field, fieldState: { error } }) => (
<InputSelect
dataTestId="timezone"
label="Timezone"
options={timezoneValues}
onChange={field.onChange}
value={field.value}
error={error?.message}
className="mb-3"
disabled
/>
)}
/>
<div className="flex w-full gap-3">
<Controller
name="start_time"
control={methods.control}
rules={{ required: 'Please enter a start time.' }}
render={({ field, fieldState: { error } }) => (
<InputText
dataTestId="start-time"
name={field.name}
type="time"
onChange={field.onChange}
value={field.value}
error={error?.message}
label="Start time"
className="flex-grow"
/>
)}
/>
<Controller
name="stop_time"
control={methods.control}
rules={{ required: 'Please enter a stop time.' }}
render={({ field, fieldState: { error } }) => (
<InputText
dataTestId="stop-time"
name={field.name}
type="time"
onChange={field.onChange}
value={field.value}
error={error?.message}
label="Stop time"
className="flex-grow"
/>
)}
/>
</div>
</>
)}
</BlockContent>
<div className="flex justify-end">
<Button className="mb-6" type="submit" size="lg" disabled={!methods.formState.isValid} loading={loading}>
Save
</Button>
</div>
</form>
</Section>
</div>
)
}

This file was deleted.

Loading