diff --git a/frontend/src/components/form/SelectAllClearButtons.tsx b/frontend/src/components/form/SelectAllClearButtons.tsx new file mode 100644 index 000000000..2c3c71c04 --- /dev/null +++ b/frontend/src/components/form/SelectAllClearButtons.tsx @@ -0,0 +1,51 @@ +import { useTranslation } from 'react-i18next'; +import { Button } from 'antd'; + +interface Option { + value: number; +} + +interface SelectAllClearButtonsProps { + options: Option[]; + value: number[]; + onChange: (value: number[]) => void; + /** Override the default "Select all" label (defaults to the inbound copy). */ + selectAllLabel?: string; + /** Override the default "Clear all" label (defaults to the inbound copy). */ + clearLabel?: string; +} + +export default function SelectAllClearButtons({ + options, + value, + onChange, + selectAllLabel, + clearLabel, +}: SelectAllClearButtonsProps) { + const { t } = useTranslation(); + + const optionValues = options.map((o) => o.value); + // Treat as "all selected" when every option is chosen, rather than comparing + // lengths — this stays correct even if `value` holds ids outside `options`. + const allSelected = options.length > 0 && optionValues.every((v) => value.includes(v)); + + return ( +
+ + +
+ ); +} diff --git a/frontend/src/components/form/index.ts b/frontend/src/components/form/index.ts index 9f3e37137..0a5785541 100644 --- a/frontend/src/components/form/index.ts +++ b/frontend/src/components/form/index.ts @@ -1,3 +1,4 @@ export { default as DateTimePicker } from './DateTimePicker'; export { default as JsonEditor } from './JsonEditor'; export { default as HeaderMapEditor } from './HeaderMapEditor'; +export { default as SelectAllClearButtons } from './SelectAllClearButtons'; diff --git a/frontend/src/pages/clients/BulkAttachInboundsModal.tsx b/frontend/src/pages/clients/BulkAttachInboundsModal.tsx index 800e15747..1fd397a3e 100644 --- a/frontend/src/pages/clients/BulkAttachInboundsModal.tsx +++ b/frontend/src/pages/clients/BulkAttachInboundsModal.tsx @@ -2,6 +2,7 @@ import { useEffect, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { Alert, Modal, Select, Typography, message } from 'antd'; +import { SelectAllClearButtons } from '@/components/form'; import type { InboundOption } from '@/hooks/useClients'; import { formatInboundLabel } from '@/lib/inbounds/label'; import type { BulkAttachResult } from '@/schemas/client'; @@ -82,16 +83,23 @@ export default function BulkAttachInboundsModal({ {targetOptions.length === 0 ? ( ) : ( - + )} diff --git a/frontend/src/pages/clients/BulkDetachInboundsModal.tsx b/frontend/src/pages/clients/BulkDetachInboundsModal.tsx index 2c120d47d..d3851f573 100644 --- a/frontend/src/pages/clients/BulkDetachInboundsModal.tsx +++ b/frontend/src/pages/clients/BulkDetachInboundsModal.tsx @@ -2,6 +2,7 @@ import { useEffect, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { Alert, Modal, Select, Typography, message } from 'antd'; +import { SelectAllClearButtons } from '@/components/form'; import type { InboundOption } from '@/hooks/useClients'; import { formatInboundLabel } from '@/lib/inbounds/label'; import type { BulkDetachResult } from '@/schemas/client'; @@ -82,16 +83,23 @@ export default function BulkDetachInboundsModal({ {targetOptions.length === 0 ? ( ) : ( - + )} diff --git a/frontend/src/pages/clients/ClientBulkAddModal.tsx b/frontend/src/pages/clients/ClientBulkAddModal.tsx index 20dedc792..8d25d850c 100644 --- a/frontend/src/pages/clients/ClientBulkAddModal.tsx +++ b/frontend/src/pages/clients/ClientBulkAddModal.tsx @@ -8,7 +8,7 @@ import type { Dayjs } from 'dayjs'; import { RandomUtil, SizeFormatter } from '@/utils'; import { formatInboundLabel } from '@/lib/inbounds/label'; import { TLS_FLOW_CONTROL } from '@/schemas/primitives'; -import { DateTimePicker } from '@/components/form'; +import { DateTimePicker, SelectAllClearButtons } from '@/components/form'; import { useClients, type InboundOption } from '@/hooks/useClients'; import { ClientBulkAddFormSchema, type ClientBulkAddFormValues } from '@/schemas/client'; @@ -213,6 +213,11 @@ export default function ClientBulkAddModal({ >
+ update('inboundIds', v)} + />