mirror of
https://github.com/hansjone/netx.git
synced 2026-10-14 23:40:54 +08:00
Fold NE selection and refresh status into the shared list pager.
Add an optional ListPager meta slot so Managed NE no longer needs a separate selection row above the table. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
312f6f2f96
commit
0ecff329cf
3 changed files with 38 additions and 12 deletions
|
|
@ -1,5 +1,5 @@
|
||||||
import { Button, Input } from "@heroui/react";
|
import { Button, Input } from "@heroui/react";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState, type ReactNode } from "react";
|
||||||
import { useI18n } from "../i18n";
|
import { useI18n } from "../i18n";
|
||||||
import { FieldSelect } from "./ui/FieldSelect";
|
import { FieldSelect } from "./ui/FieldSelect";
|
||||||
|
|
||||||
|
|
@ -13,6 +13,8 @@ export type ListPagerProps = {
|
||||||
onPageSizeChange?: (size: number) => void;
|
onPageSizeChange?: (size: number) => void;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
className?: string;
|
className?: string;
|
||||||
|
/** Extra status shown after the totals (e.g. selection count), so pages need no separate row. */
|
||||||
|
meta?: ReactNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Shared denser pager: meta + prev/next + jump + optional page size. */
|
/** Shared denser pager: meta + prev/next + jump + optional page size. */
|
||||||
|
|
@ -26,6 +28,7 @@ export function ListPager({
|
||||||
onPageSizeChange,
|
onPageSizeChange,
|
||||||
disabled = false,
|
disabled = false,
|
||||||
className = "",
|
className = "",
|
||||||
|
meta,
|
||||||
}: ListPagerProps) {
|
}: ListPagerProps) {
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const safePages = Math.max(1, pages || 1);
|
const safePages = Math.max(1, pages || 1);
|
||||||
|
|
@ -54,6 +57,7 @@ export function ListPager({
|
||||||
page: String(page),
|
page: String(page),
|
||||||
pages: String(safePages),
|
pages: String(safePages),
|
||||||
})}
|
})}
|
||||||
|
{meta}
|
||||||
</div>
|
</div>
|
||||||
<div className="pager__controls btn-row">
|
<div className="pager__controls btn-row">
|
||||||
<Button
|
<Button
|
||||||
|
|
|
||||||
|
|
@ -671,15 +671,6 @@ export function NePage() {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="pt-list">
|
<div className="pt-list">
|
||||||
{selected.length ? (
|
|
||||||
<div className="ne-selection-meta">
|
|
||||||
<span>{t("managedNe.selectedCount", { n: selected.length })}</span>
|
|
||||||
<Button size="sm" variant="ghost" onPress={() => setSelected([])}>
|
|
||||||
{t("managedNe.clearSelection")}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
) : null}
|
|
||||||
{listQuery.isFetching ? <p className="muted">{t("common.refreshing")}</p> : null}
|
|
||||||
{listQuery.isError ? (
|
{listQuery.isError ? (
|
||||||
<p className="error-text">{t("managedNe.loadFailed", { error: errText(listQuery.error) })}</p>
|
<p className="error-text">{t("managedNe.loadFailed", { error: errText(listQuery.error) })}</p>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
@ -832,6 +823,19 @@ export function NePage() {
|
||||||
setPage(1);
|
setPage(1);
|
||||||
}}
|
}}
|
||||||
disabled={listQuery.isLoading}
|
disabled={listQuery.isLoading}
|
||||||
|
meta={
|
||||||
|
<>
|
||||||
|
{selected.length ? (
|
||||||
|
<span className="ne-selection-meta">
|
||||||
|
· {t("managedNe.selectedCount", { n: selected.length })}
|
||||||
|
<button type="button" className="ne-selection-meta__clear" onClick={() => setSelected([])}>
|
||||||
|
{t("managedNe.clearSelection")}
|
||||||
|
</button>
|
||||||
|
</span>
|
||||||
|
) : null}
|
||||||
|
{listQuery.isFetching ? <span className="ne-selection-meta"> · {t("common.refreshing")}</span> : null}
|
||||||
|
</>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
||||||
|
|
@ -115,9 +115,27 @@ button.ne-tag-card.is-active {
|
||||||
.ne-selection-meta {
|
.ne-selection-meta {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 6px;
|
gap: 8px;
|
||||||
|
margin-left: 6px;
|
||||||
color: var(--nx-text-muted);
|
color: var(--nx-text-muted);
|
||||||
font-size: 12px;
|
}
|
||||||
|
|
||||||
|
.ne-page .ne-selection-meta__clear {
|
||||||
|
padding: 0;
|
||||||
|
border: 0;
|
||||||
|
background: transparent;
|
||||||
|
color: var(--nx-accent);
|
||||||
|
cursor: pointer;
|
||||||
|
font: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ne-page .ne-selection-meta__clear:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ne-page .ne-selection-meta__clear:focus-visible {
|
||||||
|
outline: 2px solid var(--nx-accent);
|
||||||
|
outline-offset: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ne-import-failures {
|
.ne-import-failures {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue