@croz/nrich-registry-core
Version:
Contains core utilities related to the nrich-registry module
689 lines (669 loc) • 23.6 kB
TypeScript
import React, { EffectCallback, ChangeEvent } from 'react';
import * as zustand from 'zustand';
import * as yup from 'yup';
/**
* Parameters for pagination when fetching entities from backend.
*/
interface PagingParameter {
/**
* Page number. Starts from 0.
*/
pageNumber: number;
/**
* Number of entities to fetch.
*/
pageSize: number;
}
/**
* Response data regarding paging when fething entities from backend.
*/
interface PagingResponse {
/**
* Is this page the first one.
*/
first: boolean;
/**
* Is this page the last one.
*/
last: boolean;
/**
* Is this page empty.
*/
empty: boolean;
/**
* Number of total pages for this search.
*/
totalPages: number;
/**
* Number of total elements over all pages for this search.
*/
totalElements: number;
/**
* Number of elements on current page.
*/
numberOfElements: number;
}
interface RegistryConfiguration {
/**
* Base URL for all function in service.ts
*/
baseURL?: string;
/**
* Additional configuration options to send with fetch request i.e. if some authentication information is required.
*/
requestOptionsResolver?: () => RequestInit;
}
/**
* Represents client property configuration that can be used when building form and grids on client side.
*/
interface RegistryPropertyConfiguration {
/**
* Property name.
*/
name: string;
/**
* Property Javascript type (converted from property type).
*/
javascriptType: string;
/**
* Property original type class name
*/
originalType: string;
/**
* Whether this property is id.
*/
id: boolean;
/**
* Whether this property is decimal (Javascript has no specific decimal type).
*/
decimal: boolean;
/**
* Whether this property represents a singular association (JPA @OneToOne or @ManyToOne)
*/
singularAssociation: boolean;
/**
* Singular association class
*/
singularAssociationReferencedClass?: string;
/**
* Label for this property in form view.
*/
formLabel: string;
/**
* Header for this property in table view.
*/
columnHeader: string;
/**
* Whether this property is editable.
*/
editable: boolean;
/**
* Whether this property is sortable.
*/
sortable: boolean;
/**
* Whether this property is searchable.
*/
searchable: boolean;
}
/**
* Represents client entity configuration that can be used when building form and grids on client side.
*/
interface RegistryEntityConfiguration {
/**
* Fully qualified classname of this registry entity.
*/
classFullName: string;
/**
* Simple class name.
*/
name: string;
/**
* Name to be displayed.
*/
displayName: string;
/**
* Group to which this registry belongs to.
*/
groupId: string;
/**
* Whether this entity is read only.
*/
readOnly: boolean;
/**
* Whether new instances of this entity can be created.
*/
creatable: boolean;
/**
* Whether this entity can be updated.
*/
updateable: boolean;
/**
* Whether this entity can be deleted.
*/
deletable: boolean;
/**
* Whether this entity has identifier assigned.
*/
identifierAssigned: boolean;
/**
* Whether this entity has IdClass identifier.
*/
idClassIdentity: boolean;
/**
* Whether this entity has EmbeddedId identifier.
*/
embeddedIdentity: boolean;
/**
* List of property names from which the id consists of.
*/
idClassPropertyNameList: string[];
/**
* Whether history for this entity is available.
*/
historyAvailable: boolean;
/**
* List of property configurations.
*/
propertyConfigurationList: RegistryPropertyConfiguration[];
/**
* List of embedded id property configurations.
*/
embeddedIdPropertyConfigurationList: RegistryPropertyConfiguration[];
/**
* List of history properties, only available if history exists.
*/
historyPropertyConfigurationList: RegistryPropertyConfiguration[];
}
/**
* Configuration for registry group (a group of registry entities).
*/
interface RegistryGroupConfiguration {
/**
* Unique id of group.
*/
groupId: string;
/**
* Display label for group.
*/
groupIdDisplayName: string;
/**
* List of entity configurations belonging to this group.
*/
entityConfigurationList: RegistryEntityConfiguration[];
}
/**
* Registry entity search parameters.
*/
interface SearchParameter {
/**
* List of properties to search.
*/
propertyNameList: string[];
/**
* Search query.
*/
query: string;
}
/**
* Sort direction.
*/
type SortDirection = "ASC" | "DESC";
/**
* Combination of property to sort by and sort direction.
*/
interface SortProperty {
/**
* Property to sort by.
*/
property: string;
/**
* Sort direction.
*/
direction: SortDirection;
}
/**
* Data regarding sorting when fetching entites from backend.
*/
interface SortResponse {
/**
* Is the result sorted.
*/
sorted: boolean;
/**
* Is the result unsorted.
*/
unsorted: boolean;
}
/**
* Type of form on registry entity administration
*/
type FormType = "create" | "update" | "preview";
/**
* Type for {@link #RegistryEntityContext} value
*/
interface RegistryEntityContextType {
/**
* Configuration of administered registry entity
*/
entityConfiguration: RegistryEntityConfiguration;
/**
* Final list of properties to be shown on table or in form. For simple registry, contains only propertyConfigurationList.
* For entities with complex ids it contains all fields from id object mapped for easier usage and UX
*/
finalProperties: RegistryPropertyConfiguration[];
/**
* Map containing entity configurations for all sub-entities of this entity.
* Key is full class name, and value is configuration
*/
singularAssociationsMap: Record<string, RegistryEntityConfiguration>;
}
/**
* Helper context used for easier data sharing in registry entity administration components
*/
declare const RegistryEntityContext: React.Context<RegistryEntityContextType>;
/**
* Helper hook to get registry entity context. Throws if the user is not inside provider.
*/
declare const useRegistryEntityContext: () => RegistryEntityContextType;
/**
* {@link #RegistryEntityContextProvider} props
*/
interface Props$1 {
/**
* Configuration of the administered entity
*/
entityConfiguration: RegistryEntityConfiguration;
/**
* Children where this context is provided
*/
children: React.ReactNode;
}
/**
* Helper provider for {@link #RegistryEntityContext} used for easier data sharing in registry entity administration components
* @param entityConfiguration configuration of the administered entity
* @param children children where this context is provided
*/
declare const RegistryEntityContextProvider: ({ entityConfiguration, children }: Props$1) => JSX.Element;
interface RegistryConfigurationStore {
/**
* Array of group configurations.
*/
groupConfigurations: RegistryGroupConfiguration[];
/**
* Load configuration
*/
load: (groupConfigurations: any) => void;
/**
* Entity formatters used for rendering complex entity types
*/
entityFormatters: Record<string, (value: any) => string>;
/**
* Entity formatters setter
*/
setEntityFormatters: (entityFormatters: Record<string, (value: any) => string>) => void;
/**
* Registry configuration
*/
registryConfiguration: RegistryConfiguration;
/**
* Registry configuration setter
*/
setRegistryConfiguration: (registryConfiguration: RegistryConfiguration) => void;
}
declare const useRegistryConfigurationStore: zustand.UseBoundStore<zustand.StoreApi<RegistryConfigurationStore>>;
/**
* {@link RegistryProvider} properties
*/
interface Props extends Partial<RegistryConfigurationStore> {
/**
* Children where registry configuration is provided
*/
children: React.ReactNode;
}
/**
* Provider for registry configuration. Until registry is fetched, renders loading screen.
* @param children Children where registry configuration is provided
* @param registryConfiguration Registry configuration for baseURL and requestOptionsResolver
* @param entityFormatters Formatters for complex object types
*/
declare const RegistryProvider: ({ children, registryConfiguration, entityFormatters }: Props) => JSX.Element;
/**
* Request when fetching a list of registry entries.
*/
type RegistryRequest = {
/**
* Full Java class name of the registry entity
*/
classFullName: string;
/**
* List of sort rules for this search request
*/
sortPropertyList?: SortProperty[];
/**
* Search configuration for this request
*/
searchParameter?: SearchParameter;
} & PagingParameter;
/**
* Response of a single registry entity request.
*/
type RegistryResponse<T> = {
/**
* List of result entities.
*/
content: T[];
/**
* Result sort.
*/
sort: SortResponse;
} & PagingResponse;
/**
* Fetches whole registry configuration.
*/
declare const loadRegistryConfiguration: () => Promise<RegistryGroupConfiguration[]>;
/**
* Fetches single registry entity list with given paging and sorting parameters.
* @param request Single load request which contains entity class, paging, sorting and search options
* @returns List of entity results
*/
declare const loadEntities: (request: RegistryRequest) => Promise<RegistryResponse<any>>;
/**
* Fetches multiple registry entity lists for given registry requests.
* @param requests List of registry requests
* @returns Map of results where key is full class name and value is single entity response list
*/
declare const bulkLoadEntities: (requests: RegistryRequest[]) => Promise<Record<string, RegistryResponse<any>>>;
/**
* Creates new entry for given registry entity
* @param classFullName Full Java class name of the registry entity
* @param createData Object with data of new entity
* @returns Created entity
*/
declare const createEntity: (classFullName: string, createData: any) => Promise<any>;
/**
* Updates existing entity with new data
* @param classFullName Full Java class name of the registry entity
* @param id Id of the existing entity
* @param updateData Object with update date for existing entity
* @returns Updated entity
*/
declare const updateEntity: (classFullName: string, id: any, updateData: any) => Promise<any>;
/**
* Deletes existing entity
* @param classFullName Full Java class name of the registry entity
* @param id Id of the existing entity
*/
declare const removeEntity: (classFullName: string, id: any) => Promise<any>;
/**
* Request when fetching a list of registry entries, without class specifics
*/
type EntityRegistryRequest = Omit<RegistryRequest, "classFullName">;
/**
* Return type of {@link useRegistryEntity}. Contains main data and methods for managing registry entities.
*/
interface UseRegistryEntity {
/**
* Configuration of wanted entity
*/
entityConfiguration: RegistryEntityConfiguration;
/**
* Id property of the entity
*/
entityIdProperty: RegistryPropertyConfiguration;
/**
* Currently fetched data for this entity.
*/
data: RegistryResponse<any[]>;
/**
* Method for reloading data explicitly with given request.
* @param request search, filter and paging data of this request
*/
load: (request: EntityRegistryRequest) => Promise<void>;
/**
* Adds new entity. Should conform to structure from {@link entityConfiguration}.
* Automatically re-fetches with request provided to hook.
* @param createData data for new entity
*/
add: (createData: any) => Promise<any>;
/**
* Edits existing entity. Should conform to structure from {@link entityConfiguration}.
* Automatically re-fetches with request provided to hook.
* @param id id of the data for editing. When complex ids are used, it should be an object containing all id fields.
* @param updateData data for editable entity
*/
edit: (id: any, updateData: any) => Promise<any>;
/**
* Deletes existing entity.
* Automatically re-fetches with request provided to hook.
* @param id id of the data for editing. When complex ids are used, it should be an object containing all id fields.
*/
remove: (id: any) => Promise<any>;
}
/**
* Default request for fetching used when other is not provided. Starts on first page with size of 25.
*/
declare const DEFAULT_INITIAL_REQUEST: EntityRegistryRequest;
declare const useRegistryEntity: (name: string, initialRequest?: EntityRegistryRequest) => UseRegistryEntity;
/**
* Return value of {@link useRegistryEntityAdministration} hook. Contains all configuration, data and handlers for most of the administration operations.
*/
interface UseRegistryEntityAdministration {
/**
* Configuration of wanted entity
*/
entityConfiguration: RegistryEntityConfiguration;
/**
* Id property of the entity
*/
entityIdProperty: RegistryPropertyConfiguration;
/**
* Currently fetched data for this entity.
*/
data: RegistryResponse<any[]>;
/**
* Currently used request for fetching.
*/
request: EntityRegistryRequest;
/**
* Handler when paging (page number or size) is changed. Refeteches data with new paging configuration.
* Reuses filter configuration if any is used.
* @param newPagingRequest new paging configuration for fetching. Non paging fields are ignored.
*/
handlePagingUpdate: (newPagingRequest: EntityRegistryRequest) => Promise<void>;
/**
* Handler when filter (query and search fields) is changed. Refeteches with new filter configuration.
* Reuses page size and resets page to 0.
*/
handleFilterUpdate: (searchParameter: SearchParameter) => Promise<void>;
/**
* Handler for adding new entry. Opens up modal for form to be filled.
*/
handleAddClick: () => void;
/**
* Handler for adding new entry from copied one. Opens up modal with filled data from copied entry.
* @param row data of the entry to be edited
*/
handleAddFromCopyClick: (row: any) => void;
/**
* Handler for editing existing entry. Opens up modal with filled data to be edited.
* @param id id of the entry to be edited
* @param row data of the entry to be edited
*/
handleEditClick: (id: any, row: any) => void;
/**
* Handler for entry preview. Opens up modal with filled data from entry.
* @param row data of the entry to be previewed
*/
handlePreviewClick: (row: any) => void;
/**
* Handler for submitting add or edit form. Closes modal and tries to save new data.
* @param values data of new/edited entry for saving
*/
handleSubmitClick: (values: any) => Promise<any>;
/**
* Current form type (create or update). Undefined if no form is currently active.
*/
formType?: FormType;
/**
* Initial data when opening form. Empty object for adding, and row data for editing.
*/
formData: any;
/**
* Flag which marks if form modal is open or not.
*/
formModalOpen: boolean;
/**
* Method for explicit closing of form modal.
*/
closeFormModal: () => void;
/**
* Flag if data is currently loading.
*/
loading: boolean;
/**
* Deletes existing entity.
* Automatically re-fetches with request provided to hook.
* @param id id of the data for editing. When complex ids are used, it should be an object containing all id fields.
*/
remove: (id: any) => Promise<any>;
}
/**
* Helper hook which handles most of the administration for registry entity. For given entity name you get all the data handling out of the box.
* This hook assumes that modal is used for forms, but usage can be what fits the case.
* @param entityName name of the entity for administration
*/
declare const useRegistryEntityAdministration: (entityName: string) => UseRegistryEntityAdministration;
/**
* Helper hook for fetching validation configuration for given entity
* @param classFullName full class name of the entity
* @param type type of form
*/
declare const useRegistryEntityYupFormConfiguration: (classFullName: string, type: FormType) => yup.ObjectSchema<any, yup.AnyObject, any, "">;
/**
* Helper hook, similar to useEffect, but doesn't trigger on initial load.
* @param effect effect to be triggered
* @param dependencies dependency array of the effect
*/
declare const useUpdateEffect: (effect: EffectCallback, dependencies?: React.DependencyList) => void;
/**
* Helper hook, similar to useEffect, but has additional debounce effect. Doesn't trigger on initial load.
* Calls effect only once for multiple triggers, when debounce timer expires. Usefully in search/filters, to filter out unnecessary requests.
* @param effect effect to be triggered
* @param debounceTime time in milliseconds for debounce
* @param dependencies dependecy array of the effect
*/
declare const useDebouncedUpdateEffect: (effect: EffectCallback, debounceTime: number, dependencies?: React.DependencyList) => void;
/**
* Return value of {@link useRegistryFilter}. Contains configuration, value and change handlers for registry filter.
*/
interface UseRegistryFilter {
/**
* List of available fields for filtering
*/
availableFields: {
value: string;
label: string;
}[];
/**
* Current value of request {@link SearchParameter}
*/
searchParameter: SearchParameter;
/**
* Change handler for search fields
* @param event change event (usually from multiselect field)
*/
handleFieldsChange: (event: ChangeEvent) => void;
/**
* Change handler for query
* @param event change event (usually from text field)
*/
handleQueryChange: (event: ChangeEvent) => void;
}
/**
* Helper hook that handles filtering states for administered registry entity. Only handles fields and leaves refeching to hook user.
* @param initialFilterValue initial filter value
*/
declare const useRegistryFilter: (initialFilterValue?: SearchParameter) => UseRegistryFilter;
/**
* Return value of {@link useRegistryForm}. Contains configuration part of the form, with initial values, while leaving user to
* handle form changes and errors.
*/
interface UseRegistryForm {
/**
* Configuration of wanted entity
*/
entityConfiguration: RegistryEntityConfiguration;
/**
* Validation schema of the form
*/
yupSchema: yup.ObjectSchema<any>;
/**
* Flattened initial values for easier access in form.
*/
finalInitialValues: any;
/**
* Properties to be shown in the form.
*/
properties: any;
}
/**
* Helper hook used in registry forms. Returns initial data and configuration to be used in the form.
* @param initialValues initial values of the form. Row data for update and empty object for create form.
* @param type type of the form (update or create)
*/
declare const useRegistryForm: (initialValues: any, type: FormType) => UseRegistryForm;
/**
* Return value of {@link useRegistrySort} hook. Contains state and sort handler which uses natural flow for sorting (asc -> desc -> none)
*/
interface UseRegistrySort {
/**
* Current sort direction. Undefined if no sort is applied.
*/
sortDirection?: SortDirection;
/**
* Change handler for sort, usually triggered on table header click. Changes sorting to next state. (asc -> desc -> none)
*/
sortChangeHandler: () => void;
}
/**
* Helper hook used for table headers to add functionality of sorting by specific field
* @param propertyConfiguration configuration of the column property
* @param value current list of sort properties
* @param onChange change handler to be called with new sort properties
* @param allowMultiple flag if multiple properties can be sorted at the same time. Default is true
*/
declare const useRegistrySort: (propertyConfiguration: RegistryPropertyConfiguration, value: SortProperty[], onChange: (newValue: SortProperty[]) => void, allowMultiple?: boolean) => UseRegistrySort;
/**
* Returns an id representation for given entity configuration and data. Can be single value (e.g. when id is numeric) or an object
* when embedded id or id class is used
* @param entityConfiguration
* @param data
*/
declare const resolveId: (entityConfiguration: any, data: any) => any;
/**
* Resolves a value for flat property from nested data.
* @param propertyConfiguration
* @param data
*/
declare const resolveValue: (propertyConfiguration: any, data: any) => any;
/**
* Rearranges object from flat structure to nested one, e.g.
* { "id.author": { "id": 1 }, "id.book": { "id": 3 }, "edition": "First edition" } to
* { "id": { "author": { "id": 1 }, "book": { "id": 3 } }, "edition": "First edition" }
* @param value form value for submission
*/
declare const restructureSubmitValue: (value: any) => {};
/**
* Formats id field as Class[id=3]. Used as default for rendering objects
* @param classFullName full name of class for formatting
* @param idFieldName name of the id field
* @param id value of the id field
*/
declare const formatIdName: (classFullName: string, idFieldName: string, id: any) => string;
/**
* Returns id field of the configuration, used when entity does not have embedded id nor id class.
* @param entityConfiguration configuration of the registry entity
*/
declare const findIdField: (entityConfiguration: RegistryEntityConfiguration) => RegistryPropertyConfiguration;
export { DEFAULT_INITIAL_REQUEST, EntityRegistryRequest, FormType, PagingParameter, PagingResponse, RegistryConfiguration, RegistryConfigurationStore, RegistryEntityConfiguration, RegistryEntityContext, RegistryEntityContextProvider, RegistryGroupConfiguration, RegistryPropertyConfiguration, RegistryProvider, RegistryRequest, RegistryResponse, SearchParameter, SortDirection, SortProperty, SortResponse, UseRegistryEntity, bulkLoadEntities, createEntity, findIdField, formatIdName, loadEntities, loadRegistryConfiguration, removeEntity, resolveId, resolveValue, restructureSubmitValue, updateEntity, useDebouncedUpdateEffect, useRegistryConfigurationStore, useRegistryEntity, useRegistryEntityAdministration, useRegistryEntityContext, useRegistryEntityYupFormConfiguration, useRegistryFilter, useRegistryForm, useRegistrySort, useUpdateEffect };