react-application-core
TypeScript icon, indicating that this package has built-in type declarations

0.0.412 • Public • Published

React Application Core

A react-based application core for the business applications.

Build Status

Flow

Flow

Description

The library is designed to quickly start develop the business applications are based on React, Redux, Material-UI.

Demo

Dependencies

Classes & markers

@action-builder

@component-container-impl

@component-impl

@effects-proxy-factory EffectsFactories

@reducer

@map

@middleware

@configuration-entity

@redux-holder-entity

Utils

Theme customization (styling)

Button

Chart

Chip

DefaultLayout

Dialog

DnD

Drawer

Field

Form

FormLayout

Header

Main

NavigationList

PageToolbar

SubHeaderLink

TabPanel

TextField

Title

Usage

Containers

Roles container
import * as React from 'react';

import {
  listWrapperMapper,
  filterWrapperMapper,
  defaultMappers,
  BaseContainer,
  DefaultLayoutContainer,
  ListContainer,
  ContainerVisibilityTypeEnum,
  actionsDisabledListWrapperEntityMapper,
  connector,
  SearchFieldToolbarContainer,
} from 'react-application-core';

import { ROUTER_PATHS } from '../../app.routes';
import { IRolesContainerProps, ROLES_SECTION } from './roles.interface';
import { IAppState } from '../../app.interface';
import { AccessConfigT, IRoleEntity } from '../permission.interface';
import { AppPermissions } from '../../app.permissions';

@connector<IAppState, AccessConfigT>({
  routeConfiguration: {
    type: ContainerVisibilityTypeEnum.PRIVATE,
    path: ROUTER_PATHS.ROLES,
  },
  accessConfiguration: [AppPermissions.ROLES_VIEW],
  mappers: [
    ...defaultMappers,
    (state) => filterWrapperMapper(state.roles),
    (state) => listWrapperMapper(state.roles)
  ],
})
class RolesContainer extends BaseContainer<IRolesContainerProps> {

  public static defaultProps: IRolesContainerProps = {
    sectionName: ROLES_SECTION,
  };

  public render(): JSX.Element {
    const props = this.props;
    const header = <SearchFieldToolbarContainer filterConfiguration={actionsDisabledListWrapperEntityMapper(props)}
                                               {...props}/>;
    return (
      <DefaultLayoutContainer headerConfiguration={{ 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,
  connector,
  LayoutBuilder,
  LayoutBuilderTypeEnum,
} from 'react-application-core';

import { IRoleContainerProps, 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>({
  routeConfiguration: {
    type: ContainerVisibilityTypeEnum.PRIVATE,
    path: ROUTER_PATHS.ROLE,
  },
  accessConfiguration: [AppPermissions.ROLE_VIEW],
  mappers: [
    ...defaultMappers,
    (state) => formMapper(state.roles.role),
    (state) => listWrapperSelectedEntityMapper(state.roles, state.roles.role)
  ],
})
class RoleContainer extends BaseContainer<IRoleContainerProps> {

  public static defaultProps: IRoleContainerProps = {
    sectionName: ROLE_SECTION,
  };

  private readonly layoutBuilder = new LayoutBuilder();

  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 headerConfiguration={{
                                navigationActionType: 'arrow_back',
                                onNavigationActionClick: this.activateFormDialog,
                              }}
                              title={title}
                              {...props}>
        <FormContainer {...props}>
          {
            this.layoutBuilder.build({
              layout: LayoutBuilderTypeEnum.VERTICAL,
              children: [
                <TextField name='name'
                           label='Name'
                           autoFocus={true}
                           required={true}/>,
                <ChipsField name='rights'
                            label='Rights'
                            options={toSelectOptions(rights)}
                            bindDictionary={RIGHTS_DICTIONARY}
                            menuConfiguration={{ 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,
  makeFailedListLoadEffectsProxy,
  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 }),
  makeFailedListLoadEffectsProxy(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);
  }
}
Access group effects
import {
  EffectsService,
  IEffectsAction,
} from 'redux-effects-promise';
import {
  BaseEffects,
  CustomActionBuilder,
  DiSupport,
  effectsBy,
  EffectsFactories,
  FormActionBuilder,
  ListActionBuilder,
  RouterActionBuilder,
  Selectors,
} from 'react-application-core';

import { IPosAccessGroupEntity } from 'pos';

import { IApi } from '../../../api';
import { IPortalState } from '../../../app.interface';
import { PA_GROUP_SECTION } from './portal-access-group.interface';
import { PA_GROUPS_SECTION } from '../portal-access-groups.interface';
import { PortalRoutes } from '../../../app.routes';

@DiSupport.provideInSingleton(PortalAccessGroupEffects)
@effectsBy(
  EffectsFactories.formSubmitErrorEffectsProxy(PA_GROUP_SECTION),
  EffectsFactories.succeedEditedListEffectsProxy({
    listSection: PA_GROUPS_SECTION,
    formSection: PA_GROUP_SECTION,
  })
)
class PortalAccessGroupEffects extends BaseEffects<IApi> {

  /**
   * @stable [01.08.2020]
   * @param action
   */
  @EffectsService.effects(FormActionBuilder.buildSubmitActionType(PA_GROUP_SECTION))
  public $onSaveAccessGroup = (action: IEffectsAction): Promise<IPosAccessGroupEntity> =>
    this.api.saveAccessGroup(action.data)

  /**
   * @stable [01.08.2020]
   * @param action
   * @param state
   */
  @EffectsService.effects(CustomActionBuilder.buildCustomDeleteActionType(PA_GROUP_SECTION))
  public async $onDeleteAccessGroup(action: IEffectsAction, state: IPortalState): Promise<IEffectsAction[]> {
    await this.api.deleteAccessGroup(
      Selectors.listSelectedEntity<IPosAccessGroupEntity>(state.access.accessGroups).id
    );
    return [
      ListActionBuilder.buildLoadAction(PA_GROUPS_SECTION),
      RouterActionBuilder.buildReplaceAction(PortalRoutes.ACCESS_GROUPS)
    ];
  }
}

License

Licensed under MIT.

Package Sidebar

Install

npm i react-application-core

Weekly Downloads

37

Version

0.0.412

License

MIT

Unpacked Size

4.27 MB

Total Files

1686

Last publish

Collaborators

  • apoterenko