Skip to content

Commit

Permalink
Merge branch 'main' into release
Browse files Browse the repository at this point in the history
  • Loading branch information
aaronshiel committed Aug 15, 2023
2 parents d3e4adf + 91b932b commit 105de8e
Show file tree
Hide file tree
Showing 13 changed files with 353 additions and 23 deletions.
29 changes: 29 additions & 0 deletions client/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -337,13 +337,15 @@ export async function fetchUsers(
isPrivate
isArchived
isAdvanced
isPublicApproved
lastTrainStatus
orgPermissions {
orgId
viewPermission
editPermission
}
updatedAt
createdAt
}
}
}
Expand Down Expand Up @@ -1030,6 +1032,7 @@ export async function fetchMentorById(
dirtyReason
isPrivate
isArchived
isPublicApproved
isAdvanced
hasVirtualBackground
virtualBackgroundUrl
Expand Down Expand Up @@ -1286,6 +1289,31 @@ export async function updateUserDisabled(
);
}

export async function updateMentorPublicApproval(
isPublicApproved: boolean,
accessToken: string,
mentorId: string
): Promise<Mentor> {
return execGql<Mentor>(
{
query: `
mutation UpdateMentorPublicApproval($mentorId: ID!, $isPublicApproved: Boolean) {
me {
updateMentorPublicApproval(mentorId: $mentorId, isPublicApproved: $isPublicApproved) {
isPublicApproved
}
}
}
`,
variables: {
mentorId,
isPublicApproved,
},
},
{ dataPath: ["me", "updateMentorPublicApproval"], accessToken }
);
}

export async function updateAnswerUrl(
accessToken: string,
mentorId: string,
Expand Down Expand Up @@ -2347,6 +2375,7 @@ export async function fetchMentors(
title
isPrivate
isArchived
isPublicApproved
isAdvanced
orgPermissions {
orgId
Expand Down
6 changes: 6 additions & 0 deletions client/src/components/setup/mentor-privacy-slide.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,12 @@ export function MentorPrivacySlide(props: {
Organization Privacy Permissions:
</Typography>
{renderOrgPermission()}
{!mentor.isPublicApproved ? (
<Typography variant="subtitle1" style={{ color: "red" }}>
Your mentor is not yet approved to be public. They will not be
visible to anyone until they are approved.
</Typography>
) : undefined}
</div>
}
/>
Expand Down
18 changes: 13 additions & 5 deletions client/src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -368,12 +368,12 @@ export function canEditMentorPrivacy(
if (!mentor || !myUser) {
return false;
}
const ops = mentor.orgPermissions?.filter(
(op) => op.editPermission === OrgEditPermissionType.ADMIN
const orgPerms = mentor.orgPermissions?.filter(
(perm) => perm.editPermission === OrgEditPermissionType.ADMIN
);
if (ops) {
const os = ops.map((op) => op.orgId);
for (const org of orgs.filter((o) => os.includes(o._id))) {
if (orgPerms) {
const orgIds = orgPerms.map((op) => op.orgId);
for (const org of orgs.filter((o) => orgIds.includes(o._id))) {
if (
org.members.find(
(m) => m.user._id === myUser._id && m.role === UserRole.ADMIN
Expand Down Expand Up @@ -483,3 +483,11 @@ interface EnumObject {
export function getEnumValues(e: EnumObject): string[] {
return Object.keys(e).map((i) => e[i]);
}

export function isDateWithinLastMonth(date: string): boolean {
const now = new Date();
const then = new Date(date);
const diff = now.getTime() - then.getTime();
const diffDays = Math.ceil(diff / (1000 * 3600 * 24));
return diffDays < 30;
}
12 changes: 9 additions & 3 deletions client/src/hooks/graphql/use-with-static-data-connection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export function useWithStaticDataConnection<T>(
if (!data) {
return;
}
const edges = sortFilter(data.edges);
const edges = sortFilter(data.edges, pageSearchParams);
const pd: Connection<T> = {
edges: edges.slice(page - pageLimit, page),
pageInfo: {
Expand All @@ -94,7 +94,10 @@ export function useWithStaticDataConnection<T>(
});
}, [data, page, pageSearchParams, preFilter, postSort]);

function sortFilter(e: Edge<T>[]): Edge<T>[] {
function sortFilter(
e: Edge<T>[],
pageSearchParams: StaticSearchParams
): Edge<T>[] {
let edges = e.filter((edge) => !preFilter || preFilter.filter(edge.node));
if (pageSearchParams.sortBy) {
const sortAscending = pageSearchParams.sortAscending ? 1 : -1;
Expand Down Expand Up @@ -149,6 +152,9 @@ export function useWithStaticDataConnection<T>(
return 0;
}
}
if (typeof aVal === "boolean" && typeof bVal === "boolean") {
return (aVal ? 1 : 0 - (bVal ? 1 : 0)) * ascending;
}
if (typeof aVal !== typeof bVal) {
if (aVal === null || aVal === undefined) {
return 1;
Expand Down Expand Up @@ -237,7 +243,7 @@ export function useWithStaticDataConnection<T>(
}

function hasNextPage(): boolean {
return sortFilter(data?.edges || []).length > page;
return sortFilter(data?.edges || [], pageSearchParams).length > page;
}

function hasPrevPage(): boolean {
Expand Down
19 changes: 19 additions & 0 deletions client/src/hooks/graphql/use-with-users.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
fetchUsers,
updateMentorAdvanced,
updateMentorPrivacy,
updateMentorPublicApproval,
updateUserDisabled,
updateUserPermissions,
} from "api";
Expand All @@ -23,6 +24,7 @@ import {
export interface UseUserData extends UseStaticDataConnection<User> {
userDataError?: LoadingError;
onUpdateUserPermissions: (userId: string, permissionLevel: string) => void;
onUpdateMentorPublicApproved: (userId: string, isDisabled: boolean) => void;
onUpdateUserDisabled: (userId: string, isDisabled: boolean) => void;
onUpdateMentorPrivacy: (mentorId: string, isPrivate: boolean) => void;
onUpdateMentorAdvanced: (mentorId: string, isAdvanced: boolean) => void;
Expand Down Expand Up @@ -83,6 +85,22 @@ export function useWithUsers(accessToken: string): UseUserData {
});
}

function onUpdateMentorPublicApproved(
mentorId: string,
isPublicApproved: boolean
): void {
updateMentorPublicApproval(isPublicApproved, accessToken, mentorId)
.then(() => {
reloadData();
})
.catch((err) => {
setUserDataError({
message: "Failed to update mentor for public approval",
error: `${err}`,
});
});
}

function onUpdateMentorPrivacy(mentorId: string, isPrivate: boolean): void {
updateMentorPrivacy(accessToken, { isPrivate }, mentorId)
.then(() => {
Expand Down Expand Up @@ -144,6 +162,7 @@ export function useWithUsers(accessToken: string): UseUserData {
onUpdateMentorPrivacy,
onUpdateMentorAdvanced,
onUpdateUserDisabled,
onUpdateMentorPublicApproved,
onArchiveMentor,
};
}
108 changes: 94 additions & 14 deletions client/src/pages/users.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import {
Theme,
SelectChangeEvent,
Checkbox,
Button,
Typography,
} from "@mui/material";
import { makeStyles } from "tss-react/mui";
import {
Expand Down Expand Up @@ -57,6 +59,7 @@ import {
canEditMentor,
canEditMentorPrivacy,
canEditUserRole,
isDateWithinLastMonth,
launchMentor,
} from "../helpers";
import useActiveMentor from "store/slices/mentor/useActiveMentor";
Expand Down Expand Up @@ -107,6 +110,14 @@ function getTableColumns(
isAdmin: boolean
): ColumnDef[] {
let columns: ColumnDef[] = [
{
id: "defaultMentor",
subField: ["isPublicApproved"],
label: "Approval",
minWidth: 0,
align: "left",
sortable: true,
},
{
id: "name",
label: "Name",
Expand Down Expand Up @@ -302,13 +313,32 @@ function UserItem(props: {
const { switchActiveMentor } = useActiveMentor();
const userRole = user.userRole;
const mentor = edge.node.defaultMentor;
const [approvalText, setApprovalText] = useState<string>(
mentor.isPublicApproved ? "Approved" : "Not Approved"
);
const [approvalTextColor, setApprovalTextColor] = useState<string>(
mentor.isPublicApproved ? "green" : "red"
);

useEffect(() => {
setApprovalText(mentor.isPublicApproved ? "Approved" : "Not Approved");
setApprovalTextColor(mentor.isPublicApproved ? "green" : "red");
}, [mentor.isPublicApproved]);

const isAdmin =
userRole === UserRole.ADMIN || userRole === UserRole.SUPER_ADMIN;

function handleRoleChange(user: string, permission: string): void {
props.userPagin.onUpdateUserPermissions(user, permission);
}

function handlePublicApprovalChange(
mentor: string,
isPublicApproved: boolean
): void {
props.userPagin.onUpdateMentorPublicApproved(mentor, isPublicApproved);
}

function handleDisabledChange(user: string, isDisabled: boolean): void {
props.userPagin.onUpdateUserDisabled(user, isDisabled);
}
Expand All @@ -324,9 +354,57 @@ function UserItem(props: {
function handleArchiveChange(mentor: string, isArchived: boolean): void {
props.userPagin.onArchiveMentor(mentor, isArchived);
}

return (
<TableRow data-cy={`user-${i}`} hover role="checkbox" tabIndex={-1}>
<TableCell data-cy="publicApproved" align="center" key={mentor._id}>
<>
{isDateWithinLastMonth(mentor.createdAt) &&
!mentor.isPublicApproved ? (
<Typography
data-cy="new-mentor-indicator"
style={{
color: "lightgreen",
fontStyle: "italic",
textDecoration: "underline",
}}
>
New Mentor
</Typography>
) : undefined}
<Button
data-cy="publicApprovalButton"
style={{
color: approvalTextColor,
cursor: "pointer",
width: "95px",
height: "50px",
}}
onMouseEnter={() => {
if (mentor.isPublicApproved) {
setApprovalText("Unapprove?");
setApprovalTextColor("red");
} else {
setApprovalText("Approve?");
setApprovalTextColor("green");
}
}}
onMouseLeave={() => {
if (mentor.isPublicApproved) {
setApprovalText("Approved");
setApprovalTextColor("green");
} else {
setApprovalText("Not Approved");
setApprovalTextColor("red");
}
}}
onClick={() => {
handlePublicApprovalChange(mentor._id, !mentor.isPublicApproved);
}}
>
<i>{approvalText}</i>
</Button>
</>
</TableCell>
<TableCell data-cy="name" align="left">
{edge.node.name}
</TableCell>
Expand Down Expand Up @@ -430,19 +508,21 @@ function UserItem(props: {
)}
</TableCell>
{isAdmin ? (
<TableCell data-cy="disabled" align="left">
<Checkbox
checked={edge.node.isDisabled}
disabled={
props.user.userRole !== UserRole.ADMIN &&
props.user.userRole !== UserRole.SUPER_ADMIN
}
color="secondary"
onClick={() =>
handleDisabledChange(edge.node._id, !edge.node.isDisabled)
}
/>
</TableCell>
<>
<TableCell data-cy="disabled" align="left">
<Checkbox
checked={edge.node.isDisabled}
disabled={
props.user.userRole !== UserRole.ADMIN &&
props.user.userRole !== UserRole.SUPER_ADMIN
}
color="secondary"
onClick={() =>
handleDisabledChange(edge.node._id, !edge.node.isDisabled)
}
/>
</TableCell>
</>
) : undefined}
{isAdmin ? (
<TableCell data-cy="advanced" align="left">
Expand Down
2 changes: 2 additions & 0 deletions client/src/types-gql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ export interface MentorGQL {
isDirty: boolean;
lastTrainStatus: JobState;
dirtyReason: MentorDirtyReason;
isPublicApproved: boolean;
isPrivate: boolean;
isArchived: boolean;
isAdvanced: boolean;
Expand All @@ -72,6 +73,7 @@ export interface MentorGQL {
answers: AnswerGQL[];
hasVirtualBackground: boolean;
virtualBackgroundUrl: string;
createdAt: string;
updatedAt: string;
}

Expand Down
2 changes: 2 additions & 0 deletions client/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ export interface Mentor {
isDirty: boolean;
lastTrainStatus: JobState;
dirtyReason: MentorDirtyReason;
isPublicApproved: boolean;
isPrivate: boolean;
isArchived: boolean;
isAdvanced: boolean;
Expand All @@ -204,6 +205,7 @@ export interface Mentor {
hasVirtualBackground: boolean;
virtualBackgroundUrl: string;
updatedAt: string;
createdAt: string;
numAnswersComplete: number;
}

Expand Down
2 changes: 1 addition & 1 deletion cypress/cypress.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"baseUrl": "http://localhost:80",
"baseUrl": "http://localhost:8000",
"video": false,
"$schema": "https://on.cypress.io/cypress.schema.json",
"chromeWebSecurity": false,
Expand Down
Loading

0 comments on commit 105de8e

Please sign in to comment.