Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 14 additions & 11 deletions epictrack-api/src/api/insights/work_staff_insight.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,28 +21,31 @@ class WorkStaffInsightGenerator:
def generate_partition_query(self, filters: List = None, staff_id: int = None):
"""Generates the group by subquery."""
filter_exprs = build_insights_filters(filters, "works") if filters else []
query = db.session.query(
StaffWorkRole.staff_id,
func.count(func.distinct(Work.id)).label("count"),
).join(Work, StaffWorkRole.work_id == Work.id)
query = (
db.session.query(
StaffWorkRole.staff_id,
func.count(func.distinct(Work.id)).label("count"),
)
.join(Work, StaffWorkRole.work_id == Work.id)
.join(Staff, Staff.id == StaffWorkRole.staff_id)
)

# Join necessary tables for filters
if filters:
query = query.join(WorkType, Work.work_type_id == WorkType.id)
query = query.join(Project, Work.project_id == Project.id)
query = query.join(WorkPhase, Work.current_work_phase_id == WorkPhase.id)

query = query.join(Staff, Staff.id == StaffWorkRole.staff_id)
query = (
query.join(WorkType, Work.work_type_id == WorkType.id)
.join(Project, Work.project_id == Project.id)
.join(WorkPhase, Work.current_work_phase_id == WorkPhase.id)
)

if staff_id:
query = query.filter(Staff.id == staff_id)
query = query.filter(Staff.is_active.is_(True))
query = query.filter(StaffWorkRole.is_active.is_(True))

query = query.filter(
Work.is_active.is_(True),
Work.is_deleted.is_(False),
Work.is_completed.is_(False),
Staff.is_active.is_(True),
StaffWorkRole.is_active.is_(True),
StaffWorkRole.role_id == RoleEnum.OFFICER_ANALYST.value,
*filter_exprs if filter_exprs else [],
Expand Down
4 changes: 4 additions & 0 deletions epictrack-api/src/api/resources/work.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,13 @@ def get():
else:
works = WorkService.find_all_works(is_active)

context = request_args.get("context", None)

exclude = [] if include_indigenous_nations else ['indigenous_works']
if not include_rel_staff:
exclude.append('rel_staff')
if context == "insights":
exclude.extend(['ea_act', 'responsible_epd', 'eac_decision_by', 'decision_by', 'substitution_act', 'eao_team'])

works_schema = res.WorkResponseSchema(many=True, exclude=exclude)

Expand Down
7 changes: 7 additions & 0 deletions epictrack-api/src/api/schemas/request/work_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,13 @@ class WorkQueryParameterSchema(RequestQueryParameterSchema):
missing=None
)

context = fields.Str(
metadata={"description": "Request context; use 'insights' for a lean response excluding unused nested objects"},
required=False,
missing=None,
allow_none=True,
)


class WorkPhaseQueryParameterSchema(RequestQueryParameterSchema):
"""Work Phase Query parameters"""
Expand Down
4 changes: 3 additions & 1 deletion epictrack-api/src/api/services/work.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,9 @@ def find_allocated_resources(cls, is_active=None):
.filter(
StaffWorkRole.work_id.in_(work_ids),
StaffWorkRole.is_deleted.is_(False),
StaffWorkRole.is_active.is_(True)
StaffWorkRole.is_active.is_(True),
Staff.is_active.is_(True),
Staff.is_deleted.is_(False)
)
.join(Role, Role.id == StaffWorkRole.role_id)
.add_entity(Role)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React, { useCallback, useEffect, useMemo } from "react";
import { MRT_ColumnDef } from "material-react-table";
import { Work } from "models/work";
import { rowsPerPageOptions } from "components/shared/MasterTrackTable/utils";
import { ETGridTitle, IButton } from "components/shared";
import { searchFilter } from "components/shared/MasterTrackTable/filters";
Expand All @@ -11,7 +10,6 @@ import { useGetWorkStaffsQuery } from "services/rtkQuery/workStaffInsights";
import { exportToCsv } from "components/shared/MasterTrackTable/utils";
import { Tooltip, Box } from "@mui/material";
import { sort } from "utils";
import { useGetWorksQuery } from "services/rtkQuery/workInsights";
import Icons from "components/icons";
import { IconProps } from "components/icons/type";
import { Role, WorkStaffRole, WorkStaffRoleNames } from "models/role";
Expand All @@ -20,57 +18,33 @@ import { useTableFilterContext } from "components/insights/TableFilterContext";

const DownloadIcon: React.FC<IconProps> = Icons["DownloadIcon"];

type WorkStaffWithWork = WorkStaff & { work: Work };

const WorkList = () => {
const [pagination, setPagination] = React.useState({
pageIndex: 0,
pageSize: 15,
});
const [workData, setWorkData] = React.useState<WorkStaffWithWork[]>([]);
const [workData, setWorkData] = React.useState<WorkStaff[]>([]);
const { columnFilters, setColumnFilters } = useTableFilterContext();
const { isUserInsights, staffId } = useInsightsContext();

const queryArg = useMemo(() => {
return {
is_active: true,
...(isUserInsights && staffId ? { staffId } : {}),
};
}, [isUserInsights, staffId]);

const { data: works } = useGetWorksQuery(queryArg, {
refetchOnMountOrArgChange: true,
});

const { data: workStaffs, isLoading } = useGetWorkStaffsQuery();

useEffect(() => {
if (workStaffs && works) {
const mergedData = workStaffs
.filter((workStaff) =>
isUserInsights
? workStaff.staff
.map((staff) => staff.id)
?.includes(staffId ? staffId : -1)
: true,
)
.map((workStaff) => {
const work = works.find(
(w) => w.eao_team_id === workStaff.eao_team.id,
);
if (!work) {
return null;
}
return { ...workStaff, work };
})
.filter(Boolean) as WorkStaffWithWork[];
setWorkData(sort(mergedData, "work.title"));
if (workStaffs) {
const filtered = workStaffs.filter((workStaff) =>
isUserInsights
? workStaff.staff
.map((staff) => staff.id)
?.includes(staffId ? staffId : -1)
: true,
);
setWorkData(sort(filtered, "title"));
setPagination((prev) => ({
...prev,
pageSize: workStaffs.length,
pageSize: filtered.length,
}));
}
}, [isUserInsights, staffId, works, workStaffs]);
}, [isUserInsights, staffId, workStaffs]);

const workLeads = useMemo(() => {
return Array.from(
Expand Down Expand Up @@ -149,7 +123,7 @@ const WorkList = () => {
);

useEffect(() => {
const cols: Array<MRT_ColumnDef<WorkStaffWithWork>> = [];
const cols: Array<MRT_ColumnDef<WorkStaff>> = [];
if (workStaffs && workStaffs.length > 0) {
const roles = [WorkStaffRole.TEAM_CO_LEAD, WorkStaffRole.OFFICER_ANALYST];
roles.forEach((role, index) => {
Expand Down Expand Up @@ -191,7 +165,7 @@ const WorkList = () => {
}
}, [getRolefilterOptions, roleFilterFunction, workStaffs]);

const columns = React.useMemo<MRT_ColumnDef<WorkStaffWithWork>[]>(() => {
const columns = React.useMemo<MRT_ColumnDef<WorkStaff>[]>(() => {
return [
{
accessorKey: "title",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
import { searchFilter } from "components/shared/MasterTrackTable/filters";
import { TableFilter } from "components/shared/filterSelect/TableFilter";
import MasterTrackTable from "components/shared/MasterTrackTable";
import { useGetAllWorksQuery } from "services/rtkQuery/workInsights";
import { useGetWorksQuery } from "services/rtkQuery/workInsights";
import { exportToCsv } from "components/shared/MasterTrackTable/utils";
import { Tooltip, Box, Grid } from "@mui/material";
import { ETCaption1, ETGridTitle, IButton } from "components/shared";
Expand Down Expand Up @@ -40,7 +40,7 @@ const WorkList = () => {
};
}, [isUserInsights, staffId]);

const { data, error, isLoading } = useGetAllWorksQuery(queryArg, {
const { data, error, isLoading } = useGetWorksQuery(queryArg, {
refetchOnMountOrArgChange: true,
});

Expand Down
38 changes: 14 additions & 24 deletions epictrack-web/src/services/rtkQuery/workInsights.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,11 @@ function buildInsightBody(

function buildQueryString(
base: string,
{ is_active, staffId }: { is_active?: boolean; staffId?: number } = {},
{
is_active,
staffId,
context,
}: { is_active?: boolean; staffId?: number; context?: string } = {},
): string {
const params: string[] = [];

Expand All @@ -45,6 +49,9 @@ function buildQueryString(
if (staffId !== undefined) {
params.push(`staff_id=${staffId}`);
}
if (context !== undefined) {
params.push(`context=${context}`);
}

return params.length ? `${base}?${params.join("&")}` : base;
}
Expand Down Expand Up @@ -92,32 +99,13 @@ export const workInsightsApi = createApi({
},
),

getAllWorks: builder.query<
Work[],
{ is_active?: boolean; staffId?: number } | void
>({
query: (
args: { is_active?: boolean; staffId?: number } = { is_active: true },
) => buildQueryString("works", args),
providesTags: (result) =>
result
? [
...result.map(({ id }) => ({
type: "Works" as const,
id,
})),
{ type: "Works", id: "LIST" },
]
: [{ type: "Works", id: "LIST" }],
}),

getWorks: builder.query<
Work[],
{ is_active?: boolean; staffId?: number } | void
>({
query: (
args: { is_active?: boolean; staffId?: number } = { is_active: true },
) => buildQueryString("works", args),
) => buildQueryString("works", { ...args, context: "insights" }),
providesTags: (result) =>
result
? [
Expand Down Expand Up @@ -150,8 +138,11 @@ export const workInsightsApi = createApi({

getWorksWithNations: builder.query<Work[], { staffId?: number } | void>({
query: (args) =>
buildQueryString("works", { ...args, is_active: true }) +
"&include_indigenous_nations=true&include_rel_staff=true",
buildQueryString("works", {
...args,
is_active: true,
context: "insights",
}) + "&include_indigenous_nations=true&include_rel_staff=true",
providesTags: (result) =>
result
? [
Expand Down Expand Up @@ -337,5 +328,4 @@ export const {
useGetWorksByYearOpenedQuery,
useGetWorksByYearCompletedQuery,
useGetWorkClosureBreakdownQuery,
useGetAllWorksQuery,
} = workInsightsApi;