Skip to content

Commit

Permalink
feat: edit role permission mapping
Browse files Browse the repository at this point in the history
  • Loading branch information
mjatin-dev committed Feb 18, 2022
1 parent 4fc332e commit b905d11
Show file tree
Hide file tree
Showing 9 changed files with 335 additions and 57 deletions.
2 changes: 2 additions & 0 deletions admin-ui/app/routes/Apps/Gluu/GluuTypeAhead.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ function GluuTypeAhead({
required,
doc_category,
doc_entry,
forwardRef = null,
}) {
const { t } = useTranslation()
return (
Expand All @@ -37,6 +38,7 @@ function GluuTypeAhead({
<Col sm={8}>
<Typeahead
allowNew
ref={forwardRef}
emptyLabel=""
labelKey={name}
onChange={(selected) => {
Expand Down
158 changes: 145 additions & 13 deletions admin-ui/plugins/admin/components/Mapping/MappingItem.js
Original file line number Diff line number Diff line change
@@ -1,55 +1,187 @@
import React, { useState } from 'react'
import React, { useEffect, useState, useRef } from 'react'
import {
Row,
Badge,
Col,
Button,
FormGroup,
Accordion,
Form,
} from '../../../../app/components'
import { useDispatch, useSelector } from 'react-redux'
import {
updateMapping,
addPermissionsToRole,
updatePermissionsToServer,
updatePermissionsServerResponse,
} from '../../redux/actions/MappingActions'
import GluuTypeAhead from '../../../../app/routes/Apps/Gluu/GluuTypeAhead'
import applicationStyle from '../../../../app/routes/Apps/Gluu/styles/applicationstyle'

import { Formik } from 'formik'

function MappingItem({ candidate }) {
const dispatch = useDispatch()
const autocompleteRef = useRef(null)
const permissions = useSelector((state) => state.apiPermissionReducer.items)
const [searchablePermissions, setSearchAblePermissions] = useState([])
const [serverPermissions, setServerPermissions] = useState(null)
const getPermissionsForSearch = () => {
const selectedPermissions = candidate.permissions
let filteredArr = []
for (let i in permissions) {
if (!selectedPermissions.includes(permissions[i].permission)) {
filteredArr.push(permissions[i].permission)
}
}
setSearchAblePermissions(filteredArr)
}

function MappingItem({ candidate, key }) {
const [item, setItem] = useState(candidate || {})
function doRemove(perm) {
const candidate = item
candidate['permissions'] = ['one', 'two']
setItem(candidate)
const revertLocalChanges = () => {
dispatch(updatePermissionsServerResponse(JSON.parse(serverPermissions)))
}

const setServerPermissionsToLocalState = () => {
setServerPermissions(JSON.stringify(candidate))
}

useEffect(() => {
setServerPermissionsToLocalState()
}, [false])

useEffect(() => {
getPermissionsForSearch()
}, [permissions, candidate?.permissions?.length])

const doRemove = (id, role) => {
dispatch(
updateMapping({
id,
role,
}),
)
}

const initialValues = {}

const handleAddPermission = (values, { resetForm }) => {
if (values?.mappingAddPermissions?.length) {
dispatch(
addPermissionsToRole({
data: values?.mappingAddPermissions,
userRole: candidate.role,
}),
)
}
resetForm()
autocompleteRef.current.clear()
}

return (
<div key={key}>
<div>
<FormGroup row />
<Row>
<Col sm={12}>
<Accordion className="mb-12">
<Accordion.Header className="text-info">
<Accordion.Indicator className="mr-2" />
{item.role}
{candidate.role}
<Badge
color="info"
style={{
float: 'right',
}}
>
{item.permissions.length}
{candidate.permissions.length}
</Badge>
</Accordion.Header>
<Accordion.Body>
{item.permissions.map((permission, id) => (
<div style={{ marginTop: 10 }}></div>
<Formik
initialValues={initialValues}
onSubmit={handleAddPermission}
>
{(formik) => (
<>
<Form onSubmit={formik.handleSubmit}>
<Row>
<Col sm={10}>
<GluuTypeAhead
name="mappingAddPermissions"
label="Search"
formik={formik}
options={searchablePermissions}
required={false}
value={[]}
forwardRef={autocompleteRef}
doc_category={'Mapping'}
></GluuTypeAhead>
</Col>
<Col>
<Button
type="submit"
color="primary"
style={applicationStyle.buttonStyle}
>
<i className="fa fa-plus mr-2"></i>
Add
</Button>
</Col>
</Row>
</Form>
</>
)}
</Formik>
{candidate.permissions.map((permission, id) => (
<Row key={id}>
<Col sm={10}>{permission}</Col>
<Col sm={2}>
<Button
type="button"
color="danger"
onClick={() => doRemove(permission)}
style={{ margin: '1px', float: 'right', padding: '0px' }}
onClick={() => doRemove(id, candidate.role)}
style={{
margin: '1px',
float: 'right',
padding: '0px',
}}
>
<i className="fa fa-trash mr-2"></i>
Remove
</Button>
</Col>
</Row>
))}
{/* Bottom Buttons */}
<FormGroup row />
<Row>
<Col sm={6}>
<Button
type="button"
color="primary"
style={applicationStyle.buttonStyle}
onClick={() => revertLocalChanges()}
>
<i className="fa fa-undo mr-2"></i>
Revert
</Button>
</Col>
<Col sm={6} className="text-right">
<Button
type="button"
color="primary"
style={applicationStyle.buttonStyle}
onClick={() => {
dispatch(updatePermissionsToServer(candidate))
setServerPermissionsToLocalState()
}}
>
<i className="fa fa-plus mr-2"></i>
Save
</Button>
</Col>
</Row>
{/* Bottom Buttons */}
</Accordion.Body>
</Accordion>
</Col>
Expand Down
87 changes: 54 additions & 33 deletions admin-ui/plugins/admin/components/Mapping/MappingPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,40 @@ import {
} from '../../../../app/components'
import GluuViewWrapper from '../../../../app/routes/Apps/Gluu/GluuViewWrapper'
import GluuRibbon from '../../../../app/routes/Apps/Gluu/GluuRibbon'
import GluuLoader from '../../../../app/routes/Apps/Gluu/GluuLoader'
import { getMapping } from '../../redux/actions/MappingActions'
import { getRoles } from '../../redux/actions/ApiRoleActions'
import { getPermissions } from '../../redux/actions/ApiPermissionActions'
import MappingItem from './MappingItem'
import {
hasPermission,
buildPayload,
ROLE_READ,
} from '../../../../app/utils/PermChecker'

function MappingPage({ mapping, apiRoles, permissions, dispatch }) {
function MappingPage({
mapping,
apiRoles,
permissions,
permissionLoading,
loading,
dispatch,
}) {
const { t } = useTranslation()
const [modal, setModal] = useState(false)
const toggle = () => setModal(!modal)
const options = []
const userAction = {}

function doFetchPermissionsList() {
buildPayload(userAction, 'PERMISSIONS', options)
dispatch(getPermissions(userAction))
}

useEffect(() => {
doFetchList()
doFetchRoles()
doFetchPermissionsList()
}, [])

function onAddConfirmed(mappingData) {
Expand All @@ -51,46 +67,51 @@ function MappingPage({ mapping, apiRoles, permissions, dispatch }) {
toggle()
}
return (
<Card>
<GluuRibbon title={t('titles.mapping')} fromLeft />
<CardBody>
<FormGroup row />
<FormGroup row />
<GluuViewWrapper canShow={hasPermission(permissions, ROLE_READ)}>
<FormGroup row>
<Col sm={10}></Col>
<Col sm={2}>
<Button
type="button"
color="primary"
style={applicationStyle.buttonStyle}
onClick={showMappingDialog}
>
<i className="fa fa-plus mr-2"></i>
Add Mapping
</Button>
</Col>
</FormGroup>
{mapping.map((candidate, idx) => (
<MappingItem key={idx} candidate={candidate} />
))}
</GluuViewWrapper>
<MappingAddDialogForm
roles={apiRoles}
handler={toggle}
modal={modal}
onAccept={onAddConfirmed}
/>
</CardBody>
</Card>
<GluuLoader blocking={loading || permissionLoading}>
<Card>
<GluuRibbon title={t('titles.mapping')} fromLeft />
<CardBody>
<FormGroup row />
<FormGroup row />
<GluuViewWrapper canShow={hasPermission(permissions, ROLE_READ)}>
<FormGroup row>
<Col sm={10}></Col>
<Col sm={2}>
<Button
type="button"
color="primary"
style={applicationStyle.buttonStyle}
onClick={showMappingDialog}
>
<i className="fa fa-plus mr-2"></i>
Add Mapping
</Button>
</Col>
</FormGroup>
{mapping.map((candidate, idx) => (
<MappingItem key={idx} candidate={candidate} />
))}
</GluuViewWrapper>
<FormGroup row />
<MappingAddDialogForm
roles={apiRoles}
handler={toggle}
modal={modal}
onAccept={onAddConfirmed}
/>
</CardBody>
</Card>
</GluuLoader>
)
}

const mapStateToProps = (state) => {
return {
mapping: state.mappingReducer.items,
loading: state.mappingReducer.loading,
apiRoles: state.apiRoleReducer.items,
permissions: state.authReducer.permissions,
permissionLoading: state.apiPermissionReducer.loading,
}
}

Expand Down
34 changes: 33 additions & 1 deletion admin-ui/plugins/admin/redux/actions/MappingActions.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
import { GET_MAPPING, GET_MAPPING_RESPONSE } from './types'
import {
GET_MAPPING,
GET_MAPPING_RESPONSE,
UPDATE_MAPPING,
ADD_PERMISSIONS_TO_ROLE,
UPDATE_PERMISSIONS_TO_SERVER,
UPDATE_PERMISSIONS_LOADING,
UPDATE_PERMISSIONS_SERVER_RESPONSE,
} from './types'

export const getMapping = (action) => ({
type: GET_MAPPING,
Expand All @@ -9,3 +17,27 @@ export const getMappingResponse = (data) => ({
type: GET_MAPPING_RESPONSE,
payload: { data },
})

export const updateMapping = (data) => ({
type: UPDATE_MAPPING,
payload: { data },
})

export const updatePermissionsLoading = (data) => ({
type: UPDATE_PERMISSIONS_LOADING,
payload: { data },
})

export const updatePermissionsServerResponse = (data) => ({
type: UPDATE_PERMISSIONS_SERVER_RESPONSE,
payload: { data },
})
export const addPermissionsToRole = (data) => ({
type: ADD_PERMISSIONS_TO_ROLE,
payload: { data },
})

export const updatePermissionsToServer = (data) => ({
type: UPDATE_PERMISSIONS_TO_SERVER,
payload: { data },
})
7 changes: 6 additions & 1 deletion admin-ui/plugins/admin/redux/actions/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,12 @@ export const SET_PERMISSION_ITEM = 'SET_PERMISSION_ITEM'
//ROLE-PERMISSION Mapping
export const GET_MAPPING = 'GET_MAPPING'
export const GET_MAPPING_RESPONSE = 'GET_MAPPING_RESPONSE'

export const UPDATE_MAPPING = 'UPDATE_MAPPING'
export const ADD_PERMISSIONS_TO_ROLE = 'ADD_PERMISSIONS_TO_ROLE'
export const UPDATE_PERMISSIONS_TO_SERVER = 'UPDATE_PERMISSIONS_TO_SERVER'
export const UPDATE_PERMISSIONS_SERVER_RESPONSE =
'UPDATE_PERMISSIONS_SERVER_RESPONSE'
export const UPDATE_PERMISSIONS_LOADING = 'UPDATE_PERMISSIONS_LOADING'
//License Details

export const GET_LICENSE_DETAILS = 'GET_LICENSE_DETAILS'
Expand Down
Loading

0 comments on commit b905d11

Please sign in to comment.