ENCOA-267

This commit is contained in:
Tiago Ribeiro
2024-12-23 10:18:52 +00:00
parent 9cf13e3f26
commit e9c961e633
6 changed files with 157 additions and 142 deletions

View File

@@ -8,6 +8,7 @@ import useGroups from "@/hooks/useGroups";
import useRecordStore from "@/stores/recordStore";
import { EntityWithRoles } from "@/interfaces/entity";
import { mapBy } from "@/utils";
import { useAllowedEntities } from "@/hooks/useEntityPermissions";
type TimeFilter = "months" | "weeks" | "days";
@@ -47,6 +48,8 @@ const RecordFilter: React.FC<Props> = ({
state.setSelectedUser
]);
const allowedViewEntities = useAllowedEntities(user, entities, 'view_student_record')
const entityUsers = useMemo(() => !entity ? users : users.filter(u => mapBy(u.entities, 'id').includes(entity)), [users, entity])
useEffect(() => setStatsUserId(user.id), [setStatsUserId, user.id])
@@ -64,7 +67,7 @@ const RecordFilter: React.FC<Props> = ({
<label className="font-normal text-base text-mti-gray-dim">Entity</label>
<Select
options={entities.map((e) => ({value: e.id, label: e.label}))}
options={allowedViewEntities.map((e) => ({ value: e.id, label: e.label }))}
onChange={(value) => setEntity(value?.value || undefined)}
isClearable
styles={{

View File

@@ -82,7 +82,7 @@ interface StatsGridItemProps {
selectedTrainingExams?: string[];
maxTrainingExams?: number;
setSelectedTrainingExams?: React.Dispatch<React.SetStateAction<string[]>>;
renderPdfIcon: (session: string, color: string, textColor: string) => React.ReactNode;
renderPdfIcon?: (session: string, color: string, textColor: string) => React.ReactNode;
}
const StatsGridItem: React.FC<StatsGridItemProps> = ({
@@ -236,7 +236,7 @@ const StatsGridItem: React.FC<StatsGridItemProps> = ({
{renderLevelScore()}
</span>
)}
{shouldRenderPDFIcon() && renderPdfIcon(session, textColor, textColor)}
{shouldRenderPDFIcon() && renderPdfIcon && renderPdfIcon(session, textColor, textColor)}
</div>
{examNumber === undefined ? (
<>

View File

@@ -79,6 +79,8 @@ const CLASSROOM_MANAGEMENT: PermissionLayout[] = [
{ label: "Upload to Classroom", key: "upload_classroom" },
{ label: "Remove from Classroom", key: "remove_from_classroom" },
{ label: "Delete Classroom", key: "delete_classroom" },
{ label: "View Student Record", key: "view_student_record" },
{ label: "Download Student Report", key: "download_student_record" },
]
const ENTITY_MANAGEMENT: PermissionLayout[] = [

View File

@@ -22,7 +22,7 @@ import { Assignment } from "@/interfaces/results";
import { getEntitiesUsers, getUsers } from "@/utils/users.be";
import { getAssignments, getEntitiesAssignments } from "@/utils/assignments.be";
import useGradingSystem from "@/hooks/useGrading";
import { mapBy, redirect, serialize } from "@/utils";
import { findBy, mapBy, redirect, serialize } from "@/utils";
import { getEntitiesWithRoles } from "@/utils/entities.be";
import { checkAccess } from "@/utils/permissions";
import { getGroups, getGroupsByEntities } from "@/utils/groups.be";
@@ -31,6 +31,7 @@ import { Grading } from "@/interfaces";
import { EntityWithRoles } from "@/interfaces/entity";
import CardList from "@/components/High/CardList";
import { requestUser } from "@/utils/api";
import { useAllowedEntities } from "@/hooks/useEntityPermissions";
export const getServerSideProps = withIronSessionSsr(async ({ req, res }) => {
const user = await requestUser(req, res)
@@ -74,6 +75,7 @@ export default function History({ user, users, assignments, entities, gradingSys
const [filter, setFilter] = useState<Filter>();
const { data: stats, isLoading: isStatsLoading } = useFilterRecordsByUser<Stat[]>(statsUserId || user?.id);
const allowedDownloadEntities = useAllowedEntities(user, entities, 'download_student_record')
const renderPdfIcon = usePDFDownload("stats");
@@ -155,6 +157,9 @@ export default function History({ user, users, assignments, entities, gradingSys
const customContent = (timestamp: string) => {
const dateStats = groupedStats[timestamp];
const statUser = findBy(users, 'id', dateStats[0]?.user)
const canDownload = mapBy(statUser?.entities, 'id').some(e => mapBy(allowedDownloadEntities, 'id').includes(e))
return (
<StatsGridItem
@@ -169,7 +174,7 @@ export default function History({ user, users, assignments, entities, gradingSys
selectedTrainingExams={selectedTrainingExams}
setSelectedTrainingExams={setSelectedTrainingExams}
maxTrainingExams={MAX_TRAINING_EXAMS}
renderPdfIcon={renderPdfIcon}
renderPdfIcon={canDownload ? renderPdfIcon : undefined}
/>
);
};

View File

@@ -61,7 +61,9 @@ export type RolePermission =
"edit_grading_system" |
"view_student_performance" |
"upload_classroom" |
"download_user_list"
"download_user_list" |
"view_student_record" |
"download_student_record"
export const DEFAULT_PERMISSIONS: RolePermission[] = [
"view_students",
@@ -136,5 +138,7 @@ export const ADMIN_PERMISSIONS: RolePermission[] = [
"edit_grading_system",
"view_student_performance",
"upload_classroom",
"download_user_list"
"download_user_list",
"view_student_record",
"download_student_record"
]

View File

@@ -3,6 +3,7 @@ import { WithEntity } from "@/interfaces/entity";
import { Assignment } from "@/interfaces/results";
import { CorporateUser, Group, GroupWithUsers, MasterCorporateUser, StudentUser, TeacherUser, Type, User } from "@/interfaces/user";
import client from "@/lib/mongodb";
import { uniq } from "lodash";
import moment from "moment";
import { getLinkedUsers, getUser } from "./users.be";
import { getSpecificUsers } from "./users.be";
@@ -116,7 +117,7 @@ export const getUsersGroups = async (ids: string[]) => {
export const convertToUsers = (group: Group, users: User[]): GroupWithUsers =>
Object.assign(group, {
admin: users.find((u) => u.id === group.admin),
participants: group.participants.map((p) => users.find((u) => u.id === p)).filter((x) => !!x) as User[],
participants: uniq(group.participants).map((p) => users.find((u) => u.id === p)).filter((x) => !!x) as User[],
});
export const getAllAssignersByCorporate = async (corporateID: string, type: Type): Promise<string[]> => {