Skip to content

Commit

Permalink
[STTYPES-6] [UILISTS-92] Add typings for SearchAndSort and friends (#51)
Browse files Browse the repository at this point in the history
* Connected sources

* logger, doh

* more deps

* remove apollo dep

* Searching AND sorting, wow!
  • Loading branch information
ncovercash authored Jan 9, 2024
1 parent 77f3250 commit 61a05c1
Show file tree
Hide file tree
Showing 37 changed files with 773 additions and 27 deletions.
2 changes: 1 addition & 1 deletion components/lib/AdvancedSearch/AdvancedSearch.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,4 @@ export interface AdvancedSearchProps {
* />
* ```
*/
export default function AdvancedSearch(props: AdvancedSearchProps): ReactNode;
export default function AdvancedSearch(props: AdvancedSearchProps): JSX.Element;
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
},
"dependencies": {
"@folio/stripes-react-hotkeys": "^3.0.0",
"history": "^4.10.1",
"ky": "^0.33.3",
"moment": "^2.29.4",
"popper.js": "^1.16.1",
Expand Down
78 changes: 55 additions & 23 deletions smart-components/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,59 @@ export const LocationSelection: any;
export const PasswordValidationField: any;
export const PersistedPaneset: any;
export const ProxyManager: any;
export const SearchAndSort: any;
export const SearchAndSortQuery: any;
export const SearchAndSortNoResultsMessage: any;
export const SearchAndSortResetButton: any;
export const SearchAndSortSearchButton: any;
export const CheckboxFilter: any;
export const ExpandFilterPaneButton: any;
export const CollapseFilterPaneButton: any;
export const MultiSelectionFilter: any;
export const DateRangeFilter: any;
export const makeQueryFunction: any;
export const makeConnectedSource: any;
export const StripesConnectedSource: any;
export const ApolloConnectedSource: any;
export const getNsKey: any;
export const mapNsKeys: any;
export const removeNsKeys: any;
export const parseFilters: any;
export const deparseFilters: any;
export const buildUrl: any;

export { default as SearchAndSort, SearchAndSortProps } from './lib/SearchAndSort';
export { default as SearchAndSortQuery } from './lib/SearchAndSort/SearchAndSortQuery';
export {
default as SearchAndSortNoResultsMessage,
SearchAndSortNoResultsMessageProps,
} from './lib/SearchAndSort/components/NoResultsMessage';
export {
default as SearchAndSortResetButton,
SearchAndSortResetButtonProps,
} from './lib/SearchAndSort/components/ResetButton';
export {
default as SearchAndSortSearchButton,
SearchAndSortSearchButtonProps,
} from './lib/SearchAndSort/components/SearchButton';
export {
default as CheckboxFilter,
CheckboxFilterProps,
} from './lib/SearchAndSort/components/CheckboxFilter';
export {
default as ExpandFilterPaneButton,
ExpandFilterPaneButtonProps,
} from './lib/SearchAndSort/components/ExpandFilterPaneButton';
export {
default as CollapseFilterPaneButton,
CollapseFilterPaneButtonProps,
} from './lib/SearchAndSort/components/CollapseFilterPaneButton';
export {
default as MultiSelectionFilter,
MultiSelectionFilterProps,
} from './lib/SearchAndSort/components/MultiSelectionFilter';
export {
default as DateRangeFilter,
DateRangeFilterProps,
} from './lib/SearchAndSort/components/DateRangeFilter';

export { default as makeQueryFunction, QueryFunction } from './lib/SearchAndSort/makeQueryFunction';
export { default as advancedSearchQueryToRows } from './lib/SearchAndSort/advancedSearchQueryToRows';

export {
default as makeConnectedSource,
ConnectedSource,
ConnectedSourceProps,
ApolloConnectedSourceProps,
StripesConnectedSourceProps,
} from './lib/SearchAndSort/ConnectedSource';
export { default as StripesConnectedSource } from './lib/SearchAndSort/ConnectedSource/StripesConnectedSource';
export { default as ApolloConnectedSource } from './lib/SearchAndSort/ConnectedSource/ApolloConnectedSource';

export * from './lib/SearchAndSort/nsQueryFunctions';
export * from './lib/SearchAndSort/parseFilters';

export { default as buildUrl } from './lib/SearchAndSort/buildUrl';

export { default as Settings, SettingsProps } from './lib/Settings';

Expand All @@ -62,6 +95,5 @@ export const useRemoteStorageMappings: any;
export const useSetRef: any;
export const useSetRefOnFocus: any;
export const usePrevious: any;
export const ColumnManager: any;
export const ColumnManagerMenu: any;
export const useColumnManager: any;

export * from './lib/ColumnManager';
50 changes: 50 additions & 0 deletions smart-components/lib/ColumnManager/ColumnManager.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { ReactNode } from 'react';

export interface ColumnManagerProps {
/** The render-prop function that will receive the relevant props for implementing toggleable columns */
children: (props: {
/** An array of visible column keys that can be passed directly down to the `<MultiColumnList>` */
visibleColumns: string[];
/** Renders a <MenuSection> that wraps renderCheckboxes for toggling columns. This makes it easy to implement inside e.g. a pane action menu. */
renderColumnsMenu: ReactNode;
/** A method that toggles the visiblity for a given column – e.g. `toggleColumn('email')` */
toggleColumn: (key: string) => void;
}) => ReactNode;
/** An object that maps keys to labels. The order of the keys will determine the default order of the columns. */
columnMapping: Record<string, ReactNode>;
/** An array of keys to exclude from the list of toggleable columns */
excludeKeys?: string[];
/**
* The unique ID is used to generate the storage key for persisting the visible columns in sessionStorage.
* The ID will also be used as a prefixed ID for any UI that is passed down to the render-prop function.
*/
id: string;
/** Whether or not to persist the visible columns in sessionStorage */
persist?: boolean;
}

/**
* A render-prop component for implementing toggleable columns in a `<MultiColumnList>`.
*
* @example
* ```
* const columnMapping = {
* status: 'Status',
* name: 'Name',
* barcode: 'Barcode',
* username: 'Username',
* email: 'Email'
* };
*
* <ColumnManager
* id="users-list-columns" // Required
* columnMapping={columnMapping} // Required
* excludeKeys={['name']} // Exclude these keys from being toggleable
* >
* {({ visibleColumns, renderColumnsMenu, toggleColumn }) => {
* // Render UI
* }}
* </ColumnManager>
* ```
*/
export default function ColumnManager(props: ColumnManagerProps): JSX.Element;
17 changes: 17 additions & 0 deletions smart-components/lib/ColumnManager/ColumnManagerMenu.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { ReactNode } from 'react';

export interface ColumnManagerMenuProps {
/** An object that maps keys to labels */
columnMapping: Record<string, ReactNode>;
/** An array of keys to exclude from the list of columns */
excludeColumns?: string[];
/** Unique ID */
prefix: string;
/** An array of visible column keys */
visibleColumns: string[];
}

/**
* Renders an action menu section for toggling columns. Provided by `<ColumnManager>` as `renderColumnsMenu`.
*/
export default function ColumnManagerMenu(props: ColumnManagerMenuProps): JSX.Element;
3 changes: 3 additions & 0 deletions smart-components/lib/ColumnManager/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export { default as ColumnManager, ColumnManagerProps } from './ColumnManager';
export { default as ColumnManagerMenu, ColumnManagerMenuProps } from './ColumnManagerMenu';
export { default as useColumnManager } from './useColumnManager';
11 changes: 11 additions & 0 deletions smart-components/lib/ColumnManager/useColumnManager.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { ReactNode } from 'react';

export default function useColumnManager(
prefix: string,
columnMapping: Record<string, ReactNode>,
persist?: boolean,
visibleColumnsProp?: string[],
): {
visibleColumns: string[];
toggleColumn: (key: string) => void;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import Logger from '../../../../util/logger';
import { ApolloConnectedSourceProps, ApolloError, ConnectedSource } from './ConnectedSource';

export default class ApolloConnectedSource implements ConnectedSource {
constructor(props: ApolloConnectedSourceProps, logger: Logger, resourceName?: string);
records(): unknown[];
resultCount(): number;
totalCount(): number | null | undefined;
pending(): boolean;
loaded(): boolean;
failure(): ApolloError | null | undefined;

failureMessage(): string;
fetchMore(increment: number): void;
successfulMutations(): unknown[];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
import Logger from '../../../../util/logger';
import { QueryFunction } from '../makeQueryFunction';

type ApolloError = {
message: string;
graphQLErrors: unknown[];
networkError: Error | null;
extraInfo: any;
};

export interface ApolloConnectedSourceProps {
apolloResource?: string;
apolloRecordsKey: string;
queryFunction: QueryFunction;
parentData: {
// properties directly on parentData
loading?: boolean;
successfulMutations?: unknown[];
error?: ApolloError;
fetchMore(params: {
variables: {
cql: string;
offset: number;
limit: number;
};
// record key is `apolloResource`
updateQuery: (
prev: Record<string, { records: unknown[] }>,
params: { fetchMoreResult: unknown },
) => Record<string, { records: unknown[] }>;
}): void;
} & {
// all within resource name (within recordsObj)
[resourceName: string]: {
totalRecords?: number;
} & {
// equals apolloRecordsKey
[recordsKey: string]: unknown[];
};
};
parentResources: {
query: Record<string, unknown>;
};
}

type StripesError = {
dataKey?: string;
httpStatus?: unknown;
message?: string;
module?: unknown;
resource?: unknown;
throwErrors?: unknown;
};

type StripesResourceType =
| ({
resultCount: number;
notes?: string | boolean;
filters?: string;
} & {
// called recordsObj in code
[resourceName: string]: {
records?: unknown[];
hasLoaded?: boolean;
isPending?: boolean;
failed?: StripesError;
other?: unknown;
successfulMutations?: unknown[];
};
})
| unknown; // these types may not be perfect; putting this to avoid errors

type StripesMutatorType =
| {
resultCount: {
replace: (count: number) => void;
};
resultOffset: {
replace: (offset: number) => void;
};
query: {
replace: (query: unknown) => void;
update: (query: unknown) => void;
};
}
| unknown; // these types may not be perfect; putting this to avoid errors

export interface StripesConnectedSourceProps {
// key is from resourceName
parentResources?: StripesResourceType;
resources?: StripesResourceType;
parentMutator?: StripesMutatorType;
mutator?: StripesMutatorType;
}

export interface ConnectedSource {
records(): unknown[];

/** Number of records retrieved so far */
resultCount(): number;
/**
* Number of records in the result-set, available to be retrieved.
*
* For {@code StripesConnectedSource}, when there are > 10k results to a search, the `totalRecords`
* value comes back as `999999999`, so we use that value to indicate
* that the count is, in fact, undefined vs returning null to indicate
* that the count has not been calculated.
*/
totalCount(): number | null | undefined;

/** True only during a request, false before and after */
pending(): boolean;

/** True only after a request, false before and during */
loaded(): boolean;

failure(): ApolloError | StripesError | undefined | null;

failureMessage(): string;

fetchMore(increment: number): void;

successfulMutations(): unknown[];
}

export type ConnectedSourceProps = ApolloConnectedSourceProps | StripesConnectedSourceProps;

export default function makeConnectedSource(
props: ConnectedSourceProps,
logger: Logger,
resourceName?: string,
): ConnectedSource | null;
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { StripesConnectedSourceProps, ConnectedSource, StripesError } from './ConnectedSource';
import Logger from '../../../../util/logger';

export default class StripesConnectedSource implements ConnectedSource {
constructor(props: StripesConnectedSourceProps, logger: Logger, resourceName?: string);
update(props: StripesConnectedSourceProps, resourceName?: string): void;
records(): unknown[];
resultCount(): number;
totalCount(): number | null | undefined;
pending(): boolean;
loaded(): boolean;
failure(): StripesError | null | undefined;
failureMessage(): string;
fetchMore(increment: number): void;
fetchByBrowsePoint(browsePoint: unknown): void;
fetchOffset(index: number): void;
successfulMutations(): unknown[];
}
7 changes: 7 additions & 0 deletions smart-components/lib/SearchAndSort/ConnectedSource/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export {
default,
ConnectedSource,
ConnectedSourceProps,
ApolloConnectedSourceProps,
StripesConnectedSourceProps,
} from './ConnectedSource';
Loading

0 comments on commit 61a05c1

Please sign in to comment.