React Application Core
A react-based application core for the business applications.
The library is designed to quickly start developing business applications are based on React, Redux, Material-UI.
Usage
Containers
Roles container
import * as React from 'react';
import {
listWrapperMapper,
filterWrapperMapper,
defaultMappers,
BaseContainer,
DefaultLayoutContainer,
SearchToolbarContainer,
ListContainer,
ContainerVisibilityTypeEnum,
IBaseContainerInternalProps,
disabledActionsListWrapperMapper,
connector,
} from 'react-application-core';
import { ROUTER_PATHS } from '../../app.routes';
import { IRolesContainerInternalProps, ROLES_SECTION } from './roles.interface';
import { IAppState } from '../../app.interface';
import { AccessConfigT, IRoleEntity } from '../permission.interface';
import { AppPermissions } from '../../app.permissions';
@connector<IAppState, AccessConfigT>({
routeConfig: {
type: ContainerVisibilityTypeEnum.PRIVATE,
path: ROUTER_PATHS.ROLES,
},
accessConfig: [AppPermissions.ROLES_VIEW],
mappers: [
...defaultMappers,
(state) => filterWrapperMapper(state.roles),
(state) => listWrapperMapper(state.roles)
],
})
class RolesContainer extends BaseContainer<IRolesContainerInternalProps, {}> {
public static defaultProps: IBaseContainerInternalProps = {
sectionName: ROLES_SECTION,
};
public render(): JSX.Element {
const props = this.props;
const header = <SearchToolbarContainer filterOptions={disabledActionsListWrapperMapper(props)}
{...props}/>;
return (
<DefaultLayoutContainer headerOptions={{ items: header }}
{...props}>
<ListContainer listConfiguration={{
itemConfiguration: { tpl: this.tpl },
useAddAction: this.permissionService.isAccessible(AppPermissions.ROLE_ADD),
}}
{...props}/>
</DefaultLayoutContainer>
);
}
private tpl = (item: IRoleEntity): JSX.Element => (
<span>
{item.name} {this.nc.id(item.id)}
</span>
)
}
Role container
import * as React from 'react';
import {
BaseContainer,
FormContainer,
FormDialog,
TextField,
toSelectOptions,
FORM_DIALOG_REF,
listWrapperSelectedEntityMapper,
formMapper,
DefaultLayoutContainer,
defaultMappers,
ChipsField,
ContainerVisibilityTypeEnum,
IBaseContainerInternalProps,
connector,
LayoutBuilder,
LayoutEnum,
uuid,
} from 'react-application-core';
import { IRoleContainerInternalProps, ROLE_SECTION } from './role.interface';
import { IAppState } from '../../../app.interface';
import { RIGHTS_DICTIONARY } from '../../../dictionary';
import { ROUTER_PATHS } from '../../../app.routes';
import { AccessConfigT } from '../../permission.interface';
import { AppPermissions } from '../../../app.permissions';
@connector<IAppState, AccessConfigT>({
routeConfig: {
type: ContainerVisibilityTypeEnum.PRIVATE,
path: ROUTER_PATHS.ROLE,
},
accessConfig: [AppPermissions.ROLE_VIEW],
mappers: [
...defaultMappers,
(state) => formMapper(state.roles.role),
(state) => listWrapperSelectedEntityMapper(state.roles, state.roles.role)
],
})
class RoleContainer extends BaseContainer<IRoleContainerInternalProps, {}> {
public static defaultProps: IBaseContainerInternalProps = {
sectionName: ROLE_SECTION,
};
private readonly layoutBuilder = new LayoutBuilder(uuid());
public render(): JSX.Element {
const props = this.props;
const dictionaries = props.dictionaries;
const rights = dictionaries.rights && dictionaries.rights.data;
const title = props.newEntity
? 'New role'
: `Role ${this.nc.id(props.entityId)}`;
return (
<DefaultLayoutContainer headerOptions={{
navigationActionType: 'arrow_back',
navigationActionHandler: this.activateFormDialog,
}}
title={title}
{...props}>
<FormContainer {...props}>
{
this.layoutBuilder.build({
layout: LayoutEnum.VERTICAL,
children: [
<TextField name='name'
label='Name'
autoFocus={true}
required={true}/>,
<ChipsField name='rights'
label='Rights'
options={toSelectOptions(rights)}
bindToDictionary={RIGHTS_DICTIONARY}
menuOptions={{ useFilter: true, renderToCenterOfBody: true }}
displayMessage='%d right(s)'/>
],
})
}
</FormContainer>
<FormDialog ref={FORM_DIALOG_REF}
onAccept={this.navigateToBack}
{...props}/>
</DefaultLayoutContainer>
);
}
}
Effects
Roles effects
import { EffectsService, IEffectsAction } from 'redux-effects-promise';
import {
buildEntityRoute,
provideInSingleton,
ListActionBuilder,
BaseEffects,
effectsBy,
makeFilteredListEffectsProxy,
makeUntouchedListEffectsProxy,
makeFailedListEffectsProxy,
makeEditedListEffectsProxy,
} from 'react-application-core';
import { IApi } from '../../api/api.interface';
import { ROUTER_PATHS } from '../../app.routes';
import { ROLES_SECTION } from './roles.interface';
import { IRoleEntity } from '../permission.interface';
import { IAppState } from '../../app.interface';
import { ROLE_SECTION } from './role';
@provideInSingleton(RolesEffects)
@effectsBy(
makeUntouchedListEffectsProxy<IAppState>({
section: ROLES_SECTION,
resolver: (state) => state.roles,
}),
makeEditedListEffectsProxy<IRoleEntity, IAppState>({
listSection: ROLES_SECTION,
formSection: ROLE_SECTION,
pathResolver: (role) => buildEntityRoute<IRoleEntity>(ROUTER_PATHS.ROLE, role),
}),
makeFilteredListEffectsProxy({ section: ROLES_SECTION }),
makeFailedListEffectsProxy(ROLES_SECTION)
)
class RolesEffects extends BaseEffects<IApi> {
@EffectsService.effects(ListActionBuilder.buildLoadActionType(ROLES_SECTION))
public $onRolesSearch(_: IEffectsAction, state: IAppState): Promise<IRoleEntity[]> {
return this.api.searchRoles(state.roles.filter.query);
}
}
Role effects
import { IEffectsAction, EffectsService } from 'redux-effects-promise';
import {
provideInSingleton,
FormActionBuilder,
IApiEntity,
BaseEffects,
makeSucceedFormEffectsProxy,
makeFailedFormEffectsProxy,
effectsBy,
} from 'react-application-core';
import { ROLES_SECTION } from '../roles.interface';
import { ROLE_SECTION } from './role.interface';
import { IApi } from '../../../api/api.interface';
import { IRoleEntity } from '../../permission.interface';
@provideInSingleton(RoleEffects)
@effectsBy(
makeFailedFormEffectsProxy(ROLE_SECTION),
makeSucceedFormEffectsProxy({
listSection: ROLES_SECTION,
formSection: ROLE_SECTION,
})
)
class RoleEffects extends BaseEffects<IApi> {
@EffectsService.effects(FormActionBuilder.buildSubmitActionType(ROLE_SECTION))
public onSaveRole(action: IEffectsAction): Promise<IRoleEntity> {
return this.api.saveRole(action.data as IApiEntity<IRoleEntity>);
}
}