Skip to content
This repository has been archived by the owner on May 16, 2023. It is now read-only.

Commit

Permalink
Feat/user mgnt (#200)
Browse files Browse the repository at this point in the history
* user mgnt without api

* confirm dialogs

* validation

* api enabled - no subgroups

* ui fixes

* fix user edit after goup delete

* sub groups handling

* fix user create

* fix label parent group
  • Loading branch information
a-trzewik authored Jul 27, 2021
1 parent b9350c3 commit c8ebcc1
Show file tree
Hide file tree
Showing 16 changed files with 1,106 additions and 9 deletions.
157 changes: 157 additions & 0 deletions src/api.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import StatisticData from './misc/statistic-data';
import ITestResult from './misc/test-result';
import IQTArchiv from './misc/qt-archiv';
import { Sex, TestResult } from './misc/enum';
import { IUser, IGroupDetails } from './misc/user';

export const api = axios.create({
baseURL: ''
Expand Down Expand Up @@ -502,3 +503,159 @@ export const useGetPDF = (hash: string | undefined, onSuccess?: (status: number)

return result;
}

export const useGetUsers = (onError?: (error: any) => void) => {
const { keycloak, initialized } = useKeycloak();
const [result, setResult] = React.useState<any>();

const refreshUsers = () => {
const header = {
"Authorization": initialized ? `Bearer ${keycloak.token}` : "",
'Content-Type': 'application/json'
};
const uri = '/api/usermanagement/users';

api.get(uri, { headers: header })
.then(response => {
setResult(response.data);
})
.catch(error => {
if (onError) {
onError(error);
}
});
}

React.useEffect(refreshUsers, []);

return [result, refreshUsers];
}

export const createUser = (user: IUser, token: string) => {
const header = {
"Authorization": `Bearer ${token}`,
'Content-Type': 'application/json'
};
const uri = '/api/usermanagement/users';
return api.post(uri, JSON.stringify(user), { headers: header })
}

export const deleteUser = (userId: string, token: string) => {
const header = {
"Authorization": `Bearer ${token}`,
'Content-Type': 'application/json'
};
const uri = '/api/usermanagement/users/'+userId;
return api.delete(uri, { headers: header })
}

export const updateUser = (user: IUser, token: string) => {
const header = {
"Authorization": `Bearer ${token}`,
'Content-Type': 'application/json'
};
const uri = '/api/usermanagement/users/'+user.id;
return api.patch(uri, JSON.stringify(user), { headers: header })
}

export const useGetGroups = (onError?: (error: any) => void) => {
const { keycloak, initialized } = useKeycloak();
const [result, setResult] = React.useState<any>();

const refreshGroups = () => {
const header = {
"Authorization": initialized ? `Bearer ${keycloak.token}` : "",
'Content-Type': 'application/json'
};
const uri = '/api/usermanagement/groups';

api.get(uri, { headers: header })
.then(response => {
setResult(response.data);
})
.catch(error => {
if (onError) {
onError(error);
}
});
}

React.useEffect(refreshGroups, []);

return [result, refreshGroups];
}

export const useGetGroupDetails = (groupReloaded: (group: IGroupDetails) => void, onError?: (error: any) => void) => {
const { keycloak, initialized } = useKeycloak();
const [result, setResult] = React.useState<any>();

const updateGroup = (groupId: string) => {
if (groupId) {
const header = {
"Authorization": initialized ? `Bearer ${keycloak.token}` : "",
'Content-Type': 'application/json'
};
const uri = '/api/usermanagement/groups/' + groupId;

api.get(uri, { headers: header })
.then(response => {
const group = response.data
groupReloaded(group);
setResult(group);
})
.catch(error => {
if (onError) {
onError(error);
}
});
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}

return [result, updateGroup, setResult];
}

export const createGroup = (group: IGroupDetails, token: string) => {
const header = {
"Authorization": `Bearer ${token}`,
'Content-Type': 'application/json'
};
const uri = '/api/usermanagement/groups';
return api.post(uri, JSON.stringify(group), { headers: header })
}

export const updateGroup = (group: IGroupDetails, token: string) => {
const header = {
"Authorization": `Bearer ${token}`,
'Content-Type': 'application/json'
};
const uri = '/api/usermanagement/groups/'+group.id;
return api.put(uri, JSON.stringify(group), { headers: header })
}

export const deleteGroup = (groupId: string, token: string) => {
const header = {
"Authorization": `Bearer ${token}`,
'Content-Type': 'application/json'
};
const uri = '/api/usermanagement/groups/'+groupId;
return api.delete(uri, { headers: header })
}

export const addUserToGroup = (userId: string ,groupId: string, token: string) => {
const header = {
"Authorization": `Bearer ${token}`,
'Content-Type': 'application/json'
};
const uri = '/api/usermanagement/groups/'+groupId+'/users';
return api.post(uri,JSON.stringify({userId: userId}), { headers: header })
}

export const addGroupAsChild = (childGroupId: string, parentGroupId: string, token: string) => {
const header = {
"Authorization": `Bearer ${token}`,
'Content-Type': 'application/json'
};
const uri = '/api/usermanagement/groups/'+parentGroupId+'/subgroups';
return api.post(uri,JSON.stringify({groupId: childGroupId}), { headers: header })
}
3 changes: 3 additions & 0 deletions src/assets/SCSS/custom.scss
Original file line number Diff line number Diff line change
Expand Up @@ -369,4 +369,7 @@ hr {
position: absolute;
left: 30px;
top: 6px;
}
.btn-icon {
padding: 0px;
}
4 changes: 3 additions & 1 deletion src/assets/i18n/de/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,5 +79,7 @@
"testId-input-header": "Eingabe Proben-ID",
"error-processId-data-load": "Die eingegebene Proben-ID ist uns nicht bekannt!",
"ok":"OK",
"change-password":"Passwort ändern"
"change-password":"Passwort ändern",
"dccConsent":"Patient wünscht ein offizielles COVID-Testzertifikat der EU (DCC).",
"user-management":"Benutzerverwaltung"
}
3 changes: 2 additions & 1 deletion src/assets/i18n/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,5 +76,6 @@
"testId-input-header": "Process number input",
"error-processId-data-load": "The entered sample ID is not known!",
"ok":"OK",
"change-password":"Change Password"
"change-password":"Change Password",
"user-management":"User Management"
}
8 changes: 8 additions & 0 deletions src/assets/images/icon_add.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions src/assets/images/icon_delete.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions src/assets/images/icon_edit.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
73 changes: 73 additions & 0 deletions src/components/confirm-modal.component.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* Corona-Warn-App / cwa-quick-test-frontend
*
* (C) 2021, T-Systems International GmbH
*
* Deutsche Telekom AG and all other contributors /
* copyright owners license this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this
* file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import React from 'react';
import { Button, Col, Container, Modal, Row } from 'react-bootstrap'

import '../i18n';
import { useTranslation } from 'react-i18next';

const ConfirmModal = (props: any) => {
const { t } = useTranslation();

return (
<Modal
contentClassName='data-modal'
show={props.show}
backdrop="static"
keyboard={false}
centered
>
<Modal.Header id='data-header' className='pb-0' >
</Modal.Header>
<Modal.Body className='py-0 bg-light'>
{props.message}
</Modal.Body>
<Modal.Footer id='data-footer'>
<Container className='p-0'>
<Row>
<Col xs='6' md='4' className='pl-0'>
<Button
className='py-0'
block
variant='outline-primary'
onClick={props.onCancel}
>
{t('translation:cancel')}
</Button>
</Col>
<Col xs='6' md='4' className='pr-0'>
<Button
className='py-0'
block
onClick={props.handleOk}
>
{t('translation:ok')}
</Button>
</Col>
</Row>
</Container>
</Modal.Footer>
</Modal>
)
}

export default ConfirmModal;
Loading

0 comments on commit c8ebcc1

Please sign in to comment.