-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Andrea Rosci
authored and
Andrea Rosci
committed
Apr 8, 2024
1 parent
2dd2edf
commit ca45f23
Showing
19 changed files
with
1,931 additions
and
1,920 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,170 +1,170 @@ | ||
import React from "react"; | ||
import React from 'react'; | ||
import type { | ||
JSONSchema7 as JSONSchema, | ||
JSONSchema7Definition as JSONSchemaDefinition, | ||
} from "json-schema"; | ||
import { PersistentFilters } from "./PersistentFilters"; | ||
import { AutoUIContext, AutoUIBaseResource } from "../schemaOps"; | ||
JSONSchema7 as JSONSchema, | ||
JSONSchema7Definition as JSONSchemaDefinition, | ||
} from 'json-schema'; | ||
import { PersistentFilters } from './PersistentFilters'; | ||
import { AutoUIContext, AutoUIBaseResource } from '../schemaOps'; | ||
import { | ||
FilterRenderMode, | ||
// FiltersView, | ||
// Filters as RenditionFilters, | ||
SchemaSieve as sieve, | ||
} from "rendition"; | ||
import { useHistory } from "../../hooks/useHistory"; | ||
import { getFromLocalStorage, setToLocalStorage } from "../utils"; | ||
FilterRenderMode, | ||
// FiltersView, | ||
// Filters as RenditionFilters, | ||
SchemaSieve as sieve, | ||
} from 'rendition'; | ||
import { useHistory } from '../../hooks/useHistory'; | ||
import { getFromLocalStorage, setToLocalStorage } from '../utils'; | ||
import { | ||
Filters as FiltersComponent, | ||
FiltersView, | ||
} from "../../components/Filters"; | ||
Filters as FiltersComponent, | ||
FiltersView, | ||
} from '../../components/Filters'; | ||
|
||
export interface FiltersProps<T> { | ||
schema: JSONSchema; | ||
filters: JSONSchema[]; | ||
views: FiltersView[]; | ||
autouiContext: AutoUIContext<T>; | ||
changeFilters: (filters: JSONSchema[]) => void; | ||
changeViews: (views: FiltersView[]) => void; | ||
renderMode?: FilterRenderMode | FilterRenderMode[]; | ||
onSearch?: (searchTerm: string) => React.ReactElement | null; | ||
showSaveView?: boolean; | ||
persistFilters?: boolean; | ||
schema: JSONSchema; | ||
filters: JSONSchema[]; | ||
views: FiltersView[]; | ||
autouiContext: AutoUIContext<T>; | ||
changeFilters: (filters: JSONSchema[]) => void; | ||
changeViews: (views: FiltersView[]) => void; | ||
renderMode?: FilterRenderMode | FilterRenderMode[]; | ||
onSearch?: (searchTerm: string) => React.ReactElement | null; | ||
showSaveView?: boolean; | ||
persistFilters?: boolean; | ||
} | ||
|
||
const removeFieldsWithNoFilter = (schema: JSONSchema): JSONSchema => { | ||
const processProperties = ( | ||
properties: JSONSchema["properties"] | undefined, | ||
parentXNoFilterSet?: Set<string> | ||
): JSONSchema["properties"] | undefined => { | ||
if (!properties) { | ||
return undefined; | ||
} | ||
|
||
const newProperties: JSONSchema["properties"] = {}; | ||
for (const [key, value] of Object.entries(properties)) { | ||
// if boolean keep boolean values as is | ||
if (typeof value === "boolean") { | ||
newProperties[key] = value; | ||
continue; | ||
} | ||
// Apply removal logic in case our parent has defined an array x-no-filter for its children | ||
// TODO: This only works with immediate children and NOT with nested properties. | ||
if (parentXNoFilterSet?.has(key)) { | ||
continue; | ||
} | ||
// Extract x-no-filter if available | ||
const xNoFilter = sieve.parseDescriptionProperty< | ||
string[] | boolean | undefined | ||
>(value, "x-no-filter"); | ||
|
||
if (xNoFilter === true) { | ||
// Exclude property entirely if xNoFilter is true | ||
continue; | ||
} | ||
|
||
const newValue: JSONSchemaDefinition = { ...value }; | ||
const xNoFilterSet = Array.isArray(xNoFilter) | ||
? new Set(xNoFilter) | ||
: undefined; | ||
|
||
if ("properties" in value) { | ||
newValue.properties = processProperties(value.properties, xNoFilterSet); | ||
} | ||
|
||
// we are not considering the case where items is an array. Should be added if necessary | ||
if ( | ||
value.items && | ||
typeof value.items === "object" && | ||
!Array.isArray(value.items) | ||
) { | ||
if ("properties" in value.items) { | ||
newValue.items = { | ||
...value.items, | ||
properties: processProperties(value.items.properties, xNoFilterSet), | ||
}; | ||
} | ||
} | ||
|
||
newProperties[key] = newValue; | ||
} | ||
|
||
return newProperties; | ||
}; | ||
|
||
if (schema.properties) { | ||
schema = { | ||
...schema, | ||
properties: processProperties(schema.properties), | ||
}; | ||
} | ||
return schema; | ||
const processProperties = ( | ||
properties: JSONSchema['properties'] | undefined, | ||
parentXNoFilterSet?: Set<string>, | ||
): JSONSchema['properties'] | undefined => { | ||
if (!properties) { | ||
return undefined; | ||
} | ||
|
||
const newProperties: JSONSchema['properties'] = {}; | ||
for (const [key, value] of Object.entries(properties)) { | ||
// if boolean keep boolean values as is | ||
if (typeof value === 'boolean') { | ||
newProperties[key] = value; | ||
continue; | ||
} | ||
// Apply removal logic in case our parent has defined an array x-no-filter for its children | ||
// TODO: This only works with immediate children and NOT with nested properties. | ||
if (parentXNoFilterSet?.has(key)) { | ||
continue; | ||
} | ||
// Extract x-no-filter if available | ||
const xNoFilter = sieve.parseDescriptionProperty< | ||
string[] | boolean | undefined | ||
>(value, 'x-no-filter'); | ||
|
||
if (xNoFilter === true) { | ||
// Exclude property entirely if xNoFilter is true | ||
continue; | ||
} | ||
|
||
const newValue: JSONSchemaDefinition = { ...value }; | ||
const xNoFilterSet = Array.isArray(xNoFilter) | ||
? new Set(xNoFilter) | ||
: undefined; | ||
|
||
if ('properties' in value) { | ||
newValue.properties = processProperties(value.properties, xNoFilterSet); | ||
} | ||
|
||
// we are not considering the case where items is an array. Should be added if necessary | ||
if ( | ||
value.items && | ||
typeof value.items === 'object' && | ||
!Array.isArray(value.items) | ||
) { | ||
if ('properties' in value.items) { | ||
newValue.items = { | ||
...value.items, | ||
properties: processProperties(value.items.properties, xNoFilterSet), | ||
}; | ||
} | ||
} | ||
|
||
newProperties[key] = newValue; | ||
} | ||
|
||
return newProperties; | ||
}; | ||
|
||
if (schema.properties) { | ||
schema = { | ||
...schema, | ||
properties: processProperties(schema.properties), | ||
}; | ||
} | ||
return schema; | ||
}; | ||
|
||
const DEFAULT_RENDER_MODE = (["add", "search", "views"] as const).slice(); | ||
const DEFAULT_RENDER_MODE = (['add', 'search', 'views'] as const).slice(); | ||
|
||
export const Filters = <T extends AutoUIBaseResource<T>>({ | ||
schema, | ||
filters, | ||
views, | ||
changeFilters, | ||
changeViews, | ||
autouiContext, | ||
renderMode, | ||
onSearch, | ||
showSaveView, | ||
persistFilters, | ||
schema, | ||
filters, | ||
views, | ||
changeFilters, | ||
changeViews, | ||
autouiContext, | ||
renderMode, | ||
onSearch, | ||
showSaveView, | ||
persistFilters, | ||
}: FiltersProps<T>) => { | ||
const history = useHistory(); | ||
|
||
const filteredSchema = React.useMemo( | ||
() => removeFieldsWithNoFilter(schema), | ||
[schema] | ||
); | ||
|
||
// We store views in any case as views should persist in both cases PersistentFilters and RenditionFilters | ||
const viewsRestorationKey = `${autouiContext.resource}__views`; | ||
const storedViews = React.useMemo( | ||
() => | ||
views.length | ||
? views | ||
: getFromLocalStorage<FiltersView[]>(viewsRestorationKey) ?? [], | ||
[viewsRestorationKey, views] | ||
); | ||
|
||
const viewsUpdate = (views: FiltersView[]) => { | ||
setToLocalStorage(viewsRestorationKey, views); | ||
changeViews?.(views); | ||
}; | ||
|
||
return ( | ||
<> | ||
{!!history && persistFilters ? ( | ||
<PersistentFilters | ||
viewsRestorationKey={viewsRestorationKey} | ||
history={history} | ||
schema={filteredSchema} | ||
filters={filters} | ||
views={storedViews} | ||
onFiltersChange={changeFilters} | ||
onViewsChange={viewsUpdate} | ||
renderMode={renderMode ?? DEFAULT_RENDER_MODE} | ||
onSearch={onSearch} | ||
// compact={[true, true, false]} | ||
// showSaveView={showSaveView} | ||
/> | ||
) : ( | ||
<FiltersComponent | ||
schema={filteredSchema} | ||
filters={filters} | ||
views={storedViews} | ||
onFiltersChange={changeFilters} | ||
onViewsChange={viewsUpdate} | ||
renderMode={renderMode ?? DEFAULT_RENDER_MODE} | ||
onSearch={onSearch} | ||
// compact={[true, true, false]} | ||
// showSaveView={showSaveView} | ||
/> | ||
)} | ||
</> | ||
); | ||
const history = useHistory(); | ||
|
||
const filteredSchema = React.useMemo( | ||
() => removeFieldsWithNoFilter(schema), | ||
[schema], | ||
); | ||
|
||
// We store views in any case as views should persist in both cases PersistentFilters and RenditionFilters | ||
const viewsRestorationKey = `${autouiContext.resource}__views`; | ||
const storedViews = React.useMemo( | ||
() => | ||
views.length | ||
? views | ||
: getFromLocalStorage<FiltersView[]>(viewsRestorationKey) ?? [], | ||
[viewsRestorationKey, views], | ||
); | ||
|
||
const viewsUpdate = (views: FiltersView[]) => { | ||
setToLocalStorage(viewsRestorationKey, views); | ||
changeViews?.(views); | ||
}; | ||
|
||
return ( | ||
<> | ||
{!!history && persistFilters ? ( | ||
<PersistentFilters | ||
viewsRestorationKey={viewsRestorationKey} | ||
history={history} | ||
schema={filteredSchema} | ||
filters={filters} | ||
views={storedViews} | ||
onFiltersChange={changeFilters} | ||
onViewsChange={viewsUpdate} | ||
renderMode={renderMode ?? DEFAULT_RENDER_MODE} | ||
onSearch={onSearch} | ||
// compact={[true, true, false]} | ||
// showSaveView={showSaveView} | ||
/> | ||
) : ( | ||
<FiltersComponent | ||
schema={filteredSchema} | ||
filters={filters} | ||
views={storedViews} | ||
onFiltersChange={changeFilters} | ||
onViewsChange={viewsUpdate} | ||
renderMode={renderMode ?? DEFAULT_RENDER_MODE} | ||
onSearch={onSearch} | ||
// compact={[true, true, false]} | ||
// showSaveView={showSaveView} | ||
/> | ||
)} | ||
</> | ||
); | ||
}; |
Oops, something went wrong.