mirror of
https://github.com/ToolJet/ToolJet
synced 2026-05-06 06:48:21 +00:00
[Feature] :: Allow users to be filtered via status (#4908)
* add: user filter via status * fix: typo in options name * refactor: add All options to status filters
This commit is contained in:
parent
c5d03f904c
commit
e50fa984ee
4 changed files with 43 additions and 11 deletions
|
|
@ -1,15 +1,28 @@
|
|||
import React from 'react';
|
||||
import Select from '@/_ui/Select';
|
||||
|
||||
const userStatusOptions = [
|
||||
{ name: 'All', value: '' },
|
||||
{ name: 'Active', value: 'active' },
|
||||
{ name: 'Invited', value: 'invited' },
|
||||
{ name: 'Archived', value: 'archived' },
|
||||
];
|
||||
|
||||
const UsersFilter = ({ filterList, darkMode, clearIconPressed }) => {
|
||||
const [options, setOptions] = React.useState({ email: '', firstName: '', lastName: '' });
|
||||
const [options, setOptions] = React.useState({ email: '', firstName: '', lastName: '', status: '' });
|
||||
|
||||
const valuesChanged = (event) => {
|
||||
const newOptions = { ...options, [event.target.name]: event.target.value };
|
||||
const valuesChanged = (event, key) => {
|
||||
let newOptions = {};
|
||||
if (!key) {
|
||||
newOptions = { ...options, [event.target.name]: event.target.value };
|
||||
} else {
|
||||
newOptions = { ...options, [key]: event };
|
||||
}
|
||||
setOptions(newOptions);
|
||||
};
|
||||
|
||||
const clearTextAndResult = () => {
|
||||
setOptions({ email: '', firstName: '', lastName: '' });
|
||||
setOptions({ email: '', firstName: '', lastName: '', status: '' });
|
||||
clearIconPressed();
|
||||
};
|
||||
|
||||
|
|
@ -32,7 +45,7 @@ const UsersFilter = ({ filterList, darkMode, clearIconPressed }) => {
|
|||
data-cy="email-filter-input-field"
|
||||
/>
|
||||
</div>
|
||||
<div className="col-3">
|
||||
<div className="col-2">
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
|
|
@ -44,7 +57,7 @@ const UsersFilter = ({ filterList, darkMode, clearIconPressed }) => {
|
|||
data-cy="first-name-filter-input-field"
|
||||
/>
|
||||
</div>
|
||||
<div className="col-3">
|
||||
<div className="col-2">
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
|
|
@ -56,7 +69,17 @@ const UsersFilter = ({ filterList, darkMode, clearIconPressed }) => {
|
|||
data-cy="last-name-filter-input-field"
|
||||
/>
|
||||
</div>
|
||||
<div className="col-3 d-flex gap-3">
|
||||
<div className="col-2">
|
||||
<Select
|
||||
options={userStatusOptions}
|
||||
value={options.status}
|
||||
onChange={(value) => valuesChanged(value, 'status')}
|
||||
width={'100%'}
|
||||
height="36px"
|
||||
useMenuPortal={true}
|
||||
/>
|
||||
</div>
|
||||
<div className="col-2 d-flex gap-3">
|
||||
<button type="submit" className="btn btn-primary" onClick={() => filterList(options)} data-cy="filter-button">
|
||||
Filter
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -15,8 +15,8 @@ export const organizationService = {
|
|||
|
||||
function getUsers(page, options) {
|
||||
const requestOptions = { method: 'GET', headers: authHeader() };
|
||||
const { firstName, lastName, email } = options;
|
||||
const query = queryString.stringify({ page, firstName, lastName, email });
|
||||
const { firstName, lastName, email, status } = options;
|
||||
const query = queryString.stringify({ page, firstName, lastName, email, status });
|
||||
|
||||
return fetch(`${config.apiUrl}/organizations/users?${query}`, requestOptions).then(handleResponse);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,11 +24,12 @@ export class OrganizationsController {
|
|||
@CheckPolicies((ability: AppAbility) => ability.can('viewAllUsers', UserEntity))
|
||||
@Get('users')
|
||||
async getUsers(@User() user, @Query() query) {
|
||||
const { page, email, firstName, lastName } = query;
|
||||
const { page, email, firstName, lastName, status } = query;
|
||||
const filterOptions = {
|
||||
...(email && { email }),
|
||||
...(firstName && { firstName }),
|
||||
...(lastName && { lastName }),
|
||||
...(status && { status }),
|
||||
};
|
||||
const usersCount = await this.organizationsService.usersCount(user, filterOptions);
|
||||
let users = [];
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ type FetchUserResponse = {
|
|||
accountSetupToken?: string;
|
||||
};
|
||||
|
||||
type UserFilterOptions = { email?: string; firstName?: string; lastName?: string };
|
||||
type UserFilterOptions = { email?: string; firstName?: string; lastName?: string; status?: string };
|
||||
|
||||
@Injectable()
|
||||
export class OrganizationsService {
|
||||
|
|
@ -150,6 +150,10 @@ export class OrganizationsService {
|
|||
qb.orWhere('lower(user.lastName) like :lastName', {
|
||||
lastName: `%${options?.lastName.toLowerCase()}%`,
|
||||
});
|
||||
if (options?.status)
|
||||
qb.orWhere('organization_user.status = :status', {
|
||||
status: `${options?.status}`,
|
||||
});
|
||||
});
|
||||
};
|
||||
const getAndConditions = () => {
|
||||
|
|
@ -166,6 +170,10 @@ export class OrganizationsService {
|
|||
qb.andWhere('lower(user.lastName) like :lastName', {
|
||||
lastName: `%${options?.lastName.toLowerCase()}%`,
|
||||
});
|
||||
if (options?.status)
|
||||
qb.andWhere('organization_user.status = :status', {
|
||||
status: `${options?.status}`,
|
||||
});
|
||||
});
|
||||
};
|
||||
const query = createQueryBuilder(OrganizationUser, 'organization_user')
|
||||
|
|
|
|||
Loading…
Reference in a new issue