Use query params with useEntityListProvider

Signed-off-by: Tim Hansen <timbonicus@gmail.com>
This commit is contained in:
Tim Hansen
2021-06-21 11:28:09 -06:00
committed by Phil Kuang
parent df12cc25aa
commit dd69629625
4 changed files with 37 additions and 2 deletions
@@ -28,8 +28,11 @@ export const EntityKindPicker = ({
initialFilter,
hidden,
}: EntityKindFilterProps) => {
const [selectedKind] = useState(initialFilter);
const { updateFilters } = useEntityListProvider();
const { updateFilters, queryParameters } = useEntityListProvider();
const [selectedKind] = useState(
// TODO Cast here is not great 🤔
(queryParameters.kind as string) ?? initialFilter,
);
useEffect(() => {
updateFilters({
+4
View File
@@ -29,6 +29,10 @@ export class EntityKindFilter implements EntityFilter {
getCatalogFilters(): Record<string, string | string[]> {
return { kind: this.value };
}
toQueryValue(): string {
return this.value;
}
}
export class EntityTypeFilter implements EntityFilter {
@@ -77,6 +77,11 @@ export type EntityListContextProps<
| ((prevFilters: EntityFilters) => Partial<EntityFilters>),
) => void;
/**
* Filter values from query parameters.
*/
queryParameters: Record<keyof EntityFilters, string | string[]>;
loading: boolean;
error?: Error;
};
@@ -89,6 +94,7 @@ type OutputState<EntityFilters extends DefaultEntityFilters> = {
appliedFilters: EntityFilters;
entities: Entity[];
backendEntities: Entity[];
queryParameters: Record<string, string | string[]>;
};
export const EntityListProvider = <EntityFilters extends DefaultEntityFilters>({
@@ -102,6 +108,7 @@ export const EntityListProvider = <EntityFilters extends DefaultEntityFilters>({
appliedFilters: {} as EntityFilters,
entities: [],
backendEntities: [],
queryParameters: {}, // TODO: Load (once!!) from query parameters
});
// The main async filter worker. Note that while it has a lot of dependencies
@@ -116,6 +123,15 @@ export const EntityListProvider = <EntityFilters extends DefaultEntityFilters>({
compact(Object.values(outputState.appliedFilters)),
);
const queryParams = Object.keys(requestedFilters).reduce((params, key) => {
const filter: EntityFilter | undefined =
requestedFilters[key as keyof EntityFilters];
if (filter?.toQueryValue) {
params[key] = filter.toQueryValue();
}
return params;
}, {} as Record<string, string | string[]>);
// TODO(mtlewis): currently entities will never be requested unless
// there's at least one filter, we should allow an initial request
// to happen with no filters.
@@ -129,14 +145,18 @@ export const EntityListProvider = <EntityFilters extends DefaultEntityFilters>({
appliedFilters: requestedFilters,
backendEntities: response.items,
entities: response.items.filter(entityFilter),
queryParameters: queryParams,
});
} else {
setOutputState({
appliedFilters: requestedFilters,
backendEntities: outputState.backendEntities,
entities: outputState.backendEntities.filter(entityFilter),
queryParameters: queryParams,
});
}
// TODO: write queryParams to query string
},
[catalogApi, requestedFilters, outputState],
{ loading: true },
@@ -168,6 +188,7 @@ export const EntityListProvider = <EntityFilters extends DefaultEntityFilters>({
entities: outputState.entities,
backendEntities: outputState.backendEntities,
updateFilters,
queryParameters: outputState.queryParameters,
loading,
error,
}}
+7
View File
@@ -34,6 +34,13 @@ export type EntityFilter = {
* @param env
*/
filterEntity?: (entity: Entity) => boolean;
/**
* Serialize the filter value to a string for query params. The UI component responsible for
* handling this filter should retrieve this from useEntityListProvider.queryParameters. The
* value restored should be in the precedence: queryParameters > initialValue prop > default.
*/
toQueryValue?: () => string | string[];
};
export type UserListFilterKind = 'owned' | 'starred' | 'all';