UNPKG

@croz/nrich-registry-core

Version:

Contains core utilities related to the nrich-registry module

689 lines (669 loc) 23.6 kB
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 };