Skip to content

Commit

Permalink
Merge pull request #2577 from bcgov/feature/DESENG-667-admin-authorin…
Browse files Browse the repository at this point in the history
…g-summary-section

[To Main] Feature - DESENG-667: Add engagement configuration summary
  • Loading branch information
NatSquared authored Aug 19, 2024
2 parents ee6caab + 993d964 commit e2d09dd
Show file tree
Hide file tree
Showing 24 changed files with 682 additions and 144 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.MD
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
## August 15, 2024

- **Feature** Add engagement configuration summary [🎟️ DESENG-667](https://citz-gdx.atlassian.net/browse/DESENG-667)

- Added a tabbed layout to the new engagement view page
- Added a new "Configuration" tab to display the engagement's configuration details
- The other tabs are blank for now, but will be filled in future tickets
- The configuration tab allows navigating back to the engagement configuration page
- Improvements to how engagements and related resources are fetched and saved

- **Feature** New engagement authoring view tab [🎟️ DESENG-674](https://citz-gdx.atlassian.net/browse/DESENG-674)

## August 13, 2024

- **Task** Fix dagster etl error in "dev" environment [🎟️ DESENG-677](https://citz-gdx.atlassian.net/browse/DESENG-677)

## August 8, 2024
Expand Down
10 changes: 5 additions & 5 deletions met-web/src/components/common/Communication/StatusIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,32 +26,32 @@ type IconWeight = 'solid' | 'regular' | 'light';
export const StatusIcon = ({
status,
color,
weight = 'solid',
weight = 'regular',
...props
}: {
status: 'success' | 'warning' | 'error' | 'info';
status: 'success' | 'warning' | 'danger' | 'info';
color?: string;
weight?: IconWeight;
} & Partial<FontAwesomeIconProps>) => {
let iconMap = {
success: faCheckCircle,
warning: faExclamationTriangle,
error: faExclamationCircle,
danger: faExclamationCircle,
info: faInfoCircle,
};
if (weight === 'regular') {
iconMap = {
success: faCheckCircleRegular,
warning: faExclamationTriangleRegular,
error: faExclamationCircleRegular,
danger: faExclamationCircleRegular,
info: faInfoCircleRegular,
};
}
if (weight === 'light') {
iconMap = {
success: faCheckCircleLight,
warning: faExclamationTriangleLight,
error: faExclamationCircleLight,
danger: faExclamationCircleLight,
info: faInfoCircleLight,
};
}
Expand Down
10 changes: 8 additions & 2 deletions met-web/src/components/common/Indicators/StatusChip.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { Chip as MuiChip, Skeleton, useTheme } from '@mui/material';
import { ChipProps as MuiChipProps, Chip as MuiChip, Skeleton, useTheme } from '@mui/material';
import { colors } from '..';
import { SubmissionStatus } from 'constants/engagementStatus';

Expand All @@ -23,12 +23,17 @@ export const getStatusFromStatusId = (statusId: SubmissionStatus): StatusText =>
}
};

export const EngagementStatusChip: React.FC<ChipProps> = ({ label: customLabel, statusId: status }) => {
export const EngagementStatusChip: React.FC<ChipProps & Partial<MuiChipProps>> = ({
label: customLabel,
statusId: status,
...props
}) => {
const statusText = getStatusFromStatusId(status);
const theme = useTheme();
const invert = theme.palette.mode === 'dark';
return (
<MuiChip
{...props}
label={customLabel || statusText}
className={`status-chip status-chip-${statusText.toLowerCase()} ${invert ? 'status-chip-invert' : ''}`}
sx={{
Expand Down Expand Up @@ -74,6 +79,7 @@ export const EngagementStatusChip: React.FC<ChipProps> = ({ label: customLabel,
borderColor: colors.surface.gray[100],
color: colors.surface.gray[40],
},
...props.sx,
}}
/>
);
Expand Down
4 changes: 2 additions & 2 deletions met-web/src/components/common/Layout/SystemMessage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export const SystemMessage = ({
children,
...props
}: {
status: 'success' | 'warning' | 'error' | 'info';
status: 'success' | 'warning' | 'danger' | 'info';
onDismiss?: () => void;
color?: string;
coloredBackground?: boolean;
Expand All @@ -30,7 +30,7 @@ export const SystemMessage = ({
maxWidth: { xs: '100%', md: '700px' },
borderRadius: '8px',
backgroundColor: coloredBackground ? colors.notification[status].tint : 'transparent',
color: 'type.primary',
color: 'text.primary',
padding: '0.8rem 1rem',
paddingLeft: { xs: '0.5rem', md: '1rem' },
border: `1px solid ${colors.notification[status].shade}`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,16 @@ export const DateRangePickerWithCalculation = () => {
if (name === 'end_date') {
trigger('end_date');
}
if (!value?.end_date) return;
setNumberOfDays(value.end_date.clone().add(1, 'second').diff(value.start_date, 'days'));
});
return () => subscription.unsubscribe();
}, [watch]);

useEffect(() => {
if (startDate && endDate) {
setNumberOfDays(endDate.clone().add(1, 'second').diff(startDate, 'days'));
}
}, [startDate, endDate]);

const getDayStyle = (props: PickersDayProps<Dayjs | null>) => {
const standardStyle = {
margin: 0,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export const engagementCreateAction: ActionFunction = async ({ request }) => {
formData.getAll('users').forEach((user_id) => {
addTeamMemberToEngagement({ user_id: user_id.toString(), engagement_id: engagement.id });
});
return redirect(`/engagements/${engagement.id}/form`);
return redirect(`/engagements/${engagement.id}/view`);
};

export default engagementCreateAction;
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { ENGAGEMENT_MEMBERSHIP_STATUS } from 'models/engagementTeamMember';
import { ActionFunction, redirect } from 'react-router-dom';
import { patchEngagement } from 'services/engagementService';
import { patchEngagementSlug } from 'services/engagementSlugService';
import {
addTeamMemberToEngagement,
revokeMembership,
reinstateMembership,
getTeamMembers,
} from 'services/membershipService';

export const engagementUpdateAction: ActionFunction = async ({ request, params }) => {
const formData = (await request.formData()) as FormData;
const engagementId = Number(params.engagementId);
await patchEngagement({
id: engagementId,
name: formData.get('name') as string,
start_date: formData.get('start_date') as string,
end_date: formData.get('end_date') as string,
is_internal: formData.get('is_internal') === 'true',
});
try {
await patchEngagementSlug({
engagement_id: engagementId,
slug: formData.get('slug') as string,
});
} catch (e) {
console.error('Error updating engagement slug', e);
}

const currentTeamMembers = await getTeamMembers({ engagement_id: engagementId });
const users = formData.getAll('users') as string[];
const usersSet = new Set(users);

try {
// Process deactivated users for reinstatement (and active users for revocation)
// Caution - headaches ahead! There is a big difference between user_id and user.external_id
for (const member of currentTeamMembers) {
const isUserInForm = usersSet.has(String(member.user.external_id));
if (member.status !== ENGAGEMENT_MEMBERSHIP_STATUS.Active) {
if (isUserInForm) {
// If the user was previously deactivated, reinstate them
reinstateMembership(engagementId, member.user_id);
}
} else if (!isUserInForm) {
// If the user was previously active but is not in the form, revoke their membership
revokeMembership(engagementId, member.user_id);
}

// Remove all known users from the set so we can add new members in the next step
usersSet.delete(String(member.user.external_id));
}
// Add new members that weren't in the current team members list
for (const user of usersSet) {
addTeamMemberToEngagement({ user_id: user, engagement_id: engagementId });
}
} catch (e) {
console.error('Error updating team members', e);
}

return redirect(`/engagements/${engagementId}/view`);
};

export default engagementUpdateAction;
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ const EngagementVisibilityControl = () => {
const isInternal = watch('is_internal');
const formSlug = watch('slug');
const isConfirmed = watch('_visibilityConfirmed');
const setIsConfirmed = (value: boolean) => setValue('_visibilityConfirmed', value);
const setIsConfirmed = (value: boolean) => setValue('_visibilityConfirmed', value, { shouldDirty: true });

const [isEditing, setIsEditing] = React.useState(false);
const [currentSlug, setCurrentSlug] = React.useState(formSlug);
const [hasBeenEdited, setHasBeenEdited] = React.useState(false);
const [hasBeenEdited, setHasBeenEdited] = React.useState(isConfirmed);

useEffect(() => {
const subscription = watch((value, { name, type }) => {
Expand All @@ -41,7 +41,7 @@ const EngagementVisibilityControl = () => {
})
.join('')
.toLowerCase();
setValue('slug', newSlug);
setValue('slug', newSlug, { shouldDirty: true });
setCurrentSlug(newSlug);
}
});
Expand Down Expand Up @@ -125,7 +125,7 @@ const EngagementVisibilityControl = () => {
onClick={() => {
setIsConfirmed(true);
setHasBeenEdited(true);
setValue('slug', currentSlug);
setValue('slug', currentSlug, { shouldDirty: true });
}}
>
Confirm
Expand Down Expand Up @@ -178,7 +178,7 @@ const EngagementVisibilityControl = () => {
disabled={!currentSlug}
variant="primary"
onClick={() => {
setValue('slug', currentSlug);
setValue('slug', currentSlug, { shouldDirty: true });
setHasBeenEdited(true);
setIsConfirmed(true);
setIsEditing(false);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';
import { Grid, Checkbox, FormControlLabel } from '@mui/material';
import { SystemMessage } from 'components/common/Layout/SystemMessage';
import { EngagementConfigurationData } from './form';
import { EngagementConfigurationData } from './wizard';
import { useFormContext } from 'react-hook-form';

export const FeedbackMethodSelector = () => {
Expand All @@ -26,6 +26,7 @@ export const FeedbackMethodSelector = () => {
checked
? [...watch('feedback_methods'), 'survey']
: watch('feedback_methods').filter((m) => m !== 'survey'),
{ shouldDirty: true },
);
}}
/>
Expand All @@ -40,6 +41,7 @@ export const FeedbackMethodSelector = () => {
checked
? [...watch('feedback_methods'), '3rd_party']
: watch('feedback_methods').filter((m) => m !== '3rd_party'),
{ shouldDirty: true },
);
}}
/>
Expand Down
Loading

0 comments on commit e2d09dd

Please sign in to comment.