API & Client - add/remove user admin rights - #15
This commit is contained in:
@ -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}`))
|
||||
|
@ -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)
|
||||
|
@ -499,6 +499,10 @@ label {
|
||||
padding: 0.1em;
|
||||
}
|
||||
|
||||
.user-table {
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
/* calendar */
|
||||
:root {
|
||||
--main-color: #1a8fff;
|
||||
|
@ -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>
|
||||
|
@ -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',
|
||||
|
@ -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",
|
||||
|
@ -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",
|
||||
|
@ -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,
|
||||
|
Reference in New Issue
Block a user