Skip to content

Commit

Permalink
implement getUsers in PG user repository
Browse files Browse the repository at this point in the history
  • Loading branch information
JeromeBu committed Oct 8, 2024
1 parent a3598f2 commit e99c4a6
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -794,9 +794,6 @@ describe("Admin router", () => {

it("401 - not with backOfficeJwt", async () => {
const response = await sharedRequest.getUsers({
body: createApiConsumerParamsFromApiConsumer(
authorizedUnJeuneUneSolutionApiConsumer,
),
headers: { authorization: generateApiConsumerJwt({ id: "osef" }) },
queryParams: { emailContains: "yolo" },
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -339,13 +339,13 @@ export class PgUserRepository implements UserRepository {

public async getUsers(filters: GetUsersFilters): Promise<UserInList[]> {
if (filters.emailContains === "") return [];

return this.transaction
.selectFrom("users")
.leftJoin("users__agencies as ua", "ua.user_id", "users.id")
.select([
"email",
(qb) => sql`date_to_iso(${qb.ref("created_at")})`.as("createdAt"),
(qb) =>
sql<string>`date_to_iso(${qb.ref("created_at")})`.as("createdAt"),
"id",
"first_name as firstName",
"last_name as lastName",
Expand All @@ -357,14 +357,15 @@ export class PgUserRepository implements UserRepository {
)
.as("externalId"),
(qb) =>
sql`${qb.fn.count<number>("ua.agency_id")}::int`.as(
sql<number>`${qb.fn.count("ua.agency_id")}::int`.as(
"numberOfAgencies",
),
])
.where("email", "ilike", `%${filters.emailContains}%`)
.groupBy("users.id")
.orderBy("users.email")
.limit(100);
.limit(100)
.execute();
}

public async updateEmail(userId: string, email: string): Promise<void> {
Expand Down
21 changes: 12 additions & 9 deletions front/src/app/pages/admin/UsersTab.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
import { fr } from "@codegouvfr/react-dsfr";
import React, {ElementRef} from "react";
import { SearchBar } from "@codegouvfr/react-dsfr/SearchBar";
import { Table } from "@codegouvfr/react-dsfr/Table";
import {useDispatch} from "react-redux";
import React, { ElementRef } from "react";
import { useDispatch } from "react-redux";
import { domElementIds } from "shared";
import { SomeUsersWithoutName } from "src/app/components/agency/SomeUsersWithoutName";
import { SearchBar } from "@codegouvfr/react-dsfr/SearchBar";
import { useAppSelector } from "src/app/hooks/reduxHooks";
import { listUsersSelectors } from "src/core-logic/domain/admin/listUsers/listUsers.selectors";
import {
listUsersSlice
} from "src/core-logic/domain/admin/listUsers/listUsers.slice";
import { listUsersSlice } from "src/core-logic/domain/admin/listUsers/listUsers.slice";

export const UsersTab = () => {

const dispatch = useDispatch();
const query = useAppSelector(listUsersSelectors.query);

Expand All @@ -38,11 +35,17 @@ export const UsersTab = () => {
// Note: The default behavior for an input of type 'text' is to clear the input value when the escape key is pressed.
// However, due to a bug in @gouvfr/dsfr the escape key event is not propagated to the input element.
// As a result this onChange is not called when the escape key is pressed.
onChange={(event) => dispatch(listUsersSlice.actions.queryUpdated(event.currentTarget.value))}
onChange={(event) =>
dispatch(
listUsersSlice.actions.queryUpdated(
event.currentTarget.value,
),
)
}
// Same goes for the keydown event so this is useless but we hope the bug will be fixed soon.
onKeyDown={(event) => {
if (event.key === "Escape") {
inputElement.current?.blur()
inputElement.current?.blur();
}
}}
/>
Expand Down
4 changes: 1 addition & 3 deletions front/src/core-logic/domain/admin/adminPreloadedState.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import { agencyAdminInitialState } from "src/core-logic/domain/admin/agenciesAdmin/agencyAdmin.slice";
import { dashboardInitialState } from "src/core-logic/domain/admin/dashboardUrls/dashboardUrls.slice";
import { icUsersAdminInitialState } from "src/core-logic/domain/admin/icUsersAdmin/icUsersAdmin.slice";
import {
listUsersInitialState
} from "src/core-logic/domain/admin/listUsers/listUsers.slice";
import { listUsersInitialState } from "src/core-logic/domain/admin/listUsers/listUsers.slice";
import { notificationsInitialState } from "src/core-logic/domain/admin/notifications/notificationsSlice";
import { RootState } from "src/core-logic/storeConfig/store";
import { apiConsumerInitialState } from "../apiConsumer/apiConsumer.slice";
Expand Down
18 changes: 10 additions & 8 deletions front/src/core-logic/domain/admin/listUsers/listUsers.selectors.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import {createSelector} from "@reduxjs/toolkit";
import {RootState} from "src/core-logic/storeConfig/store";
import { createSelector } from "@reduxjs/toolkit";
import { RootState } from "src/core-logic/storeConfig/store";

const listUserState = ({ admin }: RootState) =>
admin.listUsers
const listUserState = ({ admin }: RootState) => admin.listUsers;

const users = createSelector(listUserState, ({ users }) => users)
const isFetching = createSelector(listUserState, ({ isFetching }) => isFetching)
const query = createSelector(listUserState, ({ query }) => query)
const users = createSelector(listUserState, ({ users }) => users);
const isFetching = createSelector(
listUserState,
({ isFetching }) => isFetching,
);
const query = createSelector(listUserState, ({ query }) => query);

export const listUsersSelectors = {
users,
isFetching,
query,
}
};

0 comments on commit e99c4a6

Please sign in to comment.