Skip to content

Instantly share code, notes, and snippets.

@QuadradS
Last active March 12, 2021 22:51
Show Gist options
  • Save QuadradS/2ae1aef38273b9fb27080de4cf4cf7ad to your computer and use it in GitHub Desktop.
Save QuadradS/2ae1aef38273b9fb27080de4cf4cf7ad to your computer and use it in GitHub Desktop.
Example of component
import * as React from 'react'
import i18next from 'i18next'
import {CircularProgress, IconButton, Paper, Table, TableBody, TableCell, TableHead, TableRow} from '@material-ui/core'
import ViewRoleRow from './ViewRoleRow'
import EditingRoleRow from './EditingRoleRow'
import {injectAware, injectProperty} from '../../../../common/annotations/dependency-injection'
import {RoleService} from '../../../../services'
import {RoleMapper} from '../../../../mappers'
import Role from '../../../../models/role'
import {Action} from '../../../../models/action'
import {Maybe} from '../../../../common/types'
import {action, computed, observable, runInAction} from 'mobx'
import {observer} from 'mobx-react'
import {Add} from '@material-ui/icons'
import EditRoleWithFormik from './CreateRoleRow/CreateRoleWithFormik'
import {RouteProps} from 'react-router-dom'
const styles = require('./index.scss')
interface AdminSystemRolesModuleProps extends RouteProps{
handleUpdate: (dto: Role.UpdateDTO) => void
}
@injectAware()
@observer
export default class AdminSystemRolesModule extends React.Component<AdminSystemRolesModuleProps> {
@injectProperty('RoleService')
private roleService: RoleService
@injectProperty('RoleMapper')
private roleMapper: RoleMapper
@observable
private editingRole: Maybe<Role.BaseModel>
@observable
private creatingRole: boolean
@computed
get updateDTO() {
return this.editingRole && this.roleService.toUpdateDTO(this.editingRole)
}
get getRoles(): Role.BaseModel[] {
return !!this.roleMapper.allRoles ? this.roleMapper.allRoles : []
}
get allActions(): Action.BaseModel[] {
return !!this.roleMapper.allActions ? this.roleMapper.allActions : []
}
componentDidMount() {
this.roleService.getAllActions()
}
render() {
if (!this.allActions.length) {
return (
<CircularProgress size={40}/>
)
}
return (
<div className={styles['system-roles-wrap']}>
<Paper>
<Table>
<colgroup>
<col style={{width: '4%'}}/>
<col style={{width: '26%'}}/>
<col style={{width: '26%'}}/>
<col style={{width: '26%'}}/>
<col style={{width: '16%'}}/>
</colgroup>
<TableHead>
<TableRow>
<TableCell align='left'/>
<TableCell classes={{head: 'table_cell_head'}}
align="left">{i18next.t(`CASE:CASE_NAME`)}</TableCell>
<TableCell classes={{head: 'table_cell_head'}}
align="left">{i18next.t(`GENERALTERMS:DESCRIPTION`)}</TableCell>
<TableCell classes={{head: 'table_cell_head'}}
align="left">{i18next.t(`GENERALTERMS:PERMISSIONS`)}</TableCell>
<TableCell align='right'>
{!this.creatingRole &&
<IconButton onClick={this.handleOpenCreateRow}>
<Add/>
</IconButton>}
</TableCell>
</TableRow>
</TableHead>
<TableBody>
{this.creatingRole &&
<EditRoleWithFormik
allActions={this.allActions}
handleCancel={this.handleCancel}
handleCreate={this.handleCreate}
/>}
{this.getRoles!! && this.getRoles.map((role: Role.BaseModel) => (
!!this.editingRole && (role.id === this.editingRole.id) ? (
<EditingRoleRow
updateDTO={this.updateDTO}
selectedRole={this.editingRole}
allActions={this.allActions}
key={role.id}
handleSave={this.handleSave}
handleClearEditingRole={this.handleCancel}
/>
) : (
<ViewRoleRow
role={role}
key={role.id}
handleSelectEditingRole={this.handleSelectEditingRole(role)}
/>
)
))}
</TableBody>
</Table>
</Paper>
</div>
)
}
@action
private handleCancel = () => {
this.editingRole = null
this.creatingRole = false
}
@action
private handleOpenCreateRow = () => {
this.creatingRole = true
}
private handleSave = async (dto: Role.UpdateDTO) => {
await this.roleService.updateRole(dto)
this.roleService.getAllActions()
.then(() => {
runInAction(() => {
this.editingRole = null
})
})
}
private handleCreate = async (dto: Role.CreateDTO) => {
await this.roleService.createRole(dto)
await this.roleService.getAllActions()
runInAction(() => {
this.editingRole = null
this.creatingRole = false
})
}
private handleSelectEditingRole = (role: Role.BaseModel) => action(() => {
this.editingRole = role
})
}
import * as React from 'react'
import Role from '../../../../../models/role'
import {observer} from 'mobx-react'
import {Action} from '../../../../../models/action'
import {Formik, FormikProps} from 'formik'
import * as Yup from 'yup'
import CreateRole, {CreateRowProps} from './index'
import i18next from 'i18next'
interface CreateRoleRowProps {
handleCreate: (dto: Role.CreateDTO) => void
handleCancel: () => void
allActions: Action.BaseModel[]
}
@observer
class CreateRoleWithFormik extends React.Component<CreateRoleRowProps> {
private validationSchema = Yup.object({
name: Yup.string()
.required(`${i18next.t('GENERALTERMS:REQUIRED')} ${i18next.t('CASE:CASE_NAME')}`),
description: Yup.string()
.required(`${i18next.t('GENERALTERMS:REQUIRED')} ${i18next.t('GENERALTERMS:DESCRIPTION')}`),
selectedActions: Yup.array()
})
public render() {
const values = {
name: '',
allActions: this.props.allActions,
selectedActions: [],
description: ''
}
return (
<Formik
render={this.withFormikProps}
initialValues={values}
validationSchema={this.validationSchema}
onSubmit={this.handleSubmit}
/>
)
}
private handleSubmit = (res: CreateRowProps) => {
// TODO: Pass actual object here or use interface
this.props.handleCreate({name: res.name, description: res.description, actions: res.selectedActions})
}
private withFormikProps = (formikProps: FormikProps<CreateRowProps>) => {
return <CreateRole handleCancel={this.props.handleCancel} {...formikProps} />
}
}
export default CreateRoleWithFormik
@service('Role')
export default class DefaultRoleService extends BaseService implements RoleService {
private fetcher: Fetcher
constructor(@injectConstructor('RoleRecordStorage') private store: RoleRecordStorage) {
super()
}
@injectMethod('Fetcher')
setFetcher(fetch: Fetcher) {
this.fetcher = fetch
}
async getAllRoles(): Promise<void> {
const params = {
command: 'DOWNLOAD',
kind: 'ROLE'
}
const response = await this.fetcher.post<Role.ListResponse>(Pathes.Roles.getAll, params, Role.ListResponse)
if (!response || !response.valid) {
throw new Error('General-Error_Messages-Invalid_response')
} else {
this.store.set('allRoles', response.response.roles)
}
}
async createRole(dto: Role.CreateDTO): Promise<Common.EmptyResponse> {
const params = {
command: 'CREATE',
kind: 'ROLE',
name: dto.name,
description: dto.description,
permissions: dto.actions
}
const response = await this.fetcher.post<Common.EmptyResponse>(Pathes.Roles.create, params, Common.EmptyResponse)
if (!response || !response.valid) {
throw new Error('General-Error_Messages-Invalid_response')
}
return response
}
async updateRole(dto: Role.UpdateDTO): Promise<Common.EmptyResponse> {
const params = {
command: 'UPDATE',
kind: 'ROLE',
id: dto.id,
name: dto.name,
description: dto.description,
permissions: dto.actions.map((action) => action.id)
}
const response = await this.fetcher.post<Common.EmptyResponse>(Pathes.Roles.update, params, Common.EmptyResponse)
if (!response || !response.valid) {
throw new Error('General-Error_Messages-Invalid_response')
}
return response
}
toUpdateDTO(role: Role.BaseModel): Role.UpdateDTO {
return new Role.UpdateDTO(
role.id, role.name, role.description, role.actions)
}
async getAllActions(): Promise<Role.ResDTO> {
const params = {
command: 'DOWNLOAD',
kind: 'ACTION'
}
const response = await this.fetcher.post<Action.GetActionsResponse>(Pathes.Roles.getActions, params, Action.GetActionsResponse)
if (!response || !response.valid) {
throw new Error('General-Error_Messages-Invalid_response')
} else {
this.store.set('actions', response.response.actions)
}
}
}
import {observable} from 'mobx'
import {attr} from '../common/annotations/model'
import {Maybe} from '../common/types'
import {Action} from './action'
export namespace Role {
export class CreateDTO {
@observable
name: string
@observable
description: string
@observable
actions: number[] // Permissions generate actions array in BaseModel
}
export class UpdateDTO {
@observable
id: number
@observable
name: string
@observable
description: string
@observable
actions: Action.BaseModel[] // Permissions generate actions array in BaseModel
constructor(id: number, name: string = '', description: string = '', actions: Action.BaseModel[] = []) {
this.id = id
this.name = name
this.description = description
this.actions = actions
}
}
export class BaseModel {
@observable
@attr()
id: number
@observable
@attr()
name: string
@observable
@attr()
description: string
@observable
status: number
@observable
@attr({type: Action.BaseModel})
actions: Action.BaseModel[]
}
export class ListData {
@observable
@attr({type: BaseModel})
roles: BaseModel[]
}
export class ListResponse {
@observable
@attr()
valid: boolean
@observable
@attr({type: ListData})
response: ListData
@observable
@attr({type: String, nullable: true})
warnings: string[]
@observable
@attr()
status: number
}
export interface Records {
allRoles: Maybe<BaseModel[]>,
actions: Maybe<Action.BaseModel[]>
}
}
export default Role
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment