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.

    Install

    npm i react-application-core

    DownloadsWeekly Downloads

    1,581

    Version

    0.0.412

    License

    MIT

    Unpacked Size

    4.27 MB

    Total Files

    1686

    Last publish

    Collaborators

    • apoterenko