Files
triggerdotdev--trigger.dev/apps/webapp/app/hooks/useSearchParam.ts
Matt Aitken 55264657d7 Run tags (#1232)
* TaskRunTag migration. Removed unused TaskTag

* Show tags for a run in the run list

* API endpoint for searching tags

* Let’s not expose an API endpoint for tags at the moment

* Filter by tags working from the URL

* Tag async filter working

* We don’t need a “None” option because it’s multi-select

* When triggering a run you can add tags

* SDK runs.retrieve and runs.list with tag support

* Tidied imports

* Changed the run list query so we show all the tags even if a run only matches one of them

* Fix for dealing with weird characters in tags

* Run tags changeset

* Creating a project has a proper loading state (and blocks multiple)

* Improved the error message for tag length

* Added a tags icon for display on the run screen

* Convenient functions for creating and getting run tags

* tags.set() from inside the run function

* Replay a run passes tags through

* Less ridiculous tags for the catalog example

* Allow passing just a string for the tags

* Order by id because there’s an index on the primary key already

* Trim the tags earlier so we don’t accidentally error if a blank string is passed

* Renamed some thing from setTags to addTags

* Use findFirst for the tags project lookup

* Added an index for "TaskRunTag"("name", "id")

It massively improves the performance of run filtering based on tags

* Use `array_agg` for the run list tags so pagination works and we get a single result for each run

* Tidied imports

* More comprehensive test of tags with all triggering functions

* Support tags with tasks.trigger, tasks.batchTrigger and tasks poll variants

* Added tasks.batchTrigger tags

* Sort the tags in the UI so they’re always in the same order

* Added tooltips in the run table for delay, ttl and tags

* Added costInCents, baseCostInCents and durationMs to runs.retrieve and runs.list

* Added support for displaying a split tag if you use key_value or key:value format

* Fix code comment

* Tweaked the JSDoc to make the prefixing clearer

* Added tasks.triggerAndWait to the tags test task
2024-07-23 16:48:09 +01:00

83 lines
1.8 KiB
TypeScript

import { useNavigate } from "@remix-run/react";
import { useOptimisticLocation } from "./useOptimisticLocation";
import { useCallback } from "react";
type Values = Record<string, string | string[] | undefined>;
export function useSearchParams() {
const navigate = useNavigate();
const location = useOptimisticLocation();
const search = new URLSearchParams(location.search);
const set = useCallback(
(values: Values) => {
for (const [param, value] of Object.entries(values)) {
if (value === undefined) {
search.delete(param);
continue;
}
if (typeof value === "string") {
search.set(param, encodeURIComponent(value));
continue;
}
search.delete(param);
for (const v of value) {
search.append(param, encodeURIComponent(v));
}
}
},
[location, search]
);
const replace = useCallback(
(values: Values) => {
set(values);
navigate(`${location.pathname}?${search.toString()}`, { replace: true });
},
[location, search]
);
const del = useCallback(
(keys: string | string[]) => {
if (!Array.isArray(keys)) {
keys = [keys];
}
for (const key of keys) {
search.delete(key);
}
navigate(`${location.pathname}?${search.toString()}`, { replace: true });
},
[location, search]
);
const value = useCallback(
(param: string) => {
const val = search.get(param) ?? undefined;
if (val === undefined) {
return val;
}
return decodeURIComponent(val);
},
[location, search]
);
const values = useCallback(
(param: string) => {
const all = search.getAll(param);
return all.map((v) => decodeURIComponent(v));
},
[location, search]
);
return {
value,
values,
set,
replace,
del,
};
}