Skip to content

Commit 133e410

Browse files
committed
feat: include missing units to organisation usage page
1 parent b423520 commit 133e410

File tree

1 file changed

+82
-28
lines changed

1 file changed

+82
-28
lines changed

src/components/usage/OrganisationUserUsage.tsx

Lines changed: 82 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@ dayjs.extend(utc);
77

88
import { type UserDetail } from "@squonk/account-server-client";
99
import { useGetOrganisation } from "@squonk/account-server-client/organisation";
10-
import { useGetUnits } from "@squonk/account-server-client/unit";
10+
import { useGetOrganisationUnits } from "@squonk/account-server-client/unit";
1111
import { useGetOrganisationUsers } from "@squonk/account-server-client/user";
1212
import { type InventoryUserDetail } from "@squonk/data-manager-client";
13+
import { useGetProjects } from "@squonk/data-manager-client/project";
1314

1415
import { Alert, Container, Typography } from "@mui/material";
1516
import { createColumnHelper } from "@tanstack/react-table";
@@ -22,6 +23,7 @@ import { getSharedColumns, type UserActivity } from "./sharedColumns";
2223
type Unit = {
2324
id: string;
2425
name?: string;
26+
number_of_projects: number;
2527
};
2628

2729
type InventoryWithUnit = UserActivity & {
@@ -36,47 +38,99 @@ export interface OrganisationUserUsageProps {
3638
organisationId: string;
3739
}
3840

39-
export const OrganisationUserUsage = ({ organisationId }: OrganisationUserUsageProps) => {
40-
const { data: organisation, isLoading: isOrganisationLoading } =
41-
useGetOrganisation(organisationId);
42-
const { data: units } = useGetUnits({
43-
query: { select: (data) => data.units.flatMap((org) => org.units) },
41+
const useOranisationUsersData = (organisationId: string) => {
42+
const { data: organisation } = useGetOrganisation(organisationId);
43+
const { data: units } = useGetOrganisationUnits(organisationId, {
44+
query: { select: (data) => data.units },
4445
});
45-
const { data, error: inventoryError } = useGetUserInventory<InventoryWithUnit[]>(
46+
const { data: allProjects } = useGetProjects(undefined, {
47+
query: { select: (data) => data.projects },
48+
});
49+
const { data, error } = useGetUserInventory<InventoryWithUnit[]>(
4650
{ org_id: organisationId },
4751
{
4852
query: {
4953
retry: false,
5054
select: (data) => {
51-
return data.users.map(({ projects, activity, first_seen, last_seen_date, username }) => ({
52-
username,
53-
activity,
54-
first_seen,
55-
last_seen_date,
56-
units: Object.values(projects)
57-
.flat()
58-
.map(({ unit_id }) => ({
59-
id: unit_id,
60-
name: units?.find((unit) => unit.id === unit_id)?.name,
61-
}))
62-
.reduce<Unit[]>((uniqueUnits, unit) => {
63-
// keep only unique units
64-
const existingUnit = uniqueUnits.find((u) => u.id === unit.id);
65-
if (!existingUnit) {
66-
uniqueUnits.push(unit);
67-
}
68-
return uniqueUnits;
69-
}, []),
70-
}));
55+
return data.users
56+
.map(({ projects, activity, first_seen, last_seen_date, username }) => {
57+
// get all the unique units from the projects
58+
// include the unit name from the units response
59+
const inventoryUnits = Object.values(projects)
60+
.flat()
61+
.map(({ unit_id }) => ({
62+
id: unit_id,
63+
name: units?.find((unit) => unit.id === unit_id)?.name,
64+
number_of_projects: Object.values(projects)
65+
.flat()
66+
.reduce((count, project) => {
67+
return project.unit_id === unit_id ? count + 1 : count;
68+
}, 0),
69+
}))
70+
.reduce<Unit[]>((uniqueUnits, unit) => {
71+
// keep only unique units
72+
const existingUnit = uniqueUnits.find((u) => u.id === unit.id);
73+
if (!existingUnit) {
74+
uniqueUnits.push(unit);
75+
}
76+
return uniqueUnits;
77+
}, []);
78+
79+
// include the units from the units response missing from the inventory that the user
80+
// is a member
81+
const newUnits: Unit[] =
82+
units
83+
?.filter((unit) => {
84+
const foundUnit = inventoryUnits.find((u) => u.id !== unit.id);
85+
if (foundUnit === undefined) {
86+
return false;
87+
} else if (
88+
(organisation?.users ?? []).map((user) => user.id).includes(username) ||
89+
organisation?.owner_id === username ||
90+
unit.owner_id === username ||
91+
unit.users.map((user) => user.id).includes(username)
92+
) {
93+
return true;
94+
}
95+
return false;
96+
})
97+
.map((unit) => ({
98+
id: unit.id,
99+
name: unit.name,
100+
number_of_projects:
101+
allProjects?.filter((project) => project.unit_id === unit.id).length ?? 0,
102+
})) ?? [];
103+
104+
const allUnits = [...inventoryUnits, ...newUnits];
105+
106+
return {
107+
username,
108+
activity,
109+
first_seen,
110+
last_seen_date,
111+
112+
units: allUnits,
113+
};
114+
})
115+
.filter((user) => user.units.length > 0);
71116
},
72117
},
73118
},
74119
);
120+
121+
return { data, error };
122+
};
123+
124+
export const OrganisationUserUsage = ({ organisationId }: OrganisationUserUsageProps) => {
125+
const { data: organisation, isLoading: isOrganisationLoading } =
126+
useGetOrganisation(organisationId);
127+
75128
const { data: organisationMembers } = useGetOrganisationUsers(organisationId, {
76129
query: {
77130
enabled: isOrganisationLoading || !organisation || organisation.caller_is_member,
78131
},
79132
});
133+
const { data, error: inventoryError } = useOranisationUsersData(organisationId);
80134

81135
const columns = [
82136
columnHelper.accessor("username", { header: "User" }),
@@ -94,7 +148,7 @@ export const OrganisationUserUsage = ({ organisationId }: OrganisationUserUsageP
94148
component="a"
95149
href={{ pathname: "/unit/[unitId]/inventory", query: { unitId: unit.id } }}
96150
>
97-
{unit.name}
151+
{unit.name ?? unit.id} ({unit.number_of_projects})
98152
</NextLink>
99153
</li>
100154
))}

0 commit comments

Comments
 (0)