API & Client - add/remove user admin rights - #15

This commit is contained in:
Sam
2020-05-01 12:12:48 +02:00
parent aa29231fd9
commit 7cc1b40f26
10 changed files with 320 additions and 27 deletions

View File

@ -28,6 +28,12 @@ export const updateSportsData = data => ({
type: 'UPDATE_SPORT_DATA',
data,
})
export const updateUsersData = data => ({
type: 'UPDATE_USER_DATA',
data,
})
export const getOrUpdateData = (
action,
target,
@ -47,6 +53,8 @@ export const getOrUpdateData = (
dispatch(setData(target, ret.data))
} else if (action === 'updateData' && target === 'sports') {
dispatch(updateSportsData(ret.data.sports[0]))
} else if (action === 'updateData' && target === 'users') {
dispatch(updateUsersData(ret.data.users[0]))
}
} else {
dispatch(setError(`${target}|${ret.message || ret.status}`))

View File

@ -15,7 +15,7 @@ class AdminUsers extends React.Component {
}
render() {
const { message, t, users } = this.props
const { message, t, updateUser, authUser, users } = this.props
return (
<div>
<Helmet>
@ -26,7 +26,7 @@ class AdminUsers extends React.Component {
<div className="row">
<div className="col card">
<div className="card-body">
<table className="table">
<table className="table user-table">
<thead>
<tr>
<th>#</th>
@ -35,6 +35,7 @@ class AdminUsers extends React.Component {
<th>{t('user:Registration Date')}</th>
<th>{t('activities:Activities')}</th>
<th>{t('user:Admin')}</th>
<th>{t('administration:Actions')}</th>
</tr>
</thead>
<tbody>
@ -79,6 +80,23 @@ class AdminUsers extends React.Component {
/>
)}
</td>
<td>
<input
type="submit"
className={`btn btn-${
user.admin ? 'dark' : 'primary'
} btn-sm`}
disabled={user.username === authUser.username}
value={
user.admin
? t('administration:Remove')
: t('administration:Add')
}
onClick={() =>
updateUser(user.username, !user.admin)
}
/>
</td>
</tr>
))}
</tbody>
@ -101,11 +119,16 @@ class AdminUsers extends React.Component {
export default connect(
state => ({
message: state.message,
authUser: state.user,
users: state.users.data,
}),
dispatch => ({
loadUsers: () => {
dispatch(getOrUpdateData('getData', 'users'))
},
updateUser: (userName, isAdmin) => {
const data = { username: userName, admin: isAdmin }
dispatch(getOrUpdateData('updateData', 'users', data, false))
},
})
)(AdminUsers)

View File

@ -499,6 +499,10 @@ label {
padding: 0.1em;
}
.user-table {
font-size: 0.9em;
}
/* calendar */
:root {
--main-color: #1a8fff;

View File

@ -94,27 +94,36 @@ function ProfileDetail({
}
className="img-fluid App-profile-img-small"
/>
<br />
<button type="submit" onClick={() => onDeletePicture()}>
{t('user:Delete picture')}
</button>
<br />
<br />
{editable && (
<>
<br />
<button
type="submit"
onClick={() => onDeletePicture()}
>
{t('user:Delete picture')}
</button>
<br />
<br />
</>
)}
</div>
)}
<form
encType="multipart/form-data"
onSubmit={event => onUploadPicture(event)}
>
<input
type="file"
name="picture"
accept=".png,.jpg,.gif"
/>
<br />
<button type="submit">{t('user:Send')}</button>
{` (max. size: ${fileSizeLimit})`}
</form>
{editable && (
<form
encType="multipart/form-data"
onSubmit={event => onUploadPicture(event)}
>
<input
type="file"
name="picture"
accept=".png,.jpg,.gif"
/>
<br />
<button type="submit">{t('user:Send')}</button>
{` (max. size: ${fileSizeLimit})`}
</form>
)}{' '}
</div>
</div>
</div>

View File

@ -48,7 +48,9 @@ export default class FitTrackeeApi {
static updateData(target, data) {
const params = {
url: `${target}${data.id ? `/${data.id}` : ''}`,
url: `${target}${
data.id ? `/${data.id}` : data.username ? `/${data.username}` : ''
}`,
method: 'PATCH',
body: data,
type: 'application/json',

View File

@ -2,6 +2,7 @@
"Actions": "Actions",
"Active": "Active",
"activities exist": "activities exist",
"Add": "Add",
"Administration": "Administration",
"Application": "Application",
"Application configuration": "Application configuration",
@ -18,6 +19,7 @@
"Max. size of uploaded files (in Mb)": "Max. size of uploaded files (in Mb)",
"Max. size of zip archive": "Max. size of zip archive",
"Max. size of zip archive (in Mb)": "Max. size of zip archive (in Mb)",
"Remove": "Remove",
"Sports": "Sports",
"user": "user",
"Users": "Users",

View File

@ -1,6 +1,7 @@
{
"Actions": "Actions",
"Active": "Active",
"Add": "Ajouter",
"Administration": "Administration",
"activities exist": "des activités existent",
"Application": "Application",
@ -18,6 +19,7 @@
"Max. size of uploaded files (in Mb)": "Taille max. des fichiers (en Mo)",
"Max. size of zip archive": "Taille max. des archives zip",
"Max. size of zip archive (in Mb)": "Taille max. des archives zip (en Mo)",
"Remove": "Retirer",
"Sports": "Sports",
"user": "user",
"Users": "Utilisateurs",

View File

@ -146,6 +146,21 @@ const sports = (state = initial.sports, action) => {
return handleDataAndError(state, 'sports', action)
}
const users = (state = initial.users, action) => {
if (action.type === 'UPDATE_USER_DATA') {
return {
...state,
data: state.data.map(user => {
if (user.username === action.data.username) {
user.admin = action.data.admin
}
return user
}),
}
}
return handleDataAndError(state, 'users', action)
}
const user = (state = initial.user, action) => {
switch (action.type) {
case 'AUTH_ERROR':
@ -167,9 +182,6 @@ const statistics = (state = initial.statistics, action) => {
return handleDataAndError(state, 'statistics', action)
}
const users = (state = initial.users, action) =>
handleDataAndError(state, 'users', action)
export default history =>
combineReducers({
activities,