Skip to content

Commit

Permalink
Handle no data error for graphs (bcgov#2093)
Browse files Browse the repository at this point in the history
* Changes to show all survey results to superusers

* removing hard coded values

* fixing linting

* splitting to seperate end points

* fixing auth check

* fixing linting

* merging method in service

* Handle no data error for graphs

* adding new nodata component

* updated

* adding constant file for http error
  • Loading branch information
VineetBala-AOT authored Aug 30, 2023
1 parent 78d344a commit 74f7406
Show file tree
Hide file tree
Showing 12 changed files with 195 additions and 103 deletions.
2 changes: 1 addition & 1 deletion analytics-api/src/analytics_api/resources/aggregator.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def get():
if counts:
return counts, HTTPStatus.OK

return 'Engagement was not found', HTTPStatus.INTERNAL_SERVER_ERROR
return 'Engagement was not found', HTTPStatus.NOT_FOUND
except KeyError:
return 'Engagement was not found', HTTPStatus.INTERNAL_SERVER_ERROR
except ValueError as err:
Expand Down
4 changes: 2 additions & 2 deletions analytics-api/src/analytics_api/resources/engagement.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def get(engagement_id):
if engagement_record:
return engagement_record, HTTPStatus.OK

return 'Engagement was not found', HTTPStatus.INTERNAL_SERVER_ERROR
return 'Engagement was not found', HTTPStatus.NOT_FOUND
except KeyError:
return 'Engagement was not found', HTTPStatus.INTERNAL_SERVER_ERROR
except ValueError as err:
Expand All @@ -67,7 +67,7 @@ def get(engagement_id):
if map_data:
return map_data, HTTPStatus.OK

return 'Engagement was not found', HTTPStatus.INTERNAL_SERVER_ERROR
return 'Engagement was not found', HTTPStatus.NOT_FOUND
except KeyError:
return 'Engagement was not found', HTTPStatus.INTERNAL_SERVER_ERROR
except ValueError as err:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def get(engagement_id):
if user_response_record:
return user_response_record, HTTPStatus.OK

return 'User Response was not found', HTTPStatus.INTERNAL_SERVER_ERROR
return 'User Response was not found', HTTPStatus.NOT_FOUND
except KeyError:
return 'User Response was not found', HTTPStatus.INTERNAL_SERVER_ERROR
except ValueError as err:
Expand Down Expand Up @@ -80,7 +80,7 @@ def get(engagement_id):
if user_response_record:
return user_response_record, HTTPStatus.OK

return 'User Response was not found', HTTPStatus.INTERNAL_SERVER_ERROR
return 'User Response was not found', HTTPStatus.NOT_FOUND
except KeyError:
return 'User Response was not found', HTTPStatus.INTERNAL_SERVER_ERROR
except ValueError as err:
Expand Down
37 changes: 0 additions & 37 deletions analytics-api/src/analytics_api/utils/roles.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,41 +18,4 @@
class Role(Enum):
"""User Role."""

PUBLIC_USER = 'public_user'
ANONYMOUS_USER = 'anonymous_user'

# STAFF Based roles
CREATE_TENANT = 'create_tenant'
VIEW_TENANT = 'view_tenant'
VIEW_USERS = 'view_users'
TOGGLE_USER_STATUS = 'toggle_user_status'
CREATE_ADMIN_USER = 'create_admin_user'
CREATE_TEAM = 'create_team'
CREATE_ENGAGEMENT = 'create_engagement'
VIEW_SURVEYS = 'view_surveys'
CREATE_SURVEY = 'create_survey'
EDIT_SURVEY = 'edit_survey'
CLONE_SURVEY = 'clone_survey'
PUBLISH_ENGAGEMENT = 'publish_engagement'
VIEW_ENGAGEMENT = 'view_engagement'
VIEW_ASSIGNED_ENGAGEMENTS = 'view_assigned_engagements'
VIEW_PRIVATE_ENGAGEMENTS = 'view_private_engagements'
EDIT_ENGAGEMENT = 'edit_engagement'
REVIEW_COMMENTS = 'review_comments'
REVIEW_ALL_COMMENTS = 'review_all_comments'
ACCESS_DASHBOARD = 'access_dashboard'
VIEW_MEMBERS = 'view_members'
EDIT_MEMBERS = 'edit_members'
VIEW_ALL_SURVEYS = 'view_all_surveys' # Super user can view all kind of surveys including hidden
EDIT_ALL_SURVEYS = 'edit_all_surveys'
EDIT_DRAFT_ENGAGEMENT = 'edit_draft_engagement'
EDIT_SCHEDULED_ENGAGEMENT = 'edit_scheduled_engagement'
EDIT_UPCOMING_ENGAGEMENT = 'edit_upcoming_engagement'
EDIT_OPEN_ENGAGEMENT = 'edit_open_engagement'
EDIT_CLOSED_ENGAGEMENT = 'edit_closed_engagement'
VIEW_APPROVED_COMMENTS = 'view_approved_comments' # used just in the front end to show the comment page
VIEW_FEEDBACKS = 'view_feedbacks'
VIEW_ALL_ENGAGEMENTS = 'view_all_engagements' # Allows user access to all engagements including draft
SHOW_ALL_COMMENT_STATUS = 'show_all_comment_status' # Allows user to see all comment status
EXPORT_TO_CSV = 'export_to_csv' # Allows users to export comments to csv
VIEW_ALL_SURVEY_RESULTS = 'view_all_survey_results' # Allows users to view results to all questions
4 changes: 3 additions & 1 deletion met-web/src/components/publicDashboard/DashboardContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,9 @@ export const DashboardContextProvider = ({ children }: DashboardContextProviderP
/* check to ensure that users without the role access_dashboard can access the dashboard only after
the engagement is closed*/
if (!isClosed && canAccessDashboard) {
throw new Error('Engagement is not yet closed');
throw new Error(
'The report will only be available to view after the engagement period is over and the engagement is closed.',
);
}
};

Expand Down
46 changes: 32 additions & 14 deletions met-web/src/components/publicDashboard/KPI/ProjectLocation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@ import { Map } from '../../../models/analytics/map';
import { Engagement } from 'models/engagement';
import { MetLabel, MetPaper } from 'components/common';
import { ErrorBox } from '../ErrorBox';
import { NoData } from '../NoData';
import MetMap from 'components/map';
import { geoJSONDecode } from 'components/engagement/form/EngagementWidgets/Map/utils';
import axios, { AxiosError } from 'axios';
import { HTTP_STATUS_CODES } from 'constants/httpResponseCodes';

interface SurveysCompletedProps {
engagement: Engagement;
Expand All @@ -22,16 +25,27 @@ const ProjectLocation = ({ engagement, engagementIsLoading, handleProjectMapData
const isTablet = useMediaQuery((theme: Theme) => theme.breakpoints.down('md'));
const circleSize = isTablet ? 100 : 250;

const setErrors = (error: AxiosError) => {
if (error.response?.status !== HTTP_STATUS_CODES.NOT_FOUND) {
setIsError(true);
}
};

const fetchData = async () => {
setIsError(false);
setIsLoading(true);
try {
const response = await getMapData(Number(engagement.id));
setData(response);
handleProjectMapData(response);
setIsLoading(false);
} catch (error) {
setIsError(true);
if (axios.isAxiosError(error)) {
setErrors(error);
} else {
setIsError(true);
}
} finally {
setIsLoading(false);
}
};

Expand All @@ -41,18 +55,7 @@ const ProjectLocation = ({ engagement, engagementIsLoading, handleProjectMapData
}
}, [engagement.id]);

if (isError) {
return (
<ErrorBox
sx={{ height: '100%', minHeight: '213px' }}
onClick={() => {
fetchData();
}}
/>
);
}

if (isLoading || engagementIsLoading || !data) {
if (isLoading || engagementIsLoading) {
return (
<>
<MetLabel mb={2}>Project Location</MetLabel>
Expand All @@ -74,6 +77,21 @@ const ProjectLocation = ({ engagement, engagementIsLoading, handleProjectMapData
);
}

if (!data) {
return <NoData sx={{ height: '100%' }} />;
}

if (isError) {
return (
<ErrorBox
sx={{ height: '100%', minHeight: '213px' }}
onClick={() => {
fetchData();
}}
/>
);
}

return (
<>
<MetLabel mb={{ md: 0.5, lg: 2 }}>Project Location</MetLabel>
Expand Down
50 changes: 34 additions & 16 deletions met-web/src/components/publicDashboard/KPI/SurveyEmailsSent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,33 @@ import Stack from '@mui/material/Stack';
import { Box, Grid, CircularProgress, useMediaQuery, Theme } from '@mui/material';
import { DASHBOARD } from '../constants';
import { getAggregatorData } from 'services/analytics/aggregatorService';
import { AggregatorData, createAggregatorData } from '../../../models/analytics/aggregator';
import { AggregatorData } from '../../../models/analytics/aggregator';
import { Engagement } from 'models/engagement';
import { RadialBarChart, PolarAngleAxis, RadialBar } from 'recharts';
import { MetLabel, MetPaper } from 'components/common';
import { ErrorBox } from '../ErrorBox';
import { NoData } from '../NoData';
import axios, { AxiosError } from 'axios';
import { HTTP_STATUS_CODES } from 'constants/httpResponseCodes';

interface SurveyEmailsSentProps {
engagement: Engagement;
engagementIsLoading: boolean;
}

const SurveyEmailsSent = ({ engagement, engagementIsLoading }: SurveyEmailsSentProps) => {
const [data, setData] = useState<AggregatorData>(createAggregatorData());
const [data, setData] = useState<AggregatorData | null>(null);
const [isLoading, setIsLoading] = useState(true);
const [isError, setIsError] = useState(false);
const isTablet = useMediaQuery((theme: Theme) => theme.breakpoints.down('md'));
const circleSize = isTablet ? 100 : 250;

const setErrors = (error: AxiosError) => {
if (error.response?.status !== HTTP_STATUS_CODES.NOT_FOUND) {
setIsError(true);
}
};

const fetchData = async () => {
setIsLoading(true);
setIsError(false);
Expand All @@ -30,9 +39,14 @@ const SurveyEmailsSent = ({ engagement, engagementIsLoading }: SurveyEmailsSentP
count_for: 'email_verification',
});
setData(response);
setIsLoading(false);
} catch (error) {
setIsError(true);
if (axios.isAxiosError(error)) {
setErrors(error);
} else {
setIsError(true);
}
} finally {
setIsLoading(false);
}
};

Expand All @@ -42,17 +56,6 @@ const SurveyEmailsSent = ({ engagement, engagementIsLoading }: SurveyEmailsSentP
}
}, [engagement.id]);

if (isError) {
return (
<ErrorBox
sx={{ height: '100%', minHeight: '213px' }}
onClick={() => {
fetchData();
}}
/>
);
}

if (isLoading || engagementIsLoading) {
return (
<>
Expand All @@ -79,6 +82,21 @@ const SurveyEmailsSent = ({ engagement, engagementIsLoading }: SurveyEmailsSentP
);
}

if (!data) {
return <NoData sx={{ height: '100%' }} />;
}

if (isError) {
return (
<ErrorBox
sx={{ height: '100%', minHeight: '213px' }}
onClick={() => {
fetchData();
}}
/>
);
}

return (
<>
<MetLabel mb={{ md: 0.5, lg: 2 }}>Survey Emails Sent</MetLabel>
Expand Down Expand Up @@ -111,7 +129,7 @@ const SurveyEmailsSent = ({ engagement, engagementIsLoading }: SurveyEmailsSentP
dominantBaseline="middle"
className="progress-label"
>
{data.value}
{data?.value}
</text>
</RadialBarChart>
</Stack>
Expand Down
50 changes: 34 additions & 16 deletions met-web/src/components/publicDashboard/KPI/SurveysCompleted.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,34 @@ import Stack from '@mui/material/Stack';
import { Box, Grid, CircularProgress, useMediaQuery, Theme } from '@mui/material';
import { DASHBOARD } from '../constants';
import { getAggregatorData } from 'services/analytics/aggregatorService';
import { AggregatorData, createAggregatorData } from '../../../models/analytics/aggregator';
import { AggregatorData } from '../../../models/analytics/aggregator';
import { Engagement } from 'models/engagement';
import { RadialBarChart, PolarAngleAxis, RadialBar } from 'recharts';
import { MetLabel, MetPaper } from 'components/common';
import { ErrorBox } from '../ErrorBox';
import { NoData } from '../NoData';
import axios, { AxiosError } from 'axios';
import { HTTP_STATUS_CODES } from 'constants/httpResponseCodes';

interface SurveysCompletedProps {
engagement: Engagement;
engagementIsLoading: boolean;
}

const SurveysCompleted = ({ engagement, engagementIsLoading }: SurveysCompletedProps) => {
const [data, setData] = useState<AggregatorData>(createAggregatorData());
const [data, setData] = useState<AggregatorData | null>(null);
const [isLoading, setIsLoading] = useState(true);
const [isError, setIsError] = useState(false);
const isTablet = useMediaQuery((theme: Theme) => theme.breakpoints.down('md'));

const circleSize = isTablet ? 100 : 250;

const setErrors = (error: AxiosError) => {
if (error.response?.status !== HTTP_STATUS_CODES.NOT_FOUND) {
setIsError(true);
}
};

const fetchData = async () => {
setIsLoading(true);
setIsError(false);
Expand All @@ -31,9 +40,14 @@ const SurveysCompleted = ({ engagement, engagementIsLoading }: SurveysCompletedP
count_for: 'survey_completed',
});
setData(response);
setIsLoading(false);
} catch (error) {
setIsError(true);
if (axios.isAxiosError(error)) {
setErrors(error);
} else {
setIsError(true);
}
} finally {
setIsLoading(false);
}
};

Expand All @@ -43,17 +57,6 @@ const SurveysCompleted = ({ engagement, engagementIsLoading }: SurveysCompletedP
}
}, [engagement.id]);

if (isError) {
return (
<ErrorBox
sx={{ height: '100%', minHeight: '213px' }}
onClick={() => {
fetchData();
}}
/>
);
}

if (isLoading || engagementIsLoading) {
return (
<>
Expand All @@ -80,6 +83,21 @@ const SurveysCompleted = ({ engagement, engagementIsLoading }: SurveysCompletedP
);
}

if (!data) {
return <NoData sx={{ height: '100%' }} />;
}

if (isError) {
return (
<ErrorBox
sx={{ height: '100%', minHeight: '213px' }}
onClick={() => {
fetchData();
}}
/>
);
}

return (
<>
<MetLabel mb={{ md: 0.5, lg: 2 }}>Surveys Completed</MetLabel>
Expand Down Expand Up @@ -112,7 +130,7 @@ const SurveysCompleted = ({ engagement, engagementIsLoading }: SurveysCompletedP
dominantBaseline="middle"
className="progress-label"
>
{data.value}
{data?.value}
</text>
</RadialBarChart>
</Stack>
Expand Down
Loading

0 comments on commit 74f7406

Please sign in to comment.