From 407b49cc3208d1deea602847b5082f5185c00df4 Mon Sep 17 00:00:00 2001 From: Berra Karaman Date: Thu, 29 Feb 2024 13:36:31 +0300 Subject: [PATCH] add tabs show unpublished activities for staff and educators --- .../zubhub/public/locales/en/translation.json | 6 + .../views/activities/activitiesStyles.js | 14 ++ .../src/store/actions/activityActions.js | 212 ++++++++---------- .../src/store/reducers/activityReducer.js | 2 + .../src/views/activities/activities.jsx | 137 ++++++----- 5 files changed, 199 insertions(+), 172 deletions(-) diff --git a/zubhub_frontend/zubhub/public/locales/en/translation.json b/zubhub_frontend/zubhub/public/locales/en/translation.json index 983199552..b0a31927c 100644 --- a/zubhub_frontend/zubhub/public/locales/en/translation.json +++ b/zubhub_frontend/zubhub/public/locales/en/translation.json @@ -1089,6 +1089,12 @@ }, "activities": { + "title": "Activities", + "tabs": { + "published": "Published", + "unpublished": "Unpublished", + "ariaLabel": "Activity Tabs" + }, "LinkedProjects": "Linked Projects", "errors": { "emptyList": "No activities created yet !", diff --git a/zubhub_frontend/zubhub/src/assets/js/styles/views/activities/activitiesStyles.js b/zubhub_frontend/zubhub/src/assets/js/styles/views/activities/activitiesStyles.js index cdd5a18bf..7ad17b4ca 100644 --- a/zubhub_frontend/zubhub/src/assets/js/styles/views/activities/activitiesStyles.js +++ b/zubhub_frontend/zubhub/src/assets/js/styles/views/activities/activitiesStyles.js @@ -1,10 +1,24 @@ const styles = theme => ({ + tabs: { + margin: '2em 0', + [theme.breakpoints.up('900')]: { + paddingRight: '1em', + }, + }, + tab: { + textTransform: 'none', + fontSize: '1.2em', + fontWeight: 600, + }, activityListContainer: { marginTop: '2em', [theme.breakpoints.down('378')]: { marginTop: '3em', }, }, + activitiesContainer: { + marginTop: 0, + }, activityBoxContainer: { padding: '5vh 10px', position: 'relative', diff --git a/zubhub_frontend/zubhub/src/store/actions/activityActions.js b/zubhub_frontend/zubhub/src/store/actions/activityActions.js index 4e1498b25..7300dd7e6 100644 --- a/zubhub_frontend/zubhub/src/store/actions/activityActions.js +++ b/zubhub_frontend/zubhub/src/store/actions/activityActions.js @@ -2,181 +2,155 @@ import { toast } from 'react-toastify'; import API from '../../api/api'; import * as at from '../actionTypes'; -let ActivityAPI = new API(); -export const setActivities = activities => { - return dispatch => { - dispatch({ - type: at.SET_ACTIVITIES, - payload: { all_activities: activities }, - }); - }; +const ActivityAPI = new API(); + +export const setActivities = activities => dispatch => { + dispatch({ + type: at.SET_ACTIVITIES, + payload: { all_activities: activities }, + }); }; -export const setActivity = activity => { - return dispatch => { - dispatch({ - type: at.SET_ACTIVITY, - payload: { activity: activity }, - }); - }; +export const setActivity = activity => dispatch => { + dispatch({ + type: at.SET_ACTIVITY, + payload: { activity }, + }); }; export const getMyActivities = ({ t, token }) => { console.log('getMyActivities', token); - return async dispatch => { - return ActivityAPI.getMyActivities(token) + return async dispatch => + ActivityAPI.getMyActivities(token) .then(res => { console.log('result', res); if (res.status >= 200 && res.status < 300) { - let response = res.json(); + const response = res.json(); response.then(all => { console.log('all', all); dispatch({ type: at.SET_ACTIVITIES, payload: { - all_activities: all, + userActivities: all, }, }); }); + } else if (res.status === 403 && res.statusText === 'Forbidden') { + toast.warning(t('activityDetails.activity.delete.dialog.forbidden')); } else { - if (res.status === 403 && res.statusText === 'Forbidden') { - toast.warning( - t('activityDetails.activity.delete.dialog.forbidden'), - ); - } else { - toast.warning(t('activities.errors.dialog.serverError')); - } + toast.warning(t('activities.errors.dialog.serverError')); } }) - .catch(error => { + .catch(() => { toast.warning(t('activities.errors.dialog.serverError')); }); - }; }; export const getUnPublishedActivities = ({ t, token }) => { console.log('getUnPublishedActivities', token); - return async dispatch => { - return ActivityAPI.getUnPublishedActivities(token) + return async dispatch => + ActivityAPI.getUnPublishedActivities(token) .then(res => { console.log('result', res); if (res.status >= 200 && res.status < 300) { - let response = res.json(); + const response = res.json(); response.then(all => { console.log('all', all); dispatch({ type: at.SET_ACTIVITIES, payload: { - all_activities: all, + unPublishedActivities: all, }, }); }); + } else if (res.status === 403 && res.statusText === 'Forbidden') { + toast.warning(t('activityDetails.activity.delete.dialog.forbidden')); } else { - if (res.status === 403 && res.statusText === 'Forbidden') { - toast.warning( - t('activityDetails.activity.delete.dialog.forbidden'), - ); - } else { - toast.warning(t('activities.errors.dialog.serverError')); - } + toast.warning(t('activities.errors.dialog.serverError')); } }) - .catch(error => { + .catch(() => { toast.warning(t('activities.errors.dialog.serverError')); }); - }; }; -export const getActivities = t => { - return async dispatch => { - return ActivityAPI.getActivities() - .then(res => { - if (res.status >= 200 && res.status < 300) { - let response = res.json(); - response.then(all => { - dispatch({ - type: at.SET_ACTIVITIES, - payload: { - all_activities: all, - }, - }); +export const getActivities = t => async dispatch => + ActivityAPI.getActivities() + .then(res => { + if (res.status >= 200 && res.status < 300) { + const response = res.json(); + response.then(all => { + dispatch({ + type: at.SET_ACTIVITIES, + payload: { + all_activities: all, + }, }); - } else { - if (res.status === 403 && res.statusText === 'Forbidden') { - toast.warning( - t('activityDetails.activity.delete.dialog.forbidden'), - ); - } else { - toast.warning(t('activities.errors.dialog.serverError')); - } - } - }) - .catch(error => { - toast.warning(t('activities.errors.dialog.serverError')); - }); - }; -}; - -export const activityCountView = args => { - return async dispatch => { - try { - const result = await ActivityAPI.activityToggleSave(args); - dispatch({ - type: at.SET_ACTIVITY, - payload: { activity: result }, - }); - return { loading: false }; - } catch (error) { - if (error.message.startsWith('Unexpected')) { - toast.warning(args.t('projects.errors.unexpected')); + }); + } else if (res.status === 403 && res.statusText === 'Forbidden') { + toast.warning(t('activityDetails.activity.delete.dialog.forbidden')); } else { - toast.warning(error.message); + toast.warning(t('activities.errors.dialog.serverError')); } - return { loading: false }; + }) + .catch(() => { + toast.warning(t('activities.errors.dialog.serverError')); + }); + +export const activityCountView = args => async dispatch => { + try { + const result = await ActivityAPI.activityToggleSave(args); + dispatch({ + type: at.SET_ACTIVITY, + payload: { activity: result }, + }); + return { loading: false }; + } catch (error) { + if (error.message.startsWith('Unexpected')) { + toast.warning(args.t('projects.errors.unexpected')); + } else { + toast.warning(error.message); } - }; + return { loading: false }; + } }; -export const activityToggleSave = args => { - return async dispatch => { - try { - const result = await ActivityAPI.activityToggleSave(args); - dispatch({ - type: at.SET_ACTIVITY, - payload: { activity: result }, - }); - return { loading: false }; - } catch (error) { - if (error.message.startsWith('Unexpected')) { - toast.warning(args.t('projects.errors.unexpected')); - } else { - toast.warning(error.message); - } - return { loading: false }; +export const activityToggleSave = args => async dispatch => { + try { + const result = await ActivityAPI.activityToggleSave(args); + dispatch({ + type: at.SET_ACTIVITY, + payload: { activity: result }, + }); + return { loading: false }; + } catch (error) { + if (error.message.startsWith('Unexpected')) { + toast.warning(args.t('projects.errors.unexpected')); + } else { + toast.warning(error.message); } - }; + return { loading: false }; + } }; -export const activityTogglePublish = args => { - return async dispatch => { - try { - const result = await ActivityAPI.activityTogglePublish(args); +export const activityTogglePublish = args => async dispatch => { + try { + const result = await ActivityAPI.activityTogglePublish(args); - dispatch({ - type: at.SET_ACTIVITY, - payload: { activity: result }, - }); - return result; - } catch (error) { - if (error.message.startsWith('Unexpected')) { - toast.warning(args.t('projects.errors.unexpected')); - } else { - toast.warning(error.message); - } - return { error: error }; + dispatch({ + type: at.SET_ACTIVITY, + payload: { activity: result }, + }); + return result; + } catch (error) { + if (error.message.startsWith('Unexpected')) { + toast.warning(args.t('projects.errors.unexpected')); + } else { + toast.warning(error.message); } - }; + return { error }; + } }; diff --git a/zubhub_frontend/zubhub/src/store/reducers/activityReducer.js b/zubhub_frontend/zubhub/src/store/reducers/activityReducer.js index b07334b3f..624f2cd4a 100644 --- a/zubhub_frontend/zubhub/src/store/reducers/activityReducer.js +++ b/zubhub_frontend/zubhub/src/store/reducers/activityReducer.js @@ -1,9 +1,11 @@ import * as at from '../actionTypes'; + const default_state = { all_activities: [], published: [], unPublishedActivities: [], selectedActivity: {}, + userActivities: [], }; const activities = (state = default_state, action) => { switch (action.type) { diff --git a/zubhub_frontend/zubhub/src/views/activities/activities.jsx b/zubhub_frontend/zubhub/src/views/activities/activities.jsx index f84503861..8a9ac989c 100644 --- a/zubhub_frontend/zubhub/src/views/activities/activities.jsx +++ b/zubhub_frontend/zubhub/src/views/activities/activities.jsx @@ -1,10 +1,7 @@ import React, { useEffect, useState } from 'react'; import { connect, useSelector } from 'react-redux'; -import { useLocation } from 'react-router-dom'; +import { Grid, Tab, Tabs, Typography } from '@mui/material'; import { makeStyles } from '@mui/styles'; -import { Grid, Typography } from '@mui/material'; -import clsx from 'clsx'; - import { getActivities, getMyActivities, @@ -23,73 +20,107 @@ import LoadingPage from '../loading/LoadingPage'; const useStyles = makeStyles(styles); function Activities(props) { - const location = useLocation(); const classes = useStyles(); const [loading, setLoading] = useState(true); const { activities } = useSelector(state => state); - const [activityList, setActivityList] = useState([]); - + const [activityList, setActivityList] = useState({ + published: [], + unPublishedActivities: [], + userActivities: [], + }); + const [tab, setTab] = useState('published'); const commonClasses = makeStyles(DefaultStyles)(); + const { t } = props; useEffect(() => { - setActivityList(activities.all_activities); + setActivityList(activities); }, [activities]); - const flagMap = { - staff: () => - props.getUnPublishedActivities({ - t: props.t, - token: props.auth.token, - }), - educator: () => - props.getMyActivities({ - t: props.t, - token: props.auth.token, - }), - }; - useEffect(async () => { + useEffect(() => { setLoading(true); - if (location.state?.flag && flagMap[location.state.flag]) { - await flagMap[location.state.flag](); - } else { + async function getActivityList() { + if (props.auth?.tags.includes('staff')) { + await props.getUnPublishedActivities({ + t: props.t, + token: props.auth.token, + }); + } else if (props.auth?.tags.includes('educator')) { + await props.getMyActivities({ + t: props.t, + token: props.auth.token, + }); + } await props.getActivities(props.t); } - setActivityList(activities.all_activities); + getActivityList(); setLoading(false); - }, [location]); + }, []); + + const handleTabChange = (event, newTab) => { + setTab(newTab); + }; + + const ActivityCard = ({ activity }) => ( + + + + ); if (loading) { return ; } else if (!activityList || activityList.length === 0) { - return ; + return ; } else { return ( -
- - Activities - - - {activityList && - activityList.map((activity, index) => ( - - - - ))} +
+ {t('activities.title')} + {(props.auth?.tags.includes('staff') || props.auth?.tags.includes('educator')) && ( + + + !activity.publish).length + }) + `} + className={classes.tab} + /> + + )} + + {activityList.published && + tab === 'published' && + activityList.published.map(activity => )} + {activityList.unPublishedActivities && + tab === 'unpublished' && + props.auth?.tags.includes('staff') && + activityList.unPublishedActivities.map(activity => )} + {activityList.userActivities && + tab === 'unpublished' && + props.auth?.tags.includes('educator') && + activityList.userActivities + .filter(activity => !activity.publish) + .map(activity => )}
);