mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-07-22 20:46:08 +00:00
feat(ui): add select all / clear all shortcuts for inbound multi-select (#5175)
* feat(ui): add select all / clear all shortcuts for inbound multi-select Adds 'Select all' and 'Clear all' buttons above the inbound multi-select in: - ClientFormModal (add/edit client) - BulkAttachInboundsModal (bulk attach clients to inbounds) - BulkDetachInboundsModal (bulk detach clients from inbounds) - ClientBulkAddModal (add bulk clients) Extracts the repeated button logic into a reusable SelectAllClearButtons component. Includes i18n keys for all 13 supported languages with proper translations. Closes #5144 * refactor(form): decouple SelectAllClearButtons labels and harden select-all Accept optional selectAllLabel/clearLabel props so the generic form component is not tied to the client-inbound i18n keys (defaults unchanged). Compute the all-selected state by checking every option is present and union the current value on select-all, so it stays correct if value holds ids outside options. --------- Co-authored-by: Sanaei <ho3ein.sanaei@gmail.com>
This commit is contained in:
@@ -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 (
|
||||
<div style={{ display: 'flex', gap: 8, marginBottom: 8 }}>
|
||||
<Button
|
||||
size="small"
|
||||
disabled={allSelected}
|
||||
// Union with the current value so selections outside `options` are kept.
|
||||
onClick={() => onChange(Array.from(new Set([...value, ...optionValues])))}
|
||||
>
|
||||
{selectAllLabel ?? t('pages.clients.selectAllInbounds')}
|
||||
</Button>
|
||||
<Button
|
||||
size="small"
|
||||
disabled={value.length === 0}
|
||||
onClick={() => onChange([])}
|
||||
>
|
||||
{clearLabel ?? t('pages.clients.clearAllInbounds')}
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -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';
|
||||
|
||||
Reference in New Issue
Block a user