Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement new simple text filter #1526

Merged
merged 16 commits into from
Jan 22, 2025
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/examples/auth-zero/src/frontend/types.generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ export type AdminUiFilterMetadata = {
export enum AdminUiFilterType {
Boolean = 'BOOLEAN',
DateRange = 'DATE_RANGE',
DropDownText = 'DROP_DOWN_TEXT',
Enum = 'ENUM',
Numeric = 'NUMERIC',
Relationship = 'RELATIONSHIP',
Expand Down
1 change: 1 addition & 0 deletions src/examples/auth-zero/src/types.generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ export type AdminUiFilterMetadata = {
export enum AdminUiFilterType {
Boolean = 'BOOLEAN',
DateRange = 'DATE_RANGE',
DropDownText = 'DROP_DOWN_TEXT',
Enum = 'ENUM',
Numeric = 'NUMERIC',
Relationship = 'RELATIONSHIP',
Expand Down
1 change: 1 addition & 0 deletions src/examples/aws-cognito/src/frontend/types.generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ export type AdminUiFilterMetadata = {
export enum AdminUiFilterType {
Boolean = 'BOOLEAN',
DateRange = 'DATE_RANGE',
DropDownText = 'DROP_DOWN_TEXT',
Enum = 'ENUM',
Numeric = 'NUMERIC',
Relationship = 'RELATIONSHIP',
Expand Down
1 change: 1 addition & 0 deletions src/examples/aws-cognito/src/types.generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ export type AdminUiFilterMetadata = {
export enum AdminUiFilterType {
Boolean = 'BOOLEAN',
DateRange = 'DATE_RANGE',
DropDownText = 'DROP_DOWN_TEXT',
Enum = 'ENUM',
Numeric = 'NUMERIC',
Relationship = 'RELATIONSHIP',
Expand Down
1 change: 1 addition & 0 deletions src/examples/federation/src/frontend/types.generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ export type AdminUiFilterMetadata = {
export enum AdminUiFilterType {
Boolean = 'BOOLEAN',
DateRange = 'DATE_RANGE',
DropDownText = 'DROP_DOWN_TEXT',
Enum = 'ENUM',
Numeric = 'NUMERIC',
Relationship = 'RELATIONSHIP',
Expand Down
1 change: 1 addition & 0 deletions src/examples/federation/src/types.generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ export type AdminUiFilterMetadata = {
export enum AdminUiFilterType {
Boolean = 'BOOLEAN',
DateRange = 'DATE_RANGE',
DropDownText = 'DROP_DOWN_TEXT',
Enum = 'ENUM',
Numeric = 'NUMERIC',
Relationship = 'RELATIONSHIP',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ export type AdminUiFilterMetadata = {
export enum AdminUiFilterType {
Boolean = 'BOOLEAN',
DateRange = 'DATE_RANGE',
DropDownText = 'DROP_DOWN_TEXT',
Enum = 'ENUM',
Numeric = 'NUMERIC',
Relationship = 'RELATIONSHIP',
Expand Down
1 change: 1 addition & 0 deletions src/examples/microsoft-entra/src/types.generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ export type AdminUiFilterMetadata = {
export enum AdminUiFilterType {
Boolean = 'BOOLEAN',
DateRange = 'DATE_RANGE',
DropDownText = 'DROP_DOWN_TEXT',
Enum = 'ENUM',
Numeric = 'NUMERIC',
Relationship = 'RELATIONSHIP',
Expand Down
1 change: 1 addition & 0 deletions src/examples/okta/src/frontend/types.generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ export type AdminUiFilterMetadata = {
export enum AdminUiFilterType {
Boolean = 'BOOLEAN',
DateRange = 'DATE_RANGE',
DropDownText = 'DROP_DOWN_TEXT',
Enum = 'ENUM',
Numeric = 'NUMERIC',
Relationship = 'RELATIONSHIP',
Expand Down
1 change: 1 addition & 0 deletions src/examples/okta/src/types.generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ export type AdminUiFilterMetadata = {
export enum AdminUiFilterType {
Boolean = 'BOOLEAN',
DateRange = 'DATE_RANGE',
DropDownText = 'DROP_DOWN_TEXT',
Enum = 'ENUM',
Numeric = 'NUMERIC',
Relationship = 'RELATIONSHIP',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ export type AdminUiFilterMetadata = {
export enum AdminUiFilterType {
Boolean = 'BOOLEAN',
DateRange = 'DATE_RANGE',
DropDownText = 'DROP_DOWN_TEXT',
Enum = 'ENUM',
Numeric = 'NUMERIC',
Relationship = 'RELATIONSHIP',
Expand Down
1 change: 1 addition & 0 deletions src/examples/rest-with-auth/src/types.generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ export type AdminUiFilterMetadata = {
export enum AdminUiFilterType {
Boolean = 'BOOLEAN',
DateRange = 'DATE_RANGE',
DropDownText = 'DROP_DOWN_TEXT',
Enum = 'ENUM',
Numeric = 'NUMERIC',
Relationship = 'RELATIONSHIP',
Expand Down
1 change: 1 addition & 0 deletions src/examples/rest-with-auth/types.generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ export type AdminUiFilterMetadata = {
export enum AdminUiFilterType {
Boolean = 'BOOLEAN',
DateRange = 'DATE_RANGE',
DropDownText = 'DROP_DOWN_TEXT',
Enum = 'ENUM',
Numeric = 'NUMERIC',
Relationship = 'RELATIONSHIP',
Expand Down
4 changes: 2 additions & 2 deletions src/examples/rest/src/backend/schema/person.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Entity, Field, ID, RelationshipField } from '@exogee/graphweaver';
import { AdminUIFilterType, Entity, Field, ID, RelationshipField } from '@exogee/graphweaver';
import { RestBackendProvider } from '@exogee/graphweaver-rest';

import { urlToIdTransform } from '../utils';
Expand All @@ -20,7 +20,7 @@ export class Person {
@Field(() => ID, { primaryKeyField: true })
url!: string;

@Field(() => String)
@Field(() => String, { adminUIOptions: { filterType: AdminUIFilterType.TEXT } })
name!: string;

@Field(() => String)
Expand Down
1 change: 1 addition & 0 deletions src/examples/rest/src/frontend/types.generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ export type AdminUiFilterMetadata = {
export enum AdminUiFilterType {
Boolean = 'BOOLEAN',
DateRange = 'DATE_RANGE',
DropDownText = 'DROP_DOWN_TEXT',
Enum = 'ENUM',
Numeric = 'NUMERIC',
Relationship = 'RELATIONSHIP',
Expand Down
1 change: 1 addition & 0 deletions src/examples/rest/src/types.generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ export type AdminUiFilterMetadata = {
export enum AdminUiFilterType {
Boolean = 'BOOLEAN',
DateRange = 'DATE_RANGE',
DropDownText = 'DROP_DOWN_TEXT',
Enum = 'ENUM',
Numeric = 'NUMERIC',
Relationship = 'RELATIONSHIP',
Expand Down
1 change: 1 addition & 0 deletions src/examples/sqlite/src/frontend/types.generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ export type AdminUiFilterMetadata = {
export enum AdminUiFilterType {
Boolean = 'BOOLEAN',
DateRange = 'DATE_RANGE',
DropDownText = 'DROP_DOWN_TEXT',
Enum = 'ENUM',
Numeric = 'NUMERIC',
Relationship = 'RELATIONSHIP',
Expand Down
1 change: 1 addition & 0 deletions src/examples/sqlite/src/types.generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ export type AdminUiFilterMetadata = {
export enum AdminUiFilterType {
Boolean = 'BOOLEAN',
DateRange = 'DATE_RANGE',
DropDownText = 'DROP_DOWN_TEXT',
Enum = 'ENUM',
Numeric = 'NUMERIC',
Relationship = 'RELATIONSHIP',
Expand Down
32 changes: 14 additions & 18 deletions src/packages/admin-ui-components/src/entity-list/component.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
import { useMutation, useQuery } from '@apollo/client';
import { addStabilizationToFilter } from '@exogee/graphweaver-apollo-client';
import { Row, RowSelectionState } from '@tanstack/react-table';
import { Outlet, useNavigate, useParams, useSearchParams } from 'react-router-dom';
import { useMemo, useState } from 'react';
import { addStabilizationToFilter } from '@exogee/graphweaver-apollo-client';
import toast from 'react-hot-toast';
import { Outlet, useNavigate, useParams, useSearchParams } from 'react-router-dom';

import { Button } from '../button';
import { generateDeleteManyEntitiesMutation } from '../detail-panel/graphql';
import { ErrorView } from '../error-view';
import { Header } from '../header';
import { ListToolBar } from '../list-toolbar';
import { Modal } from '../modal';
import { SelectionBar } from '../selection-bar';
import { Table } from '../table';
import {
PAGE_SIZE,
SortEntity,
Expand All @@ -14,19 +22,10 @@ import {
useSchema,
} from '../utils';
import { convertEntityToColumns } from './columns';
import { Table } from '../table';
import { Loader } from '../loader';
import { Header } from '../header';
import { QueryResponse, queryForEntityPage } from './graphql';
import { ListToolBar } from '../list-toolbar';
import { Modal } from '../modal';
import { generateDeleteManyEntitiesMutation } from '../detail-panel/graphql';
import { Button } from '../button';
import { SelectionBar } from '../selection-bar';
import { ErrorView } from '../error-view';

import styles from './styles.module.css';
import { ExportModal } from '../export-modal';
import styles from './styles.module.css';

export const EntityList = <TData extends object>() => {
const { entity: entityName, id } = useParams();
Expand Down Expand Up @@ -76,13 +75,10 @@ export const EntityList = <TData extends object>() => {
}
);

if (loading && !data) {
return <Loader />;
}
if (error) {
return <ErrorView message={error.message} />;
}
if (!data) {
if (!loading && !data) {
return <ErrorView message="Error! Unable to load entity." />;
}

Expand Down Expand Up @@ -110,7 +106,7 @@ export const EntityList = <TData extends object>() => {
...variables.pagination,
offset: nextPage * PAGE_SIZE,
},
filter: addStabilizationToFilter(variables.filter ?? {}, sort, data.result?.[0]),
filter: addStabilizationToFilter(variables.filter ?? {}, sort, data?.result?.[0]),
},
});
};
Expand Down Expand Up @@ -158,7 +154,7 @@ export const EntityList = <TData extends object>() => {
return (
<div className={styles.wrapper}>
<Header>
<ListToolBar count={data.aggregate?.count} onExportToCSV={handleShowExportModal} />
<ListToolBar count={data?.aggregate?.count} onExportToCSV={handleShowExportModal} />
</Header>
<Table
loading={loading}
Expand Down
11 changes: 7 additions & 4 deletions src/packages/admin-ui-components/src/filter-bar/component.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import { ReactNode, useEffect, useCallback } from 'react';
import { useNavigate, useParams, useSearchParams } from 'react-router-dom';
import { ReactNode, useCallback, useEffect } from 'react';
import toast from 'react-hot-toast';
import { useNavigate, useParams, useSearchParams } from 'react-router-dom';

import { Button } from '../button';
import { AdminUIFilterType, decodeSearchParams, Filter, routeFor, useSchema } from '../utils';
import {
BooleanFilter,
validateFilter,
DateRangeFilter,
DropdownTextFilter,
EnumFilter,
NumericFilter,
RelationshipFilter,
TextFilter,
validateFilter,
} from '../filters';
import { AdminUIFilterType, decodeSearchParams, Filter, routeFor, useSchema } from '../utils';

import styles from './styles.module.css';

Expand Down Expand Up @@ -118,6 +119,8 @@ export const FilterBar = ({ iconBefore }: { iconBefore?: ReactNode }) => {
switch (field.filter.type) {
case AdminUIFilterType.TEXT:
return <TextFilter key={field.name} {...options} />;
case AdminUIFilterType.DROP_DOWN_TEXT:
return <DropdownTextFilter key={field.name} {...options} />;
case AdminUIFilterType.BOOLEAN:
return <BooleanFilter key={field.name} {...options} />;
case AdminUIFilterType.RELATIONSHIP:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { useLazyQuery } from '@apollo/client';
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Straight clone of the previous TextFilter file


import { ComboBox, Filter, SelectMode, SelectOption, useSchema } from '..';
import { queryForFilterOptions } from './graphql';
import { toSelectOption } from './utils';

export interface DropdownTextFilterProps {
fieldName: string;
entity: string;
onChange?: (fieldName: string, newFilter: Filter) => void;
filter?: Filter;
}

export const DropdownTextFilter = ({
fieldName,
entity,
onChange,
filter,
}: DropdownTextFilterProps) => {
const { entityByName } = useSchema();

const [getData, { loading, error, data }] = useLazyQuery<{
result: Record<string, string>[];
}>(queryForFilterOptions(entityByName(entity), fieldName));

const comboBoxOptions = new Set<string>((data?.result || []).map((value) => value?.[fieldName]));

const handleOnChange = (options?: SelectOption[]) => {
const hasSelectedOptions = (options ?? [])?.length > 0;
onChange?.(
fieldName,
hasSelectedOptions ? { [`${fieldName}_in`]: options?.map((option) => option.value) } : {}
);
};

const handleOnOpen = () => {
if (!data && !loading && !error) {
getData();
}
};

const currentFilterValue = (filter?.[`${fieldName}_in`] as string[]) ?? [];

return (
<ComboBox
key={fieldName}
options={[...comboBoxOptions].map(toSelectOption)}
value={currentFilterValue.map(toSelectOption)}
placeholder={fieldName}
onChange={handleOnChange}
onOpen={handleOnOpen}
loading={loading}
mode={SelectMode.MULTI}
data-testid={`${fieldName}-filter`}
/>
);
};
7 changes: 4 additions & 3 deletions src/packages/admin-ui-components/src/filters/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
export * from './enum-filter';
export * from './text-filter';
export * from './boolean-filter';
export * from './relationship-filter';
export * from './date-range-filter';
export * from './dropdown-text-filter';
export * from './enum-filter';
export * from './numeric-filter';
export * from './relationship-filter';
export * from './text-filter';
export * from './utils';
43 changes: 8 additions & 35 deletions src/packages/admin-ui-components/src/filters/text-filter.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
import { useLazyQuery } from '@apollo/client';

import { Filter, ComboBox, SelectMode, SelectOption, useSchema } from '..';
import { queryForFilterOptions } from './graphql';
import { toSelectOption } from './utils';
import { Filter, Input } from '..';

export interface TextFilterProps {
fieldName: string;
Expand All @@ -11,41 +7,18 @@ export interface TextFilterProps {
filter?: Filter;
}

export const TextFilter = ({ fieldName, entity, onChange, filter }: TextFilterProps) => {
const { entityByName } = useSchema();

const [getData, { loading, error, data }] = useLazyQuery<{
result: Record<string, string>[];
}>(queryForFilterOptions(entityByName(entity), fieldName));

const comboBoxOptions = new Set<string>((data?.result || []).map((value) => value?.[fieldName]));

const handleOnChange = (options?: SelectOption[]) => {
const hasSelectedOptions = (options ?? [])?.length > 0;
onChange?.(
fieldName,
hasSelectedOptions ? { [`${fieldName}_in`]: options?.map((option) => option.value) } : {}
);
export const TextFilter = ({ fieldName, onChange, filter }: TextFilterProps) => {
const handleOnChange = (fieldName: string, newValue?: string) => {
onChange?.(fieldName, newValue ? { [fieldName]: newValue } : {});
};

const handleOnOpen = () => {
if (!data && !loading && !error) {
getData();
}
};

const currentFilterValue = (filter?.[`${fieldName}_in`] as string[]) ?? [];

return (
<ComboBox
<Input
key={fieldName}
options={[...comboBoxOptions].map(toSelectOption)}
value={currentFilterValue.map(toSelectOption)}
placeholder={fieldName}
inputMode="text"
fieldName={fieldName}
value={String(filter?.[fieldName] ?? '')}
onChange={handleOnChange}
onOpen={handleOnOpen}
loading={loading}
mode={SelectMode.MULTI}
data-testid={`${fieldName}-filter`}
/>
);
Expand Down
2 changes: 1 addition & 1 deletion src/packages/admin-ui-components/src/filters/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const getValidFilterProperties = (fields: EntityField[]): Set<string> => {
const supportedKeys = new Set<string>();
for (const field of fields) {
switch (field.filter?.type) {
case AdminUIFilterType.TEXT:
case AdminUIFilterType.DROP_DOWN_TEXT:
supportedKeys.add(field.name);
supportedKeys.add(`${field.name}_in`);
break;
Expand Down
Loading
Loading