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
@@ -1,9 +1,20 @@
import { createFileRoute } from '@tanstack/react-router'
import { createFileRoute, useParams } from '@tanstack/react-router'
import { useOrganization } from '@qovery/domains/organizations/feature'
import { AICopilotSettings } from '@qovery/shared/devops-copilot/feature'
import { useDocumentTitle } from '@qovery/shared/util-hooks'

export const Route = createFileRoute('/_authenticated/organization/$organizationId/settings/ai-copilot')({
component: RouteComponent,
})

function RouteComponent() {
return <div>Hello "/_authenticated/organization/$organizationId/settings/ai-copilot"!</div>
const { organizationId = '' } = useParams({ strict: false })
useDocumentTitle('AI Copilot - Organization settings')
const { data: organization } = useOrganization({ organizationId })

if (!organization) {
return null
}

return <AICopilotSettings organization={organization} />
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { useFeatureFlagVariantKey } from 'posthog-js/react'
import { type Organization } from 'qovery-typescript-axios'
import { useAuth } from '@qovery/shared/auth'
import { SettingsHeading } from '@qovery/shared/console-shared'
import { useUserAccount } from '@qovery/shared/iam/feature'
import { Callout, Icon, Section } from '@qovery/shared/ui'
import { useAICopilotConfig } from '../hooks/use-ai-copilot-config/use-ai-copilot-config'
import { useAICopilotRecurringTasks } from '../hooks/use-ai-copilot-recurring-tasks/use-ai-copilot-recurring-tasks'
import { useDeleteAICopilotRecurringTask } from '../hooks/use-delete-ai-copilot-recurring-task/use-delete-ai-copilot-recurring-task'
Expand Down Expand Up @@ -54,31 +56,46 @@ export function AICopilotSettings(props: AICopilotSettingsProps) {
return (
<div className="w-full justify-between">
<div className="max-w-content-with-navigation-left p-8">
{!isEnabled && !isLoadingConfig ? (
<SectionAICopilotOptIn
organization={organization}
isLoading={isLoadingConfig}
onEnable={() => handleToggleCopilot(true)}
/>
) : (
<>
<SectionAICopilotConfiguration
<Section>
<SettingsHeading title="AI Copilot Configuration" description="Configure your Copilot" showNeedHelp={false} />
<Callout.Root color="purple" className="mb-4">
<Callout.Icon>
<Icon iconName="flask" />
</Callout.Icon>
<Callout.Text>
<Callout.TextHeading>Beta Feature</Callout.TextHeading>
<Callout.TextDescription>
The AI Copilot is currently in beta. This is an experimental feature and functionality may change.
Billing terms are not final and will be communicated before any charges apply.
</Callout.TextDescription>
</Callout.Text>
</Callout.Root>
{!isEnabled && !isLoadingConfig ? (
<SectionAICopilotOptIn
organization={organization}
isLoading={isLoadingConfig || !orgConfig}
isUpdating={updateConfigMutation.isLoading}
currentMode={currentMode}
onModeChange={(mode) => updateConfigMutation.mutate({ enabled: true, readOnly: mode === 'read-only' })}
onDisable={() => handleToggleCopilot(false)}
isLoading={isLoadingConfig}
onEnable={() => handleToggleCopilot(true)}
/>
) : (
<div className="flex flex-col gap-8">
<SectionAICopilotConfiguration
organization={organization}
isLoading={isLoadingConfig || !orgConfig}
isUpdating={updateConfigMutation.isLoading}
currentMode={currentMode}
onModeChange={(mode) => updateConfigMutation.mutate({ enabled: true, readOnly: mode === 'read-only' })}
onDisable={() => handleToggleCopilot(false)}
/>

<SectionScheduledTasks
tasks={tasks}
isLoading={isLoadingTasks}
onToggleTask={(taskId) => toggleTaskMutation.mutate({ taskId })}
onDeleteTask={(taskId) => deleteTaskMutation.mutate({ taskId })}
/>
</>
)}
<SectionScheduledTasks
tasks={tasks}
isLoading={isLoadingTasks}
onToggleTask={(taskId) => toggleTaskMutation.mutate({ taskId })}
onDeleteTask={(taskId) => deleteTaskMutation.mutate({ taskId })}
/>
</div>
)}
</Section>
</div>
</div>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,6 @@ describe('SectionAICopilotConfiguration', () => {
mockUseFeatureFlagVariantKey.mockReturnValue('control')
})

it('should render section heading', () => {
render(<SectionAICopilotConfiguration {...defaultProps} />)

expect(screen.getByText('AI Copilot Configuration')).toBeInTheDocument()
expect(screen.getByText('Configure your Copilot')).toBeInTheDocument()
})

it('should show loader when loading', () => {
const { container } = render(<SectionAICopilotConfiguration {...defaultProps} isLoading={true} />)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ export interface SectionAICopilotConfigurationProps {
function getDisableConfirmationModal(closeModal: () => void, onDisable: () => void) {
return (
<div className="p-6">
<h2 className="h4 mb-2 text-neutral-400">Disable AI Copilot</h2>
<p className="mb-6 text-sm text-neutral-350">
<h2 className="h4 mb-2 text-neutral">Disable AI Copilot</h2>
<p className="mb-6 text-sm text-neutral-subtle">
Are you sure you want to disable AI Copilot? This will stop all AI-powered assistance for your organization.
</p>
<div className="flex justify-end gap-3">
Expand Down Expand Up @@ -85,37 +85,21 @@ export function SectionAICopilotConfiguration({

return (
<Section>
<div className="mb-8">
<Heading className="mb-2">AI Copilot Configuration</Heading>
<p className="text-xs text-neutral-400">Configure your Copilot</p>
</div>
<Callout.Root color="purple" className="mb-6">
<Callout.Icon>
<Icon iconName="flask" />
</Callout.Icon>
<Callout.Text>
<Callout.TextHeading>Beta Feature</Callout.TextHeading>
<Callout.TextDescription>
The AI Copilot is currently in beta. This is an experimental feature and functionality may change. Billing
terms are not final and will be communicated before any charges apply.
</Callout.TextDescription>
</Callout.Text>
</Callout.Root>
<BlockContent title="Configuration" classNameContent="p-0">
<BlockContent title="Configuration" classNameContent="p-0" className="m-0">
{isLoading ? (
<div className="flex justify-center p-5">
<LoaderSpinner className="w-5" />
</div>
) : (
<div className="space-y-6 p-6">
<div className={`-mx-6 px-6 ${hasReadWriteAccess ? 'border-b border-neutral-250 pb-6' : ''}`}>
<div className={`-mx-6 px-6 ${hasReadWriteAccess ? 'border-b border-neutral pb-6' : ''}`}>
<div className="flex items-center gap-4">
<div className="flex-1">
<div className="mb-2 flex items-center">
<Icon iconName="robot" className="mr-2 text-brand-500" />
<p className="text-sm font-medium text-neutral-400">AI Copilot for {organization?.name}</p>
<Icon iconName="robot" className="mr-2 text-brand" />
<p className="text-sm font-medium text-neutral">AI Copilot for {organization?.name}</p>
</div>
<p className="text-xs text-neutral-350">AI-powered assistance is currently active</p>
<p className="text-xs text-neutral-subtle">AI-powered assistance is currently active</p>
</div>
<Button
size="md"
Expand All @@ -136,8 +120,8 @@ export function SectionAICopilotConfiguration({
{hasReadWriteAccess && (
<>
<div className="space-y-2">
<label className="text-sm font-medium text-neutral-400">Access Mode</label>
<p className="text-xs text-neutral-350">
<label className="text-sm font-medium text-neutral">Access Mode</label>
<p className="text-xs text-neutral-subtle">
Choose the level of access the AI Copilot will have on your organization
</p>
</div>
Expand Down Expand Up @@ -166,7 +150,7 @@ export function SectionAICopilotConfiguration({

<Callout.Root color="sky" className="mt-4">
<Callout.Icon>
<Icon name={IconAwesomeEnum.CIRCLE_INFO} />
<Icon iconName="circle-info" iconStyle="regular" />
</Callout.Icon>
<Callout.Text>
<Callout.TextHeading>
Expand Down
Loading