Skip to content

Commit

Permalink
feat(admin-ui): implement server side search
Browse files Browse the repository at this point in the history
  • Loading branch information
mjatin-dev committed Oct 14, 2022
1 parent 6fc72c4 commit 8344c17
Show file tree
Hide file tree
Showing 13 changed files with 179 additions and 21 deletions.
14 changes: 14 additions & 0 deletions admin-ui/app/redux/actions/AttributesActions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import {
GET_ATTRIBUTES_FOR_USER_MANAGEMENT,
GET_ATTRIBUTES_FOR_USER_MANAGEMENT_RESPONSE
} from './types'

export const getAttributesRoot = (options) => ({
type: GET_ATTRIBUTES_FOR_USER_MANAGEMENT,
payload: { options },
})

export const getAttributesResponseRoot = (data) => ({
type: GET_ATTRIBUTES_FOR_USER_MANAGEMENT_RESPONSE,
payload: { data },
})
1 change: 1 addition & 0 deletions admin-ui/app/redux/actions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ export * from './AuthActions'
export * from './InitActions'
export * from './LicenseActions'
export * from './OidcDiscoveryActions'
export * from './AttributesActions'
2 changes: 2 additions & 0 deletions admin-ui/app/redux/actions/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ export const GET_SCOPES_FOR_STAT_RESPONSE = 'GET_SCOPES_FOR_STAT_RESPONSE'
export const GET_ATTRIBUTES_FOR_STAT = 'GET_ATTRIBUTES_FOR_STAT'
export const GET_ATTRIBUTES_FOR_STAT_RESPONSE =
'GET_ATTRIBUTES_FOR_STAT_RESPONSE'
export const GET_ATTRIBUTES_FOR_USER_MANAGEMENT = "GET_ATTRIBUTES_FOR_USER_MANAGEMENT"
export const GET_ATTRIBUTES_FOR_USER_MANAGEMENT_RESPONSE = "GET_ATTRIBUTES_FOR_USER_MANAGEMENT_RESPONSE"
export const GET_CLIENTS_FOR_STAT = 'GET_CLIENTS_FOR_STAT'
export const GET_CLIENTS_FOR_STAT_RESPONSE = 'GET_CLIENTS_FOR_STAT_RESPONSE'

Expand Down
16 changes: 16 additions & 0 deletions admin-ui/app/redux/api/AttributeApi.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { handleResponse } from 'Utils/ApiUtils'

export default class AttributeApi {
constructor(api) {
this.api = api
}

// Get all attributes
getAllAttributes = (opts) => {
return new Promise((resolve, reject) => {
this.api.getAttributes(opts, (error, data) => {
handleResponse(error, reject, resolve, data)
})
})
}
}
39 changes: 39 additions & 0 deletions admin-ui/app/redux/reducers/AttributesReducer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { GET_ATTRIBUTES_FOR_USER_MANAGEMENT, GET_ATTRIBUTES_FOR_USER_MANAGEMENT_RESPONSE } from '../actions/types'
import _ from 'lodash'
import reducerRegistry from './ReducerRegistry'
const INIT_STATE = {
items:[],
loading: false,
}

const reducerName = 'attributesReducerRoot'

export default function attributesReducerRoot(state = INIT_STATE, action) {
switch (action.type) {
case GET_ATTRIBUTES_FOR_USER_MANAGEMENT:
return {
...state,
loading: true,
}
case GET_ATTRIBUTES_FOR_USER_MANAGEMENT_RESPONSE:
if (action.payload.data) {
return {
...state,
loading: false,
items: _.unionBy(action.payload.data.entries, state.items, 'displayName'),
}
} else {
return handleDefault()
}
default:
return handleDefault()
}

function handleDefault() {
return {
...state,
loading: false,
}
}
}
reducerRegistry.register(reducerName, attributesReducerRoot)
2 changes: 2 additions & 0 deletions admin-ui/app/redux/reducers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import logoutReducer from './LogoutReducer'
import licenseReducer from './LicenseReducer'
import licenseDetailsReducer from './LicenseDetailsReducer'
import oidcDiscoveryReducer from './OidcDiscoveryReducer'
import attributesReducerRoot from './AttributesReducer'
const appReducers = {
authReducer,
fidoReducer,
Expand All @@ -20,6 +21,7 @@ const appReducers = {
mauReducer,
healthReducer,
licenseDetailsReducer,
attributesReducerRoot
}

export default appReducers
57 changes: 57 additions & 0 deletions admin-ui/app/redux/sagas/AttributesSaga.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { call, all, put, fork, takeLatest, select } from 'redux-saga/effects'
import { isFourZeroOneError, addAdditionalData } from 'Utils/TokenController'
import {
getAttributesResponseRoot
} from '../actions/AttributesActions'
import { getAPIAccessToken } from 'Redux/actions/AuthActions'
import { postUserAction } from 'Redux/api/backend-api'
import {
GET_ATTRIBUTES_FOR_USER_MANAGEMENT,
} from '../actions/types'
import {
FETCH,
} from '../../audit/UserActionType'
// } from '../../../../app/audit/UserActionType'
import AttributeApi from '../api/AttributeApi'
import { getClient } from 'Redux/api/base'
import { initAudit } from 'Redux/sagas/SagaUtils'

const PERSON_SCHEMA = 'person schema'

const JansConfigApi = require('jans_config_api')

function* newFunction() {
const token = yield select((state) => state.authReducer.token.access_token)
const issuer = yield select((state) => state.authReducer.issuer)
const api = new JansConfigApi.AttributeApi(
getClient(JansConfigApi, token, issuer),
)
return new AttributeApi(api)
}

export function* getAttributesRoot({ payload }) {
const audit = yield* initAudit()
try {
addAdditionalData(audit, FETCH, PERSON_SCHEMA, payload)
const attributeApi = yield* newFunction()
const data = yield call(attributeApi.getAllAttributes, payload.options)
yield put(getAttributesResponseRoot(data))
yield call(postUserAction, audit)
} catch (e) {
yield put(getAttributesResponseRoot([]))
if (isFourZeroOneError(e)) {
const jwt = yield select((state) => state.authReducer.userinfo_jwt)
yield put(getAPIAccessToken(jwt))
}
}
}

export function* watchGetAttributesRoot() {
yield takeLatest(GET_ATTRIBUTES_FOR_USER_MANAGEMENT, getAttributesRoot)
}

export default function* rootSaga() {
yield all([
fork(watchGetAttributesRoot),
])
}
3 changes: 2 additions & 1 deletion admin-ui/app/redux/sagas/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import licenseSaga from './LicenseSaga'
import licenseDetailsSaga from './LicenseDetailsSaga'
import oidcDiscoverySaga from './OidcDiscoverySaga'
import process from 'Plugins/PluginSagasResolver'

import attributes from './AttributesSaga'
export default function* rootSaga() {
const pluginSagaArr = process()
yield all(
Expand All @@ -27,6 +27,7 @@ export default function* rootSaga() {
mauSaga(),
healthSaga(),
licenseDetailsSaga(),
attributes()
],
pluginSagaArr,
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ function UserAddPage() {
(state) => state.userReducer.redirectToUserListPage,
)
const { t } = useTranslation()
const personAttributes = useSelector((state) => state.attributeReducer.items)
const personAttributes = useSelector((state) => state.attributesReducerRoot.items)
const createCustomAttributes = (values) => {
let customAttributes = []
if (values) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import moment from 'moment'
const UserDetailViewPage = ({ row }) => {
const { rowData } = row
const DOC_SECTION = 'user'
const personAttributes = useSelector((state) => state.attributeReducer.items)

const personAttributes = useSelector((state) => state.attributesReducerRoot.items)
const getCustomAttributeById = (id) => {
let claimData = null
for (let i in personAttributes) {
Expand Down Expand Up @@ -61,16 +61,17 @@ const UserDetailViewPage = ({ row }) => {
} else {
valueToShow = data?.values[0]
}
return (
<Col sm={4} key={'customAttributes' + key}>
<GluuFormDetailRow
label={getCustomAttributeById(data.name).displayName}
doc_category={getCustomAttributeById(data.name).description}
isDirect={true}
value={valueToShow}
/>
</Col>
)
return (
<Col sm={4} key={'customAttributes' + key}>
<GluuFormDetailRow
label={getCustomAttributeById(data.name) ? getCustomAttributeById(data.name).displayName : ''}
doc_category={getCustomAttributeById(data.name) ? getCustomAttributeById(data.name).description : ''}
isDirect={true}
value={valueToShow}
/>
</Col>
)

})}
</Row>
</Container>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ function UserEditPage() {
const navigate =useNavigate()
const { t } = useTranslation()
const userDetails = useSelector((state) => state.userReducer.selectedUserData)
const personAttributes = useSelector((state) => state.attributeReducer.items)
const personAttributes = useSelector((state) => state.attributesReducerRoot.items)
const redirectToUserListPage = useSelector(
(state) => state.userReducer.redirectToUserListPage,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import GluuCommitDialog from '../../../../app/routes/Apps/Gluu/GluuCommitDialog'
import { Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap'
import { changeUserPassword } from '../../redux/actions/UserActions'
import { ThemeContext } from 'Context/theme/themeContext'
import { getAttributesRoot } from '../../../../app/redux/actions'

function UserForm({ formik }) {
const dispatch = useDispatch()
Expand All @@ -23,11 +24,20 @@ function UserForm({ formik }) {
const [changePasswordModal, setChangePasswordModal] = useState(false)
const theme = useContext(ThemeContext)
const selectedTheme = theme.state.theme

let options = {}
const toggle = () => {
setModal(!modal)
}

useEffect(() => {
const delayDebounceFn = setTimeout(() => {
options['pattern'] = searchClaims;
dispatch(getAttributesRoot(options))
}, 500)

return () => clearTimeout(delayDebounceFn)
},[searchClaims])

const submitChangePassword = () => {
const submitableValue = {
inum: userDetails.inum,
Expand All @@ -50,7 +60,7 @@ function UserForm({ formik }) {
}

const userDetails = useSelector((state) => state.userReducer.selectedUserData)
const personAttributes = useSelector((state) => state.attributeReducer.items)
const personAttributes = useSelector((state) => state.attributesReducerRoot.items)
const loading = useSelector((state) => state.userReducer.loading)
const setSelectedClaimsToState = (data) => {
const tempList = [...selectedClaims]
Expand Down Expand Up @@ -373,7 +383,7 @@ function UserForm({ formik }) {
/>
<ul className="list-group">
{personAttributes.map((data, key) => {
const name = data.name.toLowerCase()
const name = data.displayName.toLowerCase()
const alreadyAddedClaim = selectedClaims.some(
(el) => el.name === data.name,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
deleteUser,
} from '../../redux/actions/UserActions'

import { getAttributes } from '../../../schema/redux/actions/AttributeActions'
import { getAttributesRoot } from '../../../../app/redux/actions/AttributesActions'
import { useDispatch, useSelector } from 'react-redux'
import { Card, CardBody } from '../../../../app/components'
import { useTranslation } from 'react-i18next'
Expand All @@ -35,9 +35,9 @@ function UserList(props) {
const dispatch = useDispatch()
const opt = {}
useEffect(() => {
opt['limit'] = 100
opt['limit'] = 10
dispatch(getUsers({}))
dispatch(getAttributes(opt))
dispatch(getAttributesRoot(opt))
dispatch(getRoles())
}, [])
const { totalItems, entriesCount } = useSelector(
Expand Down Expand Up @@ -177,6 +177,21 @@ function UserList(props) {
dispatch(getUsers(options))
}

useEffect(() => {
let usedAttributes = [];
for(let i in usersList){
for(let j in usersList[i].customAttributes){
let val = usersList[i].customAttributes[j].name
if(!usedAttributes.includes(val)){
usedAttributes.push(val);
}
}
}
if(usedAttributes.length){
dispatch(getAttributesRoot({pattern:usedAttributes.toString(), limit:100}))
}
},[usersList])

return (
<GluuLoader blocking={loading}>
<Card style={applicationStyle.mainCard}>
Expand Down

0 comments on commit 8344c17

Please sign in to comment.