mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-11 15:04:52 +09:00
Keep users instance filter and icon search in the URL (#1185)
The instance picker on the users page and the search box on the icon reference page held their value in component state, so leaving the page and coming back with the browser history reset them. Both now go through useTableQueryState like the table filters do, as user.instance and icon.search. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
b0fb43d678
commit
c6867de13d
2 files changed
+21
-4
No files matched your search
@@ -9,6 +9,7 @@ import { useParams } from "react-router-dom";
|
||||
import { useModPack } from "../model/mod_pack";
|
||||
import { PrototypeMetadataEntry } from "../store/export_prototype_metadata_store";
|
||||
import useResourceState from "../util/useResourceState";
|
||||
import useTableQueryState from "../util/useTableQueryState";
|
||||
import ResourceState from "./ResourceState";
|
||||
|
||||
const { Text } = Typography;
|
||||
@@ -39,7 +40,9 @@ export default function IconReferencePage() {
|
||||
let params = useParams();
|
||||
let modPackId = Number(params.id);
|
||||
|
||||
const [filter, setFilter] = useState("");
|
||||
// Filters live as you type, written to the URL on blur, enter or clear
|
||||
const queryState = useTableQueryState({ namespace: "icon" });
|
||||
const filter = queryState.filteredValue("search")?.[0] ?? "";
|
||||
const [expandedGroups, setExpandedGroups] = useState<Set<string>>(new Set());
|
||||
const [modPack, synced, error] = useModPack(modPackId);
|
||||
const state = useResourceState(modPack, synced, error, modPackId);
|
||||
@@ -137,7 +140,15 @@ export default function IconReferencePage() {
|
||||
<Input
|
||||
placeholder="Filter by type or name…"
|
||||
value={filter}
|
||||
onChange={e => setFilter(e.target.value)}
|
||||
onChange={e => {
|
||||
const values = e.target.value ? [e.target.value] : null;
|
||||
queryState.setFilter("search", values);
|
||||
if (!values) {
|
||||
queryState.commitFilter("search", null);
|
||||
}
|
||||
}}
|
||||
onBlur={() => queryState.commitFilter("search")}
|
||||
onPressEnter={() => queryState.commitFilter("search")}
|
||||
allowClear
|
||||
style={{ width: 320 }}
|
||||
/>
|
||||
|
||||
@@ -20,6 +20,7 @@ import PageLayout from "./PageLayout";
|
||||
import PluginExtra from "./PluginExtra";
|
||||
import UsersTable from "./UsersTable";
|
||||
import { InputInstanceWithAll } from "./InputInstance";
|
||||
import useTableQueryState from "../util/useTableQueryState";
|
||||
|
||||
function CreateUserButton() {
|
||||
let control = useContext(ControlContext);
|
||||
@@ -368,7 +369,10 @@ function BulkUserActionButton() {
|
||||
|
||||
export default function UsersPage() {
|
||||
const account = useAccount();
|
||||
const [instanceId, setInstanceId] = useState<number | null>(null);
|
||||
// Kept in the URL with the users table state so back/forward restores it
|
||||
const tableState = useTableQueryState<lib.UserDetails>({ namespace: "user" });
|
||||
const instanceParam = Number(tableState.filteredValue("instance")?.[0]);
|
||||
const instanceId = Number.isInteger(instanceParam) ? instanceParam : null;
|
||||
|
||||
return <PageLayout nav={[{ name: "Users" }]}>
|
||||
<PageHeader
|
||||
@@ -377,7 +381,9 @@ export default function UsersPage() {
|
||||
{account.hasAllPermission("core.instance.list", "core.instance.subscribe")
|
||||
&& <InputInstanceWithAll
|
||||
value={instanceId}
|
||||
onChange={value => setInstanceId(value as number)}
|
||||
onChange={value => tableState.commitFilter(
|
||||
"instance", value === null ? null : [String(value)]
|
||||
)}
|
||||
fieldDefinition={{ optional: true } as any}
|
||||
disabled={false}
|
||||
/>}
|
||||
|
||||
Reference in new issue
Block a user