chore: Update package.json and pnpm-lock.yaml to add husky for Git hooks; enhance Docker workflow with pnpm setup and linting steps; refactor various components to utilize new form components and improve UI consistency.
Build, Test, and Push CFDM Docker Image / test (push) Successful in 4m5s
Build, Test, and Push CFDM Docker Image / build-and-push (push) Successful in 2m26s
Build, Test, and Push CFDM Docker Image / update-wiki (push) Successful in 8s
Build, Test, and Push CFDM Docker Image / create-release (push) Has been skipped
Build, Test, and Push CFDM Docker Image / test (push) Successful in 4m5s
Build, Test, and Push CFDM Docker Image / build-and-push (push) Successful in 2m26s
Build, Test, and Push CFDM Docker Image / update-wiki (push) Successful in 8s
Build, Test, and Push CFDM Docker Image / create-release (push) Has been skipped
This commit is contained in:
@@ -3,6 +3,7 @@ import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
|
||||
import { useMemo, useState } from 'react'
|
||||
import { useForm } from 'react-hook-form'
|
||||
import { zodResolver } from '@hookform/resolvers/zod'
|
||||
import { GlobeIcon } from 'lucide-react'
|
||||
import { toast } from 'sonner'
|
||||
import { api } from '@/lib/api-client'
|
||||
import { createDomainSchema, type CreateDomainInput } from '@/lib/schemas'
|
||||
@@ -14,15 +15,16 @@ import {
|
||||
} from '@/queries'
|
||||
import { PageHeader } from '@/components/page-header'
|
||||
import { PageShell } from '@/components/page-shell'
|
||||
import { QueryState } from '@/components/query-state'
|
||||
import { DataTableCard } from '@/components/data-table-card'
|
||||
import { DomainsDataTable, type DomainTableRow } from '@/components/domains-data-table'
|
||||
import { FormSheet } from '@/components/form-sheet'
|
||||
import { FormFieldSimple } from '@/components/form-field'
|
||||
import { LoadingButton } from '@/components/loading-button'
|
||||
import { TableSkeleton } from '@/components/table-skeleton'
|
||||
import { Button } from '@cfdm/ui/components/button'
|
||||
import { Input } from '@cfdm/ui/components/input'
|
||||
import {
|
||||
Field,
|
||||
FieldGroup,
|
||||
FieldLabel,
|
||||
} from '@cfdm/ui/components/field'
|
||||
import { FieldGroup } from '@cfdm/ui/components/field'
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
@@ -30,15 +32,6 @@ import {
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from '@cfdm/ui/components/select'
|
||||
import {
|
||||
Sheet,
|
||||
SheetContent,
|
||||
SheetDescription,
|
||||
SheetFooter,
|
||||
SheetHeader,
|
||||
SheetTitle,
|
||||
} from '@cfdm/ui/components/sheet'
|
||||
import { Spinner } from '@cfdm/ui/components/spinner'
|
||||
|
||||
export const Route = createFileRoute('/_auth/domains/')({
|
||||
loader: ({ context: { queryClient } }) =>
|
||||
@@ -56,7 +49,13 @@ function DomainsPage() {
|
||||
const listGroupId =
|
||||
filterGroupId && filterGroupId !== 'none' ? Number(filterGroupId) : undefined
|
||||
const queryClient = useQueryClient()
|
||||
const { data: domains } = useQuery(domainsListQueryOptions(listGroupId))
|
||||
const {
|
||||
data: domains,
|
||||
isLoading,
|
||||
isError,
|
||||
error,
|
||||
refetch,
|
||||
} = useQuery(domainsListQueryOptions(listGroupId))
|
||||
const { data: groups } = useQuery(groupsQueryOptions())
|
||||
|
||||
const groupItems = useMemo(
|
||||
@@ -102,12 +101,12 @@ function DomainsPage() {
|
||||
deleteMutation.mutate(domain.id)
|
||||
}
|
||||
|
||||
const handleCreate = form.handleSubmit((values) => {
|
||||
const handleCreate = (values: CreateDomainInput) => {
|
||||
createMutation.mutate({
|
||||
zone_name: values.zone_name.trim(),
|
||||
group_id: importGroupId ? Number(importGroupId) : undefined,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const handleImportGroupChange = (value: string | null) => {
|
||||
const next = value === 'none' || !value ? '' : value
|
||||
@@ -135,6 +134,10 @@ function DomainsPage() {
|
||||
[filteredDomains],
|
||||
)
|
||||
|
||||
const hasActiveFilter = filterGroupId !== ''
|
||||
const isZeroResults = hasActiveFilter && tableData.length === 0 && (domains?.length ?? 0) > 0
|
||||
const isTrulyEmpty = tableData.length === 0 && !hasActiveFilter
|
||||
|
||||
return (
|
||||
<PageShell>
|
||||
<PageHeader
|
||||
@@ -150,68 +153,100 @@ function DomainsPage() {
|
||||
}
|
||||
/>
|
||||
|
||||
<DataTableCard
|
||||
title="Список доменов"
|
||||
description="Импортированные зоны Cloudflare"
|
||||
<QueryState
|
||||
isLoading={isLoading}
|
||||
isError={isError}
|
||||
error={error}
|
||||
onRetry={refetch}
|
||||
skeleton={<TableSkeleton />}
|
||||
>
|
||||
<DomainsDataTable
|
||||
data={tableData}
|
||||
groupFilterItems={groupItems}
|
||||
groupFilterValue={filterGroupId || 'all'}
|
||||
onGroupFilterChange={handleFilterGroupChange}
|
||||
onDelete={handleDeleteDomain}
|
||||
isDeleting={deleteMutation.isPending}
|
||||
/>
|
||||
</DataTableCard>
|
||||
|
||||
<Sheet open={sheetOpen} onOpenChange={setSheetOpen}>
|
||||
<SheetContent>
|
||||
<SheetHeader>
|
||||
<SheetTitle>Импорт домена</SheetTitle>
|
||||
<SheetDescription>
|
||||
Добавить зону из аккаунта Cloudflare в менеджер
|
||||
</SheetDescription>
|
||||
</SheetHeader>
|
||||
<form onSubmit={handleCreate} className="flex flex-col gap-4 px-4">
|
||||
<FieldGroup>
|
||||
<Field>
|
||||
<FieldLabel htmlFor="zone_name">Имя зоны</FieldLabel>
|
||||
<Input
|
||||
id="zone_name"
|
||||
placeholder="example.com"
|
||||
{...form.register('zone_name')}
|
||||
aria-invalid={!!form.formState.errors.zone_name}
|
||||
/>
|
||||
</Field>
|
||||
<Field>
|
||||
<FieldLabel htmlFor="import_group_id">Группа</FieldLabel>
|
||||
<Select
|
||||
items={groupItems}
|
||||
value={importGroupId || 'none'}
|
||||
onValueChange={handleImportGroupChange}
|
||||
>
|
||||
<SelectTrigger id="import_group_id" className="w-full">
|
||||
<SelectValue placeholder="Без группы" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{groupItems.map((item) => (
|
||||
<SelectItem key={item.value} value={item.value}>
|
||||
{item.label}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
<SheetFooter>
|
||||
<Button type="submit" disabled={createMutation.isPending} className="w-full">
|
||||
{createMutation.isPending && <Spinner data-icon="inline-start" />}
|
||||
{createMutation.isPending ? 'Импорт…' : 'Импортировать'}
|
||||
<DataTableCard
|
||||
title="Список доменов"
|
||||
description="Импортированные зоны Cloudflare"
|
||||
isEmpty={isTrulyEmpty || isZeroResults}
|
||||
emptyTitle={
|
||||
isZeroResults ? 'Ничего не найдено' : 'Домены не импортированы'
|
||||
}
|
||||
emptyDescription={
|
||||
isZeroResults
|
||||
? 'По выбранному фильтру группы нет подходящих зон'
|
||||
: 'Импортируйте зону из аккаунта Cloudflare'
|
||||
}
|
||||
emptyIcon={GlobeIcon}
|
||||
emptyAction={
|
||||
isZeroResults ? (
|
||||
<Button variant="outline" onClick={() => setFilterGroupId('')}>
|
||||
Сбросить фильтр
|
||||
</Button>
|
||||
</SheetFooter>
|
||||
</form>
|
||||
</SheetContent>
|
||||
</Sheet>
|
||||
) : (
|
||||
<Button onClick={() => setSheetOpen(true)}>Импортировать домен</Button>
|
||||
)
|
||||
}
|
||||
>
|
||||
{!isTrulyEmpty && !isZeroResults && (
|
||||
<DomainsDataTable
|
||||
data={tableData}
|
||||
groupFilterItems={groupItems}
|
||||
groupFilterValue={filterGroupId || 'all'}
|
||||
onGroupFilterChange={handleFilterGroupChange}
|
||||
onDelete={handleDeleteDomain}
|
||||
isDeleting={deleteMutation.isPending}
|
||||
/>
|
||||
)}
|
||||
</DataTableCard>
|
||||
</QueryState>
|
||||
|
||||
<FormSheet
|
||||
open={sheetOpen}
|
||||
onOpenChange={setSheetOpen}
|
||||
title="Импорт домена"
|
||||
description="Добавить зону из аккаунта Cloudflare в менеджер"
|
||||
form={form}
|
||||
onSubmit={handleCreate}
|
||||
footer={
|
||||
<LoadingButton
|
||||
type="submit"
|
||||
className="w-full"
|
||||
isLoading={createMutation.isPending}
|
||||
loadingLabel="Импорт…"
|
||||
>
|
||||
Импортировать
|
||||
</LoadingButton>
|
||||
}
|
||||
>
|
||||
<FieldGroup>
|
||||
<FormFieldSimple
|
||||
label="Имя зоны"
|
||||
htmlFor="zone_name"
|
||||
error={form.formState.errors.zone_name}
|
||||
>
|
||||
<Input
|
||||
id="zone_name"
|
||||
placeholder="example.com"
|
||||
{...form.register('zone_name')}
|
||||
aria-invalid={!!form.formState.errors.zone_name}
|
||||
/>
|
||||
</FormFieldSimple>
|
||||
<FormFieldSimple label="Группа" htmlFor="import_group_id">
|
||||
<Select
|
||||
items={groupItems}
|
||||
value={importGroupId || 'none'}
|
||||
onValueChange={handleImportGroupChange}
|
||||
>
|
||||
<SelectTrigger id="import_group_id" className="w-full">
|
||||
<SelectValue placeholder="Без группы" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{groupItems.map((item) => (
|
||||
<SelectItem key={item.value} value={item.value}>
|
||||
{item.label}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</FormFieldSimple>
|
||||
</FieldGroup>
|
||||
</FormSheet>
|
||||
</PageShell>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user