From c2e44c729ffa75baf40f9e567206dfaff7c2b004 Mon Sep 17 00:00:00 2001 From: Roberto Lopez J Date: Tue, 17 Jan 2023 03:49:35 +0000 Subject: [PATCH 01/29] [Added new page for eventtype] --- src/app/services/breathecode.js | 20 ++- src/app/views/events/events.jsx | 1 + src/app/views/events/eventtypes.jsx | 170 +++++++++++++++++++++++ src/app/views/events/forms/EventForm.jsx | 1 + src/app/views/events/routes.js | 5 + 5 files changed, 192 insertions(+), 5 deletions(-) create mode 100644 src/app/views/events/eventtypes.jsx diff --git a/src/app/services/breathecode.js b/src/app/services/breathecode.js index 1f7c1c4a..806dcdb5 100644 --- a/src/app/services/breathecode.js +++ b/src/app/services/breathecode.js @@ -776,6 +776,16 @@ class BreatheCodeClient { "Academy event", `${this.host}/events/academy/organizer` ), + getAcademyEventType: () => + axios.bcGet( + "Event Type", + `${this.host}/events/academy/eventype` + ), + getAcademyEventTypeSlug: () => + axios.bcGet( + "Event Type", + `${this.host}/events/academy/eventype/${eventtype_slug}` + ), postAcademyEventOrganization: (payload) => axios.bcPost( "Academy event", @@ -802,6 +812,11 @@ class BreatheCodeClient { "Delete organizer", `${this.host}/events/academy/organization/organizer/${org}` ), + deleteAcademyEventTypes: (org) => + axios.bcDelete( + "Delete Eventtype", + `${this.host}/events/academy/eventype` + ), getEventbriteWebhook: (query) => { const qs = serializeQuerystring(query); return axios.bcGet( @@ -815,11 +830,6 @@ class BreatheCodeClient { }, getAcademyVenues: () => axios.bcGet("Venues", `${this.host}/events/academy/venues`), - getAcademyEventType: () => - axios.bcGet( - "Event Type", - `${this.host}/events/academy/eventype` - ), downloadCSV: (query) => { const qs = Object.keys(query) .map((key) => `${key}=${query[key]}`) diff --git a/src/app/views/events/events.jsx b/src/app/views/events/events.jsx index 6d998a4b..dff82a9c 100644 --- a/src/app/views/events/events.jsx +++ b/src/app/views/events/events.jsx @@ -229,6 +229,7 @@ const EventList = () => { search={async (querys) => { const { data } = await bc.events().getAcademyEvents(querys); setItems(data.results); + console.log(data) return data; }} deleting={async (querys) => { diff --git a/src/app/views/events/eventtypes.jsx b/src/app/views/events/eventtypes.jsx new file mode 100644 index 00000000..9e0e805f --- /dev/null +++ b/src/app/views/events/eventtypes.jsx @@ -0,0 +1,170 @@ +import React, { useState } from 'react'; +import { + Icon, + IconButton, + Button +} from '@material-ui/core'; +import A from '@material-ui/core/Link'; +import { Link } from 'react-router-dom'; +import dayjs from 'dayjs'; +import { toast } from 'react-toastify'; +import { Breadcrumb } from '../../../matx'; +import { getSession } from '../../redux/actions/SessionActions'; +import bc from '../../services/breathecode'; +import { SmartMUIDataTable } from '../../components/SmartDataTable'; + +toast.configure(); +const toastOption = { + position: toast.POSITION.BOTTOM_RIGHT, + autoClose: 8000, +}; + +const relativeTime = require('dayjs/plugin/relativeTime'); + +dayjs.extend(relativeTime); + +const EventList = () => { + const session = getSession(); + + const [items, setItems] = useState([]); + + const thisURL = `https://breathecode.herokuapp.com/v1/events/academy/eventype`; + + const [openDialog, setOpenDialog] = useState(false); + + const columns = [ + { + name: 'name', // field name in the row object + label: 'Name', // column title that will be shown in table + options: { + filter: true, + }, + }, + { + name: 'slug', // field name in the row object + label: 'Slug', // column title that will be shown in table + options: { + filter: true, + customBodyRenderLite: (dataIndex) => { + const item = items[dataIndex]; + return ( +
+
+ + {item?.slug} + +
+
+
+ ); + }, + }, + }, + { + name: 'description', // field name in the row object + label: 'Description', // column title that will be shown in table + options: { + filter: true, + customBodyRenderLite: (dataIndex) => { + const item = items[dataIndex]; + return ( +
+
+ + {item?.description} + +
+
+
+ ); + }, + }, + }, + { + name: 'language', // field name in the row object + label: 'Language', // column title that will be shown in table + options: { + filter: true, + customBodyRenderLite: (dataIndex) => { + const item = items[dataIndex]; + return ( +
+
+ +
+
+
+ ); + }, + }, + }, + { + name: 'action', + label: ' ', + options: { + filter: false, + customBodyRenderLite: (dataIndex) => ( +
+
+ + + edit + + +
+ ), + }, + }, + ]; + + return ( + <> +
+
+
+
+ +
+ +
+ + + +
+
+
+
+
+ { + const { data } = await bc.events().getAcademyEventType(querys); + setItems(data.results); + console.log('data', data) + return data; + }} + deleting={async (querys) => { + const { status } = await bc.events().deleteAcademyEventTypes(querys); + return status; + }} + /> +
+
+
+ + ); +}; + +export default EventList; diff --git a/src/app/views/events/forms/EventForm.jsx b/src/app/views/events/forms/EventForm.jsx index 50fa8966..9dd9f7f5 100644 --- a/src/app/views/events/forms/EventForm.jsx +++ b/src/app/views/events/forms/EventForm.jsx @@ -421,6 +421,7 @@ const EventForm = () => { )} /> + Manage Event Types Event Description diff --git a/src/app/views/events/routes.js b/src/app/views/events/routes.js index a8e8bae4..4901a2ed 100644 --- a/src/app/views/events/routes.js +++ b/src/app/views/events/routes.js @@ -27,6 +27,11 @@ const routes = [ exact: true, component: React.lazy(() => import('./attendees')), }, + { + path: '/events/type/list', + exact: true, + component: React.lazy(() => import('./eventtypes')), + }, ]; export default routes; From 2b49c663eba97e5fd7c2891be91ba206f5a818e3 Mon Sep 17 00:00:00 2001 From: Roberto Lopez J Date: Tue, 7 Feb 2023 17:04:57 +0000 Subject: [PATCH 02/29] [Added two new views for EventTypes] --- src/app/services/breathecode.js | 18 +- .../admin/syllabus-form/SyllabusDetails.jsx | 1 - src/app/views/admin/syllabus-form/index.jsx | 1 - .../EditAddEventTypes/EventTypeDetails.jsx | 185 ++++++++++++++ .../events/EditAddEventTypes/JoinEvents.jsx | 230 ++++++++++++++++++ .../events/EditAddEventTypes/NewEventType.jsx | 108 ++++++++ .../views/events/EditAddEventTypes/index.jsx | 131 ++++++++++ src/app/views/events/events.jsx | 5 - src/app/views/events/eventtypes.jsx | 34 +-- src/app/views/events/forms/EventForm.jsx | 3 +- src/app/views/events/routes.js | 7 +- 11 files changed, 697 insertions(+), 26 deletions(-) create mode 100644 src/app/views/events/EditAddEventTypes/EventTypeDetails.jsx create mode 100644 src/app/views/events/EditAddEventTypes/JoinEvents.jsx create mode 100644 src/app/views/events/EditAddEventTypes/NewEventType.jsx create mode 100644 src/app/views/events/EditAddEventTypes/index.jsx diff --git a/src/app/services/breathecode.js b/src/app/services/breathecode.js index 806dcdb5..0bcb8f1c 100644 --- a/src/app/services/breathecode.js +++ b/src/app/services/breathecode.js @@ -776,15 +776,27 @@ class BreatheCodeClient { "Academy event", `${this.host}/events/academy/organizer` ), + addAcademyEventType: (payload) => + axios.bcPost( + "Academy event type", + `${this.host}/events/academy/eventype`, + payload + ), getAcademyEventType: () => axios.bcGet( "Event Type", `${this.host}/events/academy/eventype` ), - getAcademyEventTypeSlug: () => + getAcademyEventTypeSlug: (slug) => axios.bcGet( - "Event Type", - `${this.host}/events/academy/eventype/${eventtype_slug}` + "Event Type Slug", + `${this.host}/events/academy/eventype/${slug}` + ), + updateAcademyEventTypeSlug: (slug, payload) => + axios.bcPut( + "Event Type Slug", + `${this.host}/events/academy/eventype/${slug}`, + payload ), postAcademyEventOrganization: (payload) => axios.bcPost( diff --git a/src/app/views/admin/syllabus-form/SyllabusDetails.jsx b/src/app/views/admin/syllabus-form/SyllabusDetails.jsx index ade8afbc..518a7128 100644 --- a/src/app/views/admin/syllabus-form/SyllabusDetails.jsx +++ b/src/app/views/admin/syllabus-form/SyllabusDetails.jsx @@ -56,7 +56,6 @@ const schema = Yup.object().shape({ const StudentDetails = ({ syllabus, onSubmit }) => { const [status, setStatus] = useState({ color: "", message: "" }); - const session = getSession(); const academyOwner = session.academy.id const syllabusId = syllabus.academy_owner.id diff --git a/src/app/views/admin/syllabus-form/index.jsx b/src/app/views/admin/syllabus-form/index.jsx index 2e71f3df..722bd236 100644 --- a/src/app/views/admin/syllabus-form/index.jsx +++ b/src/app/views/admin/syllabus-form/index.jsx @@ -34,7 +34,6 @@ dayjs.extend(LocalizedFormat); const Student = () => { const { syllabusSlug } = useParams(); const session = getSession(); - console.log("session", session) const [syllabus, setSyllabus] = useState(null); const [schedules, setSchedules] = useState([]); const [openDialog, setOpenDialog] = useState(false); diff --git a/src/app/views/events/EditAddEventTypes/EventTypeDetails.jsx b/src/app/views/events/EditAddEventTypes/EventTypeDetails.jsx new file mode 100644 index 00000000..4fc91c18 --- /dev/null +++ b/src/app/views/events/EditAddEventTypes/EventTypeDetails.jsx @@ -0,0 +1,185 @@ +import React, { useState, useEffect } from 'react'; +import { Button, Card, Grid, TextField, MenuItem, Checkbox, FormControlLabel } from '@material-ui/core'; +import { Formik, Form } from 'formik'; +import { Alert, AlertTitle } from '@material-ui/lab'; +import * as Yup from 'yup'; +// import axios from 'axios'; +// import * as yup from 'yup'; +import PropTypes from 'prop-types'; +import Field from '../../../components/Field'; +import { schemas } from '../../../utils'; +import { getSession } from '../../../redux/actions/SessionActions'; + + +const eventypePropTypes = { + id: PropTypes.number, + slug: PropTypes.string, + name: PropTypes.string, + language: PropTypes.string, + onSubmit: PropTypes.func, + academy_owner: PropTypes.number, +}; + +const propTypes = { + onSubmit: PropTypes.func.isRequired, + eventype: PropTypes.shape(eventypePropTypes).isRequired, +}; + +const schema = Yup.object().shape({ + // academy: yup.number().required().positive().integer(), + // schedule: yup.number().required().positive().integer(), + slug: schemas.slug(), + name: schemas.name(), +}); + + + +const EventTypeDetails = ({ eventype, onSubmit }) => { + const [status, setStatus] = useState({ color: "", message: "" }); + const session = getSession(); + const academyOwner = session.academy.id; + const eventypeAcademyId = eventype.academy.id; + + useEffect(() => { + if (eventypeAcademyId !== academyOwner) { + setStatus({ color: "warning", message: `This Event Type is owned by another academy, you can not make changes to its basic information.` }); + } else { + ""; + } + }, [academyOwner]); + + return ( + + + {eventypeAcademyId !== academyOwner && ( + + {eventypePropTypes.id !== academyOwner + ? (<>{status.message}) + : ""} + + )} + + {eventype.private && ( + + + + This event type is private + + + + )} + + + { + onSubmit(values); + setSubmitting(false); + }} + > + + {eventypeAcademyId !== academyOwner ? ( + + + + + + ) : ( + ({ values, isSubmitting, setFieldValue, handleChange }) => ( +
+ + + + + + Language + + + { + setFieldValue('language', e.target.value); + }} + select + > + {['es', 'en'].map((item) => ( + + {item.toUpperCase()} + + ))} + + + + + } + label="Allow Shared Creation" + /> + +
+ +
+
+
+ ))} +
+
+ ) +}; + +EventTypeDetails.propTypes = propTypes; + +export default EventTypeDetails; diff --git a/src/app/views/events/EditAddEventTypes/JoinEvents.jsx b/src/app/views/events/EditAddEventTypes/JoinEvents.jsx new file mode 100644 index 00000000..d362ee38 --- /dev/null +++ b/src/app/views/events/EditAddEventTypes/JoinEvents.jsx @@ -0,0 +1,230 @@ +import React, { useState, useEffect } from 'react'; +import { Button, Card, Grid, Icon, IconButton, TextField } from '@material-ui/core'; +import Box from '@mui/material/Box'; +import Modal from '@mui/material/Modal'; +import { Formik, Form } from 'formik'; +import { Alert, AlertTitle } from '@material-ui/lab'; +import * as Yup from 'yup'; +// import axios from 'axios'; +// import * as yup from 'yup'; +import PropTypes from 'prop-types'; +import Field from '../../../components/Field'; +import { schemas } from '../../../utils'; +import { getSession } from '../../../redux/actions/SessionActions'; + + +const eventypePropTypes = { + id: PropTypes.number, + slug: PropTypes.string, + name: PropTypes.string, + academy_owner: PropTypes.number, +}; + +const propTypes = { + onSubmit: PropTypes.func.isRequired, + eventype: PropTypes.shape(eventypePropTypes).isRequired, +}; + +const schema = Yup.object().shape({ + // academy: yup.number().required().positive().integer(), + // schedule: yup.number().required().positive().integer(), + slug: schemas.slug(), + name: schemas.name(), +}); + + + +const JoinEvents = ({ eventype, onSubmit }) => { + const [isLoading, setIsLoading] = useState(false); + const [openDialog, setOpenDialog] = useState(false); + const [hasMore, setHasMore] = useState(true); + + const session = getSession(); + const academyOwner = session.academy.id; + const eventypeAcademyId = eventype.academy.id; + const eventTypeVisbility = eventype.visibility_settings + + const [open, setOpen] = React.useState(false); + const handleOpen = () => setOpen(true); + const handleClose = () => setOpen(false); + + const style = { + position: 'absolute', + top: '50%', + left: '50%', + transform: 'translate(-50%, -50%)', + width: 400, + bgcolor: 'background.paper', + border: '2px solid #000', + boxShadow: 24, + p: 4, + }; + + return ( + + + + {eventype.private && ( + + + + This event type is private + + + + )} + + + { + onSubmit(values); + setSubmitting(false); + }} + > + + {eventypeAcademyId == academyOwner ? ( + <> +

Who can join these events?

+ +
+ {isLoading && } +
+ {eventTypeVisbility.length > 0 + ? eventTypeVisbility.map((s, i) => ( + ({ values, setFieldValue, handleChange }) => ( +
+ + + {visibility_settings.academy !== '' ? ( + + Everyone at the academy {value}. + + ) : ('')} + + {visibility_settings.syllabus !== '' ? ( + + Only students from {eventype.academy} with access to {value} syllabus. + + ) : ('')} + + {visibility_settings.cohort !== '' ? ( + + Only students from {eventype.academy} with access to {eventTypeVisbility.syllabus} syllabus from cohorts {value} + + ) : ('')} + + + + + add_circle + + + + +
+ + { + setFieldValue('academy', e.target.value); + }} + select + > + {['', eventTypeVisbility.academy].map((item) => ( + + {item.toUpperCase()} + + ))} + + { + setFieldValue('cohort', e.target.value); + }} + select + > + {['', eventTypeVisbility.cohort].map((item) => ( + + {item.toUpperCase()} + + ))} + + { + setFieldValue('syllabus', e.target.value); + }} + select + > + {['', eventTypeVisbility.syllabus].map((item) => ( + + {item.toUpperCase()} + + ))} + + +
+
+
+
+
+ ))) : ( +
There are no shared settings
+ )} +
+
+
+ + ) : ( + <> +

There are no shared settings

+ )} +
+ +
+ ) +}; + +JoinEvents.propTypes = propTypes; + +export default JoinEvents; diff --git a/src/app/views/events/EditAddEventTypes/NewEventType.jsx b/src/app/views/events/EditAddEventTypes/NewEventType.jsx new file mode 100644 index 00000000..c0e9698c --- /dev/null +++ b/src/app/views/events/EditAddEventTypes/NewEventType.jsx @@ -0,0 +1,108 @@ +import React from 'react'; +import { Formik } from 'formik'; +import { + Grid, + Card, + Divider, + Button, +} from '@material-ui/core'; +import { useHistory } from 'react-router-dom'; +import * as Yup from 'yup'; +import bc from '../../../services/breathecode'; +import Field from '../../../components/Field'; +import { Breadcrumb } from '../../../../matx'; +import { schemas } from '../../../utils'; + +const schema = Yup.object().shape({ + // academy: yup.number().required().positive().integer(), + // schedule: yup.number().required().positive().integer(), + slug: schemas.slug(), + name: schemas.name(), + // schedule_type: Yup.mixed().oneOf(scheduleTypes).required(), +}); + +const NewSyllabus = () => { + const history = useHistory(); + + const addEventType = async (values, { setSubmitting }) => { + try { + const response = await bc.events().addAcademyEventType(values); + if (response.status === 201) { + setSubmitting(false); + history.push('/events/academy/eventype'); + } + } catch (error) { + console.error(error); + } + }; + + return ( +
+
+ +
+ + +
+

Add a New Event Type

+
+ + + + {({ + handleSubmit, isSubmitting, + }) => ( +
+ + + + + + +
+ +
+
+ )} +
+
+
+ ); +}; + +export default NewSyllabus; diff --git a/src/app/views/events/EditAddEventTypes/index.jsx b/src/app/views/events/EditAddEventTypes/index.jsx new file mode 100644 index 00000000..2f888400 --- /dev/null +++ b/src/app/views/events/EditAddEventTypes/index.jsx @@ -0,0 +1,131 @@ +import React, { useState, useEffect } from 'react'; +import { + Dialog, + Icon, + Button, + Grid, + DialogTitle, + DialogActions, + DialogContent, + DialogContentText, +} from '@material-ui/core'; +import dayjs from 'dayjs'; +import { useParams } from 'react-router-dom'; +import { toast } from 'react-toastify'; +import bc from '../../../services/breathecode'; +import EventTypeDetails from './EventTypeDetails'; +import JoinEvents from './JoinEvents'; +import DowndownMenu from '../../../components/DropdownMenu'; +import { Breadcrumb } from '../../../../matx'; +import { MatxLoading } from '../../../../matx'; +import ConfirmAlert from '../../../components/ConfirmAlert'; +import { getSession } from '../../../redux/actions/SessionActions'; + +toast.configure(); +const toastOption = { + position: toast.POSITION.BOTTOM_RIGHT, + autoClose: 8000, +}; + +// TODO: this require in this context is weird +const LocalizedFormat = require('dayjs/plugin/localizedFormat'); + +dayjs.extend(LocalizedFormat); + +const Student = () => { + const { slug } = useParams(); + const session = getSession(); + const [eventype, setEventype] = useState(null); + const [openDialog, setOpenDialog] = useState(false); + const [makePublicDialog, setMakePublicDialog] = useState(false); + const [isLoading, setIsLoading] = useState(false); + + const options = [ + { label: `Make ${eventype?.private ? 'public' : 'private'}`, value: 'make_public' }, + { label: 'Edit Event Type Content', value: 'edit_eventype' }, + ]; + + const fetchEventype = async () => { + try { + const response = await bc.events().getAcademyEventTypeSlug(slug); + setEventype(response.data); + } catch (error) { + console.error(error); + return false; + } + return true; + }; + + useEffect(() => { + setIsLoading(true); + const fetchEventypePromise = fetchEventype(); + fetchEventypePromise.then(() => setIsLoading(false)); + }, []); + + const updateEventype = async (values) => { + try { + await bc.events().updateAcademyEventTypeSlug(slug, values); + fetchEventype(); + } catch (error) { + console.error(error); + } + }; + + const onAccept = () => updateEventype({ private: !eventype.private }); + + return ( +
+
+ {isLoading && } + {/* This Dialog opens the modal to delete the user in the cohort */} + setOpenDialog(false)} + aria-labelledby="alert-dialog-title" + aria-describedby="alert-dialog-description" + > + +
+
+ +
+

+ {eventype?.slug} +

+
+ { + if (value === 'edit_eventtype') { + window.open(`https://eventype.4geeks.com/?academy=${academy.id}&events/?eventype=${eventype?.slug}&token=${session.token}`, '_blank'); + } else if (value === 'make_public') { + setMakePublicDialog(true); + } + }} + > + +
+ + {eventype ? ( + + + + + + + + + + ) : ''} + +
+ ); +}; + +export default Student; diff --git a/src/app/views/events/events.jsx b/src/app/views/events/events.jsx index dff82a9c..263a1942 100644 --- a/src/app/views/events/events.jsx +++ b/src/app/views/events/events.jsx @@ -46,10 +46,6 @@ const EventList = () => { const [items, setItems] = useState([]); const thisURL = `https://breathecode.herokuapp.com/v1/events/ical/events?academy=${session.academy.id}`; - - const [openDialog, setOpenDialog] = useState(false); - const [url, setUrl] = useState(''); - const columns = [ { name: 'id', // field name in the row object @@ -229,7 +225,6 @@ const EventList = () => { search={async (querys) => { const { data } = await bc.events().getAcademyEvents(querys); setItems(data.results); - console.log(data) return data; }} deleting={async (querys) => { diff --git a/src/app/views/events/eventtypes.jsx b/src/app/views/events/eventtypes.jsx index 9e0e805f..e14e7ca4 100644 --- a/src/app/views/events/eventtypes.jsx +++ b/src/app/views/events/eventtypes.jsx @@ -2,11 +2,22 @@ import React, { useState } from 'react'; import { Icon, IconButton, - Button + Button, + Card, +Tooltip , + Grid, + DialogTitle, + Dialog, + DialogActions, + DialogContent, + TextField, + InputAdornment, } from '@material-ui/core'; import A from '@material-ui/core/Link'; +import ReactCountryFlag from "react-country-flag" import { Link } from 'react-router-dom'; import dayjs from 'dayjs'; +import { createTheme } from '@material-ui/core/styles'; import { toast } from 'react-toastify'; import { Breadcrumb } from '../../../matx'; import { getSession } from '../../redux/actions/SessionActions'; @@ -23,15 +34,11 @@ const relativeTime = require('dayjs/plugin/relativeTime'); dayjs.extend(relativeTime); -const EventList = () => { +const EventTypeList = () => { const session = getSession(); const [items, setItems] = useState([]); - const thisURL = `https://breathecode.herokuapp.com/v1/events/academy/eventype`; - - const [openDialog, setOpenDialog] = useState(false); - const columns = [ { name: 'name', // field name in the row object @@ -91,7 +98,7 @@ const EventList = () => {
{ customBodyRenderLite: (dataIndex) => (
- + edit @@ -128,13 +135,13 @@ const EventList = () => {
- +
@@ -147,12 +154,11 @@ const EventList = () => { columns={columns} items={items} view="event?" - historyReplace="/events/eventtypes" + historyReplace="/events/eventype" singlePage="" search={async (querys) => { const { data } = await bc.events().getAcademyEventType(querys); - setItems(data.results); - console.log('data', data) + setItems(data); return data; }} deleting={async (querys) => { @@ -167,4 +173,4 @@ const EventList = () => { ); }; -export default EventList; +export default EventTypeList; diff --git a/src/app/views/events/forms/EventForm.jsx b/src/app/views/events/forms/EventForm.jsx index 9dd9f7f5..421bd773 100644 --- a/src/app/views/events/forms/EventForm.jsx +++ b/src/app/views/events/forms/EventForm.jsx @@ -66,6 +66,7 @@ const EventForm = () => { if (data.slug) setSlug(data.slug); if (data.event_type) setEventType({ ...data.event_type, academy: data.academy }); if (data.venue) setVenue({ ...data.venue }); + if (data.description) setVenue({ ...data.description }); }) .catch((error) => error); @@ -421,7 +422,7 @@ const EventForm = () => { )} /> - Manage Event Types + Manage Event Types Event Description diff --git a/src/app/views/events/routes.js b/src/app/views/events/routes.js index 4901a2ed..b41eb9e8 100644 --- a/src/app/views/events/routes.js +++ b/src/app/views/events/routes.js @@ -28,10 +28,15 @@ const routes = [ component: React.lazy(() => import('./attendees')), }, { - path: '/events/type/list', + path: '/events/eventype', exact: true, component: React.lazy(() => import('./eventtypes')), }, + { + path: '/events/eventype/:slug', + exact: true, + component: React.lazy(() => import('./EditAddEventTypes/index')), + }, ]; export default routes; From 708ec90d94ed810751b4fac6de3bd191138a7b72 Mon Sep 17 00:00:00 2001 From: Roberto Lopez J Date: Tue, 14 Feb 2023 22:59:11 +0000 Subject: [PATCH 03/29] [Made all changes, still working on it] --- .../EditAddEventTypes/EventTypeDetails.jsx | 47 +-- .../events/EditAddEventTypes/JoinEvents.jsx | 309 +++++++++--------- .../events/EditAddEventTypes/NewEventType.jsx | 97 ++++-- .../views/events/EditAddEventTypes/index.jsx | 17 +- src/app/views/events/events.jsx | 2 +- src/app/views/events/eventtypes.jsx | 23 +- src/app/views/events/routes.js | 5 + 7 files changed, 279 insertions(+), 221 deletions(-) diff --git a/src/app/views/events/EditAddEventTypes/EventTypeDetails.jsx b/src/app/views/events/EditAddEventTypes/EventTypeDetails.jsx index 4fc91c18..8c2160bf 100644 --- a/src/app/views/events/EditAddEventTypes/EventTypeDetails.jsx +++ b/src/app/views/events/EditAddEventTypes/EventTypeDetails.jsx @@ -96,7 +96,7 @@ const EventTypeDetails = ({ eventype, onSubmit }) => { @@ -120,31 +120,32 @@ const EventTypeDetails = ({ eventype, onSubmit }) => { type="text" label="Description" name="description" - placeholder="12345" + placeholder="This is a description" required /> - Language - - - { - setFieldValue('language', e.target.value); - }} - select - > - {['es', 'en'].map((item) => ( - - {item.toUpperCase()} - - ))} - + Language + + + { + setFieldValue('lang', e.target.value); + }} + select + > + {['es', 'en'].map((item) => ( + + {item?.toUpperCase()} + + ))} + { const [isLoading, setIsLoading] = useState(false); - const [openDialog, setOpenDialog] = useState(false); - const [hasMore, setHasMore] = useState(true); - - const session = getSession(); - const academyOwner = session.academy.id; - const eventypeAcademyId = eventype.academy.id; - const eventTypeVisbility = eventype.visibility_settings - - const [open, setOpen] = React.useState(false); + const eventTypeVisbility = eventype.visibility_settings[0] const handleOpen = () => setOpen(true); const handleClose = () => setOpen(false); + const [syllabus, setSyllabus] = useState(null); + + const [open, setOpen] = React.useState(false); const style = { position: 'absolute', @@ -60,6 +57,8 @@ const JoinEvents = ({ eventype, onSubmit }) => { p: 4, }; + + return ( @@ -75,153 +74,153 @@ const JoinEvents = ({ eventype, onSubmit }) => { )} - { - onSubmit(values); - setSubmitting(false); - }} - > - - {eventypeAcademyId == academyOwner ? ( - <> -

Who can join these events?

- -
- {isLoading && } -
- {eventTypeVisbility.length > 0 - ? eventTypeVisbility.map((s, i) => ( - ({ values, setFieldValue, handleChange }) => ( -
- - - {visibility_settings.academy !== '' ? ( - - Everyone at the academy {value}. - - ) : ('')} - - {visibility_settings.syllabus !== '' ? ( - - Only students from {eventype.academy} with access to {value} syllabus. - - ) : ('')} - - {visibility_settings.cohort !== '' ? ( - - Only students from {eventype.academy} with access to {eventTypeVisbility.syllabus} syllabus from cohorts {value} - - ) : ('')} - - - - - add_circle - - - +

Who can join these events?

+ + +
+ + {isLoading && } + +
+ <> + {eventTypeVisbility != null ? eventype.visibility_settings.map((visibility, i) => ( + +
+ + + +
+ {!visibility?.academy ? '' : `Everyone at the academy ${visibility?.academy.name}`} +
+
+ +
+ {!visibility?.academy + || !visibility?.syllabus ? '' + : `Only students from ${visibility.academy.name} with access to ${visibility.syllabus.name} syllabus.`} +
+
+ + +
+ {!visibility?.academy + || !visibility?.syllabus + || visibility?.cohort + ? '' : `From cohort ${visibility?.cohort.name}`} +
+
+
+ +
+ + { + onSubmit(values); + setSubmitting(false); + }} + > + + + + { + handleOpen() + }}> + + add_circle + + + {({ values, isSubmitting, handleChange, handleSubmit, setFieldValue }) => ( + +
+ - { - setFieldValue('academy', e.target.value); - }} - select - > - {['', eventTypeVisbility.academy].map((item) => ( - - {item.toUpperCase()} - - ))} - - { - setFieldValue('cohort', e.target.value); - }} - select - > - {['', eventTypeVisbility.cohort].map((item) => ( - - {item.toUpperCase()} - - ))} - - { - setFieldValue('syllabus', e.target.value); - }} - select - > - {['', eventTypeVisbility.syllabus].map((item) => ( - - {item.toUpperCase()} - - ))} - + + + Syllabus + + + +
+ setSyllabus(x)} + width="100%" + className="m-4" + asyncSearch={() => bc.admissions().getAllSyllabus()} + size="small" + data-cy="syllabus" + label="syllabus" + required + getOptionLabel={(option) => `${option.name}`} + value={syllabus} + /> + {syllabus ? ( + setVersion(v)} + width="30%" + key={syllabus.slug} + asyncSearch={() => + bc.admissions().getAllCourseSyllabus(syllabus.slug) + } + size="small" + data-cy="version" + label="Version" + required + getOptionLabel={(option) => + option.status === "PUBLISHED" + ? `${option.version}` + : "⚠️ " + + option.version + + " (" + + option.status + + ")" + } + value={version} + /> + ) : ( + "" + )} +
+
+ + Cohort +
+
+ +
-
-
-
- ))) : ( -
There are no shared settings
+ + + )} -
-
-
- - ) : ( - <> -

There are no shared settings

- )} - - - +
+ +
+ + )) : ( +
There are no shared settings
+ )} + +
+ +
+
+
) }; diff --git a/src/app/views/events/EditAddEventTypes/NewEventType.jsx b/src/app/views/events/EditAddEventTypes/NewEventType.jsx index c0e9698c..c6b6be51 100644 --- a/src/app/views/events/EditAddEventTypes/NewEventType.jsx +++ b/src/app/views/events/EditAddEventTypes/NewEventType.jsx @@ -1,17 +1,22 @@ import React from 'react'; -import { Formik } from 'formik'; import { Grid, Card, + TextField, + MenuItem, + FormControlLabel, + Checkbox, Divider, Button, } from '@material-ui/core'; import { useHistory } from 'react-router-dom'; import * as Yup from 'yup'; +import { Formik, Form } from 'formik'; import bc from '../../../services/breathecode'; import Field from '../../../components/Field'; import { Breadcrumb } from '../../../../matx'; import { schemas } from '../../../utils'; +import { getSession } from '../../../redux/actions/SessionActions'; const schema = Yup.object().shape({ // academy: yup.number().required().positive().integer(), @@ -21,15 +26,17 @@ const schema = Yup.object().shape({ // schedule_type: Yup.mixed().oneOf(scheduleTypes).required(), }); -const NewSyllabus = () => { +const NewEventype = () => { const history = useHistory(); + const session = getSession(); const addEventType = async (values, { setSubmitting }) => { try { - const response = await bc.events().addAcademyEventType(values); + const response = await bc.events().addAcademyEventType({...values, academy: session.academy.id}); + console.log(session.academy) if (response.status === 201) { setSubmitting(false); - history.push('/events/academy/eventype'); + history.push('/events/eventype'); } } catch (error) { console.error(error); @@ -39,12 +46,10 @@ const NewSyllabus = () => { return (
-
@@ -60,15 +65,20 @@ const NewSyllabus = () => { onSubmit={addEventType} > {({ - handleSubmit, isSubmitting, + values, setFieldValue, isSubmitting, handleChange }) => ( -
+ + { type="text" label="Description" name="description" - placeholder="12345" - required - /> - + + Language + + + { + setFieldValue('lang', e.target.value); + }} + select + > + {['','es', 'en'].map((item) => ( + + {item.toUpperCase()} + + ))} + + + + + } + label="Allow Shared Creation" + /> + +
+ +
-
- -
-
+ )} @@ -105,4 +146,4 @@ const NewSyllabus = () => { ); }; -export default NewSyllabus; +export default NewEventype; diff --git a/src/app/views/events/EditAddEventTypes/index.jsx b/src/app/views/events/EditAddEventTypes/index.jsx index 2f888400..47e1f5b9 100644 --- a/src/app/views/events/EditAddEventTypes/index.jsx +++ b/src/app/views/events/EditAddEventTypes/index.jsx @@ -32,14 +32,22 @@ const LocalizedFormat = require('dayjs/plugin/localizedFormat'); dayjs.extend(LocalizedFormat); -const Student = () => { +const Eventtype = () => { const { slug } = useParams(); const session = getSession(); const [eventype, setEventype] = useState(null); + const [openDialog, setOpenDialog] = useState(false); const [makePublicDialog, setMakePublicDialog] = useState(false); const [isLoading, setIsLoading] = useState(false); +// const howManyDaysAgo = () => { +// if (!eventype) return 0; + // return dayjs().diff(eventype.created_at, 'days'); + +// }; + + const options = [ { label: `Make ${eventype?.private ? 'public' : 'private'}`, value: 'make_public' }, { label: 'Edit Event Type Content', value: 'edit_eventype' }, @@ -64,6 +72,7 @@ const Student = () => { const updateEventype = async (values) => { try { + values.academy = values.academy.id await bc.events().updateAcademyEventTypeSlug(slug, values); fetchEventype(); } catch (error) { @@ -98,7 +107,7 @@ const Student = () => { icon="more_horiz" onSelect={({ value }) => { if (value === 'edit_eventtype') { - window.open(`https://eventype.4geeks.com/?academy=${academy.id}&events/?eventype=${eventype?.slug}&token=${session.token}`, '_blank'); + window.open(`https://eventype.4geeks.com/?academy=${session.academy.id}&events/?eventype=${eventype?.slug}&token=${session.token}`, '_blank'); } else if (value === 'make_public') { setMakePublicDialog(true); } @@ -113,9 +122,11 @@ const Student = () => { + + ) : ''} { ); }; -export default Student; +export default Eventtype; diff --git a/src/app/views/events/events.jsx b/src/app/views/events/events.jsx index 263a1942..3eab59eb 100644 --- a/src/app/views/events/events.jsx +++ b/src/app/views/events/events.jsx @@ -45,7 +45,7 @@ const EventList = () => { const [items, setItems] = useState([]); - const thisURL = `https://breathecode.herokuapp.com/v1/events/ical/events?academy=${session.academy.id}`; + const thisURL = `https://breathecode.herokuapp.com/v1/events/ical/events?academy=${session.academy.id}&allow_shared_creation=true`; const columns = [ { name: 'id', // field name in the row object diff --git a/src/app/views/events/eventtypes.jsx b/src/app/views/events/eventtypes.jsx index e14e7ca4..3cd65812 100644 --- a/src/app/views/events/eventtypes.jsx +++ b/src/app/views/events/eventtypes.jsx @@ -17,7 +17,6 @@ import A from '@material-ui/core/Link'; import ReactCountryFlag from "react-country-flag" import { Link } from 'react-router-dom'; import dayjs from 'dayjs'; -import { createTheme } from '@material-ui/core/styles'; import { toast } from 'react-toastify'; import { Breadcrumb } from '../../../matx'; import { getSession } from '../../redux/actions/SessionActions'; @@ -80,6 +79,12 @@ const EventTypeList = () => { {item?.description} +
@@ -88,8 +93,8 @@ const EventTypeList = () => { }, }, { - name: 'language', // field name in the row object - label: 'Language', // column title that will be shown in table + name: 'academy', // field name in the row object + label: 'Academy', // column title that will be shown in table options: { filter: true, customBodyRenderLite: (dataIndex) => { @@ -97,12 +102,9 @@ const EventTypeList = () => { return (
- + + {item?.academy.name} +
@@ -137,9 +139,8 @@ const EventTypeList = () => {
-
- + diff --git a/src/app/views/events/routes.js b/src/app/views/events/routes.js index b41eb9e8..5b7c76fd 100644 --- a/src/app/views/events/routes.js +++ b/src/app/views/events/routes.js @@ -37,6 +37,11 @@ const routes = [ exact: true, component: React.lazy(() => import('./EditAddEventTypes/index')), }, + { + path: '/events/NewEventType', + exact: true, + component: React.lazy(() => import('./EditAddEventTypes/NewEventType')), + }, ]; export default routes; From 0f9430d5fd7fa0b22be8ad86b7bcf65246dd1c75 Mon Sep 17 00:00:00 2001 From: Roberto Lopez J Date: Wed, 15 Feb 2023 00:02:22 +0000 Subject: [PATCH 04/29] [Added the Modal inside EventypeDetails] --- .../events/EditAddEventTypes/JoinEvents.jsx | 229 +++++++++--------- .../events/EditAddEventTypes/NewEventType.jsx | 7 +- src/app/views/events/forms/EventForm.jsx | 5 +- 3 files changed, 121 insertions(+), 120 deletions(-) diff --git a/src/app/views/events/EditAddEventTypes/JoinEvents.jsx b/src/app/views/events/EditAddEventTypes/JoinEvents.jsx index 51eb9f75..d31d0857 100644 --- a/src/app/views/events/EditAddEventTypes/JoinEvents.jsx +++ b/src/app/views/events/EditAddEventTypes/JoinEvents.jsx @@ -73,6 +73,93 @@ const JoinEvents = ({ eventype, onSubmit }) => { )} + { + onSubmit(values); + setSubmitting(false); + }} + > + {({ values, isSubmitting, handleChange, handleSubmit, setFieldValue }) => ( + +
+ + + + + + + Syllabus + + + +
+ setSyllabus(x)} + width="100%" + className="m-4" + asyncSearch={() => bc.admissions().getAllSyllabus()} + size="small" + data-cy="syllabus" + label="syllabus" + required + getOptionLabel={(option) => `${option.name}`} + value={syllabus} + /> + {syllabus ? ( + setVersion(v)} + width="30%" + key={syllabus.slug} + asyncSearch={() => + bc.admissions().getAllCourseSyllabus(syllabus.slug) + } + size="small" + data-cy="version" + label="Version" + required + getOptionLabel={(option) => + option.status === "PUBLISHED" + ? `${option.version}` + : "⚠️ " + + option.version + + " (" + + option.status + + ")" + } + value={version} + /> + ) : ( + "" + )} +
+
+ + Cohort + +
+
+ +
+ +
+ + +
+ )} +
+

Who can join these events?

@@ -89,131 +176,49 @@ const JoinEvents = ({ eventype, onSubmit }) => { -
- {!visibility?.academy ? '' : `Everyone at the academy ${visibility?.academy.name}`} -
+
+ {!visibility?.academy ? '' : `Everyone at the academy` + `${visibility?.academy.name}`} +
- {!visibility?.academy - || !visibility?.syllabus ? '' - : `Only students from ${visibility.academy.name} with access to ${visibility.syllabus.name} syllabus.`} -
+ {!visibility?.academy + || !visibility?.syllabus ? '' + : `Only students from ${visibility.academy.name} with access to ${visibility.syllabus.name} syllabus.`} +
- {!visibility?.academy - || !visibility?.syllabus - || visibility?.cohort - ? '' : `From cohort ${visibility?.cohort.name}`} -
+ {!visibility?.academy + || !visibility?.syllabus + || visibility?.cohort + ? '' : `From cohort ${visibility?.cohort.name}`} +
- + { + handleOpen() + }}> + + add_circle + + - - { - onSubmit(values); - setSubmitting(false); - }} - > - - - - { - handleOpen() - }}> - - add_circle - - - {({ values, isSubmitting, handleChange, handleSubmit, setFieldValue }) => ( - -
- - - - - - - Syllabus - - - -
- setSyllabus(x)} - width="100%" - className="m-4" - asyncSearch={() => bc.admissions().getAllSyllabus()} - size="small" - data-cy="syllabus" - label="syllabus" - required - getOptionLabel={(option) => `${option.name}`} - value={syllabus} - /> - {syllabus ? ( - setVersion(v)} - width="30%" - key={syllabus.slug} - asyncSearch={() => - bc.admissions().getAllCourseSyllabus(syllabus.slug) - } - size="small" - data-cy="version" - label="Version" - required - getOptionLabel={(option) => - option.status === "PUBLISHED" - ? `${option.version}` - : "⚠️ " + - option.version + - " (" + - option.status + - ")" - } - value={version} - /> - ) : ( - "" - )} -
-
- - Cohort - -
-
- -
- -
- - -
- )} -
-
)) : ( -
There are no shared settings
+ <> +
There are no shared settings
+ + { + handleOpen() + }}> + + add_circle + + + )}
diff --git a/src/app/views/events/EditAddEventTypes/NewEventType.jsx b/src/app/views/events/EditAddEventTypes/NewEventType.jsx index c6b6be51..a1d8c402 100644 --- a/src/app/views/events/EditAddEventTypes/NewEventType.jsx +++ b/src/app/views/events/EditAddEventTypes/NewEventType.jsx @@ -69,12 +69,7 @@ const NewEventype = () => { }) => (
- + { if (!id) setSlug(slugify(title).toLowerCase()); }, [title]); + useEffect(() => { if (id) { bc.events() @@ -422,7 +423,7 @@ const EventForm = () => { )} /> - Manage Event Types + Manage Event Types Event Description From d1f04c686ac7e41c1d29ede53426b3526fb97fd8 Mon Sep 17 00:00:00 2001 From: Roberto Lopez J Date: Thu, 16 Feb 2023 00:28:37 +0000 Subject: [PATCH 05/29] [Simplified the JoinEvents file] --- .../events/EditAddEventTypes/JoinEvents.jsx | 228 +++++++++--------- 1 file changed, 111 insertions(+), 117 deletions(-) diff --git a/src/app/views/events/EditAddEventTypes/JoinEvents.jsx b/src/app/views/events/EditAddEventTypes/JoinEvents.jsx index d31d0857..815703c7 100644 --- a/src/app/views/events/EditAddEventTypes/JoinEvents.jsx +++ b/src/app/views/events/EditAddEventTypes/JoinEvents.jsx @@ -81,83 +81,83 @@ const JoinEvents = ({ eventype, onSubmit }) => { setSubmitting(false); }} > - {({ values, isSubmitting, handleChange, handleSubmit, setFieldValue }) => ( - - + {({ values, isSubmitting, handleChange, handleSubmit, setFieldValue }) => ( + + - - - + + + - - Syllabus - + + Syllabus + - -
+ +
+ setSyllabus(x)} + width="100%" + className="m-4" + asyncSearch={() => bc.admissions().getAllSyllabus()} + size="small" + data-cy="syllabus" + label="syllabus" + required + getOptionLabel={(option) => `${option.name}`} + value={syllabus} + /> + {syllabus ? ( setSyllabus(x)} - width="100%" className="m-4" - asyncSearch={() => bc.admissions().getAllSyllabus()} + debounced={false} + onChange={(v) => setVersion(v)} + width="30%" + key={syllabus.slug} + asyncSearch={() => + bc.admissions().getAllCourseSyllabus(syllabus.slug) + } size="small" - data-cy="syllabus" - label="syllabus" + data-cy="version" + label="Version" required - getOptionLabel={(option) => `${option.name}`} - value={syllabus} + getOptionLabel={(option) => + option.status === "PUBLISHED" + ? `${option.version}` + : "⚠️ " + + option.version + + " (" + + option.status + + ")" + } + value={version} /> - {syllabus ? ( - setVersion(v)} - width="30%" - key={syllabus.slug} - asyncSearch={() => - bc.admissions().getAllCourseSyllabus(syllabus.slug) - } - size="small" - data-cy="version" - label="Version" - required - getOptionLabel={(option) => - option.status === "PUBLISHED" - ? `${option.version}` - : "⚠️ " + - option.version + - " (" + - option.status + - ")" - } - value={version} - /> - ) : ( - "" - )} -
-
- - Cohort - + ) : ( + "" + )} +
+
+ + Cohort -
- -
- -
- - -
- )} +
+
+ +
+ + + + + + )} @@ -170,56 +170,50 @@ const JoinEvents = ({ eventype, onSubmit }) => {
<> - {eventTypeVisbility != null ? eventype.visibility_settings.map((visibility, i) => ( - -
- - - -
- {!visibility?.academy ? '' : `Everyone at the academy` + `${visibility?.academy.name}`} -
-
- -
- {!visibility?.academy - || !visibility?.syllabus ? '' - : `Only students from ${visibility.academy.name} with access to ${visibility.syllabus.name} syllabus.`} -
-
- - -
- {!visibility?.academy - || !visibility?.syllabus - || visibility?.cohort - ? '' : `From cohort ${visibility?.cohort.name}`} -
-
-
+ +
+ + {eventTypeVisbility != null ? eventype.visibility_settings.map((visibility, i) => ( + <> + + +
+ {!visibility?.academy ? '' : `Everyone at the academy ` + `${visibility?.academy.name}` + (i > 0 ? `, ${visibility[i + 1]?.academy.name}` : '')} +
+
+ +
+ {!visibility?.academy + || !visibility?.syllabus ? '' + : `Only students from ${visibility.academy.name} with access to ${visibility.syllabus.name} syllabus.`} +
+
+ + +
+ {!visibility?.academy + || !visibility?.syllabus + || visibility?.cohort + ? '' : `From cohort ${visibility?.cohort.name}`} +
+
+
+ + )) : ( + <> +
There are no shared settings
+ + )} { - handleOpen() - }}> - - add_circle - - -
-
-
- )) : ( - <> -
There are no shared settings
- - { - handleOpen() - }}> - - add_circle - - - - )} + handleOpen() + }}> + + add_circle + + +
+
+
From e7bb8eb590c6a8683a13a679be7ea162d9312f4c Mon Sep 17 00:00:00 2001 From: Roberto Lopez J Date: Fri, 17 Feb 2023 23:45:54 +0000 Subject: [PATCH 06/29] [Updates to eventtypes] --- .../EditAddEventTypes/EventTypeDetails.jsx | 17 +- .../events/EditAddEventTypes/JoinEvents.jsx | 299 +++++++++--------- .../events/EditAddEventTypes/NewEventType.jsx | 86 +++-- .../views/events/EditAddEventTypes/index.jsx | 46 ++- 4 files changed, 260 insertions(+), 188 deletions(-) diff --git a/src/app/views/events/EditAddEventTypes/EventTypeDetails.jsx b/src/app/views/events/EditAddEventTypes/EventTypeDetails.jsx index 8c2160bf..878687b9 100644 --- a/src/app/views/events/EditAddEventTypes/EventTypeDetails.jsx +++ b/src/app/views/events/EditAddEventTypes/EventTypeDetails.jsx @@ -83,14 +83,14 @@ const EventTypeDetails = ({ eventype, onSubmit }) => { { { + if (visibility && visibility?.academy && visibility?.syllabus) { + if (visibility.cohort) return <>Everyone at {visibility.academy.name} with access to {visibility.syllabus.name} syllabus, from cohort {visibility.cohort.name} + else return <>Everyone at {visibility.academy.name} with access to {visibility.syllabus.name} syllabus + } else if (visibility.cohort) return <>Everyone at {visibility.academy.name} from cohort {visibility.cohort.name} + else return <>Everyone at {visibility.academy.name} +} -const JoinEvents = ({ eventype, onSubmit }) => { +const JoinEvents = ({ eventype, onSubmit, openDialogDeleteVisibility, setOpenDialogDeleteVisibility, setVisibilitySetting }) => { const [isLoading, setIsLoading] = useState(false); - const eventTypeVisbility = eventype.visibility_settings[0] const handleOpen = () => setOpen(true); const handleClose = () => setOpen(false); + const [chooseCohort, setChooseCohort] = useState(null); + const [chooseAcademy, setChooseAcademy] = useState(null); const [syllabus, setSyllabus] = useState(null); - const [open, setOpen] = React.useState(false); const style = { @@ -57,169 +64,171 @@ const JoinEvents = ({ eventype, onSubmit }) => { p: 4, }; + return ( + <> +

Who can join these events?

+ - return ( + {eventype.private && ( + + + + This event type is private + + + + )} - - - {eventype.private && ( - - - - This event type is private - - - - )} - - { - onSubmit(values); - setSubmitting(false); - }} - > - {({ values, isSubmitting, handleChange, handleSubmit, setFieldValue }) => ( - -
- - - - + { + onSubmit(values); + setSubmitting(false); + }} + > + {({ values, isSubmitting, handleChange, handleSubmit, setFieldValue }) => ( + + + + + + - Syllabus - + Academy + -
- setSyllabus(x)} - width="100%" - className="m-4" - asyncSearch={() => bc.admissions().getAllSyllabus()} - size="small" - data-cy="syllabus" - label="syllabus" - required - getOptionLabel={(option) => `${option.name}`} - value={syllabus} - /> - {syllabus ? ( +
setVersion(v)} - width="30%" - key={syllabus.slug} - asyncSearch={() => - bc.admissions().getAllCourseSyllabus(syllabus.slug) - } + onChange={(x) => setChooseAcademy(x)} + width="100%" + className="m-4" + asyncSearch={() => bc.marketing().getAcademyAlias()} size="small" - data-cy="version" - label="Version" - required - getOptionLabel={(option) => - option.status === "PUBLISHED" - ? `${option.version}` - : "⚠️ " + - option.version + - " (" + - option.status + - ")" - } - value={version} + data-cy="academy" + label="academy" + + getOptionLabel={(option) => `${option.name}`} + value={chooseAcademy} /> - ) : ( - "" - )} -
- - - Cohort - - -
- -
- - - - - - )} - - - -

Who can join these events?

- - -
+
+
- {isLoading && } - -
- <> - -
- - {eventTypeVisbility != null ? eventype.visibility_settings.map((visibility, i) => ( - <> - - -
- {!visibility?.academy ? '' : `Everyone at the academy ` + `${visibility?.academy.name}` + (i > 0 ? `, ${visibility[i + 1]?.academy.name}` : '')} -
-
- -
- {!visibility?.academy - || !visibility?.syllabus ? '' - : `Only students from ${visibility.academy.name} with access to ${visibility.syllabus.name} syllabus.`} -
-
+ + Syllabus + + +
+ setSyllabus(x)} + width="100%" + className="m-4" + asyncSearch={() => bc.admissions().getAllSyllabus()} + size="small" + data-cy="syllabus" + label="syllabus" + + getOptionLabel={(option) => `${option.name}`} + value={syllabus} + /> +
+
+ + Cohort + + +
+ setChooseCohort(x)} + width="100%" + className="m-4" + asyncSearch={() => bc.admissions().getAllCohorts()} + size="small" + data-cy="cohort" + label="cohort" + + getOptionLabel={(option) => `${option.name}`} + value={chooseCohort} + /> +
+
+
+
+ +
+ + + + + + )} + + + + +
+ + {isLoading && } + +
+ <> + +
+ + + {eventype && eventype.visibility_settings && eventype.visibility_settings.length > 0 ? eventype.visibility_settings.map((visibility, i) => ( -
- {!visibility?.academy - || !visibility?.syllabus - || visibility?.cohort - ? '' : `From cohort ${visibility?.cohort.name}`} -
+ + {getVisibilitySettingMessage(visibility)} + + + { + setVisibilitySetting(visibility); + setOpenDialogDeleteVisibility(true); + }} + > + delete + +
-
- - )) : ( - <> -
There are no shared settings
- - )} - { + )) : ( + <> +
There are no shared settings
+ + )} + { handleOpen() }}> add_circle - -
-
- -
+ + +
+
+ +
-
- - +
+
+
+ ) }; diff --git a/src/app/views/events/EditAddEventTypes/NewEventType.jsx b/src/app/views/events/EditAddEventTypes/NewEventType.jsx index a1d8c402..3d3515fd 100644 --- a/src/app/views/events/EditAddEventTypes/NewEventType.jsx +++ b/src/app/views/events/EditAddEventTypes/NewEventType.jsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useState } from 'react'; import { Grid, Card, @@ -18,6 +18,8 @@ import { Breadcrumb } from '../../../../matx'; import { schemas } from '../../../utils'; import { getSession } from '../../../redux/actions/SessionActions'; +const slugify = require('slugify'); + const schema = Yup.object().shape({ // academy: yup.number().required().positive().integer(), // schedule: yup.number().required().positive().integer(), @@ -29,10 +31,11 @@ const schema = Yup.object().shape({ const NewEventype = () => { const history = useHistory(); const session = getSession(); + const [name, setName] = useState('') const addEventType = async (values, { setSubmitting }) => { try { - const response = await bc.events().addAcademyEventType({...values, academy: session.academy.id}); + const response = await bc.events().addAcademyEventType({ ...values, academy: session.academy.id }); console.log(session.academy) if (response.status === 201) { setSubmitting(false); @@ -69,26 +72,63 @@ const NewEventype = () => { }) => (
- - - - + + Name + + + setName(e.target.value)} + required + /> + + + + Slug + + + + + + Description + + + + Language @@ -105,7 +145,7 @@ const NewEventype = () => { }} select > - {['','es', 'en'].map((item) => ( + {['', 'es', 'en'].map((item) => ( {item.toUpperCase()} diff --git a/src/app/views/events/EditAddEventTypes/index.jsx b/src/app/views/events/EditAddEventTypes/index.jsx index 47e1f5b9..9c5fedea 100644 --- a/src/app/views/events/EditAddEventTypes/index.jsx +++ b/src/app/views/events/EditAddEventTypes/index.jsx @@ -36,17 +36,18 @@ const Eventtype = () => { const { slug } = useParams(); const session = getSession(); const [eventype, setEventype] = useState(null); - const [openDialog, setOpenDialog] = useState(false); + const [openDialogDeleteVisibility, setOpenDialogDeleteVisibility] = useState(false); const [makePublicDialog, setMakePublicDialog] = useState(false); const [isLoading, setIsLoading] = useState(false); + const [visibilitySetting, setVisibilitySetting] = useState(null) -// const howManyDaysAgo = () => { -// if (!eventype) return 0; - // return dayjs().diff(eventype.created_at, 'days'); + // const howManyDaysAgo = () => { + // if (!eventype) return 0; + // return dayjs().diff(eventype.created_at, 'days'); + + // }; -// }; - const options = [ { label: `Make ${eventype?.private ? 'public' : 'private'}`, value: 'make_public' }, @@ -94,10 +95,31 @@ const Eventtype = () => { aria-describedby="alert-dialog-description" > + setOpenDialogDeleteVisibility(false)} + aria-labelledby="alert-dialog-title" + aria-describedby="alert-dialog-description" + > + + Are you sure you want to delete this Visibility Setting from the Event Type? + + + + + +
-
- -
+
+ +

{eventype?.slug}

@@ -119,12 +141,12 @@ const Eventtype = () => { {eventype ? ( - + - + - + From aec587aaf6df276fc24dcc14f614b290d8c77b3f Mon Sep 17 00:00:00 2001 From: Roberto Lopez J Date: Tue, 21 Feb 2023 17:31:15 +0000 Subject: [PATCH 07/29] [Finished Eventype pages] --- .../events/EditAddEventTypes/JoinEvents.jsx | 30 +++---------------- 1 file changed, 4 insertions(+), 26 deletions(-) diff --git a/src/app/views/events/EditAddEventTypes/JoinEvents.jsx b/src/app/views/events/EditAddEventTypes/JoinEvents.jsx index b9f1e199..108296d4 100644 --- a/src/app/views/events/EditAddEventTypes/JoinEvents.jsx +++ b/src/app/views/events/EditAddEventTypes/JoinEvents.jsx @@ -20,6 +20,7 @@ const eventypePropTypes = { slug: PropTypes.string, name: PropTypes.string, academy_owner: PropTypes.number, + visibility_settings: PropTypes.string, }; const schema = Yup.object().shape({ @@ -37,8 +38,8 @@ const propTypes = { const getVisibilitySettingMessage = (visibility) => { if (visibility && visibility?.academy && visibility?.syllabus) { - if (visibility.cohort) return <>Everyone at {visibility.academy.name} with access to {visibility.syllabus.name} syllabus, from cohort {visibility.cohort.name} - else return <>Everyone at {visibility.academy.name} with access to {visibility.syllabus.name} syllabus + if (visibility.cohort) return <>Everyone at {visibility.academy.name} with access to {visibility.syllabus.name} syllabus, from cohort {visibility.cohort.name} + else return <>Everyone at {visibility.academy.name} with access to {visibility.syllabus.name} syllabus } else if (visibility.cohort) return <>Everyone at {visibility.academy.name} from cohort {visibility.cohort.name} else return <>Everyone at {visibility.academy.name} } @@ -48,7 +49,6 @@ const JoinEvents = ({ eventype, onSubmit, openDialogDeleteVisibility, setOpenDia const handleOpen = () => setOpen(true); const handleClose = () => setOpen(false); const [chooseCohort, setChooseCohort] = useState(null); - const [chooseAcademy, setChooseAcademy] = useState(null); const [syllabus, setSyllabus] = useState(null); const [open, setOpen] = React.useState(false); @@ -88,7 +88,7 @@ const JoinEvents = ({ eventype, onSubmit, openDialogDeleteVisibility, setOpenDia setSubmitting(false); }} > - {({ values, isSubmitting, handleChange, handleSubmit, setFieldValue }) => ( + {({ values, isSubmitting, handleSubmit, setFieldValue }) => ( @@ -96,28 +96,6 @@ const JoinEvents = ({ eventype, onSubmit, openDialogDeleteVisibility, setOpenDia - - Academy - - - -
- setChooseAcademy(x)} - width="100%" - className="m-4" - asyncSearch={() => bc.marketing().getAcademyAlias()} - size="small" - data-cy="academy" - label="academy" - - getOptionLabel={(option) => `${option.name}`} - value={chooseAcademy} - /> -
-
- Syllabus From fba1a99d0dd41d886ee6b33901e103849c94d84f Mon Sep 17 00:00:00 2001 From: Roberto Lopez J Date: Tue, 21 Feb 2023 22:09:38 +0000 Subject: [PATCH 08/29] [commented out the trash and the + for eventypes] --- src/app/views/events/EditAddEventTypes/JoinEvents.jsx | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/app/views/events/EditAddEventTypes/JoinEvents.jsx b/src/app/views/events/EditAddEventTypes/JoinEvents.jsx index 108296d4..0e16a046 100644 --- a/src/app/views/events/EditAddEventTypes/JoinEvents.jsx +++ b/src/app/views/events/EditAddEventTypes/JoinEvents.jsx @@ -173,22 +173,29 @@ const JoinEvents = ({ eventype, onSubmit, openDialogDeleteVisibility, setOpenDia {getVisibilitySettingMessage(visibility)} +{/* + { setVisibilitySetting(visibility); setOpenDialogDeleteVisibility(true); }} > + delete + + */} )) : ( <>
There are no shared settings
)} + +{/* { handleOpen() }}> @@ -196,6 +203,8 @@ const JoinEvents = ({ eventype, onSubmit, openDialogDeleteVisibility, setOpenDia add_circle + */} +
From e078932e5034a4dc2d368b365a222334f5a11a01 Mon Sep 17 00:00:00 2001 From: Roberto Lopez J Date: Mon, 27 Feb 2023 18:52:24 +0000 Subject: [PATCH 09/29] [Made changes to names] --- .../EventTypeDetails.jsx | 0 .../{EditAddEventTypes => EventTypesForm}/NewEventType.jsx | 0 .../JoinEvents.jsx => EventTypesForm/ShareEventsCard.jsx} | 6 +++--- .../events/{EditAddEventTypes => EventTypesForm}/index.jsx | 2 +- src/app/views/events/events.jsx | 2 +- src/app/views/events/routes.js | 4 ++-- 6 files changed, 7 insertions(+), 7 deletions(-) rename src/app/views/events/{EditAddEventTypes => EventTypesForm}/EventTypeDetails.jsx (100%) rename src/app/views/events/{EditAddEventTypes => EventTypesForm}/NewEventType.jsx (100%) rename src/app/views/events/{EditAddEventTypes/JoinEvents.jsx => EventTypesForm/ShareEventsCard.jsx} (97%) rename src/app/views/events/{EditAddEventTypes => EventTypesForm}/index.jsx (99%) diff --git a/src/app/views/events/EditAddEventTypes/EventTypeDetails.jsx b/src/app/views/events/EventTypesForm/EventTypeDetails.jsx similarity index 100% rename from src/app/views/events/EditAddEventTypes/EventTypeDetails.jsx rename to src/app/views/events/EventTypesForm/EventTypeDetails.jsx diff --git a/src/app/views/events/EditAddEventTypes/NewEventType.jsx b/src/app/views/events/EventTypesForm/NewEventType.jsx similarity index 100% rename from src/app/views/events/EditAddEventTypes/NewEventType.jsx rename to src/app/views/events/EventTypesForm/NewEventType.jsx diff --git a/src/app/views/events/EditAddEventTypes/JoinEvents.jsx b/src/app/views/events/EventTypesForm/ShareEventsCard.jsx similarity index 97% rename from src/app/views/events/EditAddEventTypes/JoinEvents.jsx rename to src/app/views/events/EventTypesForm/ShareEventsCard.jsx index 0e16a046..9a35e5fd 100644 --- a/src/app/views/events/EditAddEventTypes/JoinEvents.jsx +++ b/src/app/views/events/EventTypesForm/ShareEventsCard.jsx @@ -44,7 +44,7 @@ const getVisibilitySettingMessage = (visibility) => { else return <>Everyone at {visibility.academy.name} } -const JoinEvents = ({ eventype, onSubmit, openDialogDeleteVisibility, setOpenDialogDeleteVisibility, setVisibilitySetting }) => { +const ShareEvents = ({ eventype, onSubmit, openDialogDeleteVisibility, setOpenDialogDeleteVisibility, setVisibilitySetting }) => { const [isLoading, setIsLoading] = useState(false); const handleOpen = () => setOpen(true); const handleClose = () => setOpen(false); @@ -219,6 +219,6 @@ const JoinEvents = ({ eventype, onSubmit, openDialogDeleteVisibility, setOpenDia ) }; -JoinEvents.propTypes = propTypes; +ShareEvents.propTypes = propTypes; -export default JoinEvents; +export default ShareEvents; diff --git a/src/app/views/events/EditAddEventTypes/index.jsx b/src/app/views/events/EventTypesForm/index.jsx similarity index 99% rename from src/app/views/events/EditAddEventTypes/index.jsx rename to src/app/views/events/EventTypesForm/index.jsx index 9c5fedea..428a7ede 100644 --- a/src/app/views/events/EditAddEventTypes/index.jsx +++ b/src/app/views/events/EventTypesForm/index.jsx @@ -14,7 +14,7 @@ import { useParams } from 'react-router-dom'; import { toast } from 'react-toastify'; import bc from '../../../services/breathecode'; import EventTypeDetails from './EventTypeDetails'; -import JoinEvents from './JoinEvents'; +import JoinEvents from './ShareEventsCard'; import DowndownMenu from '../../../components/DropdownMenu'; import { Breadcrumb } from '../../../../matx'; import { MatxLoading } from '../../../../matx'; diff --git a/src/app/views/events/events.jsx b/src/app/views/events/events.jsx index 3eab59eb..263a1942 100644 --- a/src/app/views/events/events.jsx +++ b/src/app/views/events/events.jsx @@ -45,7 +45,7 @@ const EventList = () => { const [items, setItems] = useState([]); - const thisURL = `https://breathecode.herokuapp.com/v1/events/ical/events?academy=${session.academy.id}&allow_shared_creation=true`; + const thisURL = `https://breathecode.herokuapp.com/v1/events/ical/events?academy=${session.academy.id}`; const columns = [ { name: 'id', // field name in the row object diff --git a/src/app/views/events/routes.js b/src/app/views/events/routes.js index 5b7c76fd..f9d7dc94 100644 --- a/src/app/views/events/routes.js +++ b/src/app/views/events/routes.js @@ -35,12 +35,12 @@ const routes = [ { path: '/events/eventype/:slug', exact: true, - component: React.lazy(() => import('./EditAddEventTypes/index')), + component: React.lazy(() => import('./EventTypesForm/index')), }, { path: '/events/NewEventType', exact: true, - component: React.lazy(() => import('./EditAddEventTypes/NewEventType')), + component: React.lazy(() => import('./EventTypesForm/NewEventType')), }, ]; From 9ca115573c6ea56d4c3769dca0ca2aa57066d3ee Mon Sep 17 00:00:00 2001 From: Roberto Lopez J Date: Mon, 27 Feb 2023 22:05:44 +0000 Subject: [PATCH 10/29] [Changed flag position & add an Avatar image] --- .../EventTypesForm/EventTypeDetails.jsx | 2 +- src/app/views/events/eventtypes.jsx | 47 ++++++++++++++++--- 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/src/app/views/events/EventTypesForm/EventTypeDetails.jsx b/src/app/views/events/EventTypesForm/EventTypeDetails.jsx index 878687b9..b0dbefd4 100644 --- a/src/app/views/events/EventTypesForm/EventTypeDetails.jsx +++ b/src/app/views/events/EventTypesForm/EventTypeDetails.jsx @@ -131,7 +131,7 @@ const EventTypeDetails = ({ eventype, onSubmit }) => { { label: 'Name', // column title that will be shown in table options: { filter: true, + customBodyRenderLite: (dataIndex) => { + const item = items[dataIndex]; + return ( +
+ +
+ + {item?.name} + + +
+
+
+ ); + }, }, }, { @@ -79,12 +100,6 @@ const EventTypeList = () => { {item?.description} -
@@ -112,6 +127,26 @@ const EventTypeList = () => { }, }, }, + { + name: 'icon_url', // field name in the row object + label: 'URL', // column title that will be shown in table + options: { + filter: true, + customBodyRenderLite: (dataIndex) => { + const item = items[dataIndex]; + return ( +
+
+ + {item?.icon_url} + +
+
+
+ ); + }, + }, + }, { name: 'action', label: ' ', From e3a0aae465712a64a9adef74356b861a9fe5c453 Mon Sep 17 00:00:00 2001 From: Roberto Lopez J Date: Tue, 28 Feb 2023 19:22:14 +0000 Subject: [PATCH 11/29] [Made final changes] --- src/app/views/events/eventtypes.jsx | 29 +++-------------------------- 1 file changed, 3 insertions(+), 26 deletions(-) diff --git a/src/app/views/events/eventtypes.jsx b/src/app/views/events/eventtypes.jsx index a8158d2f..d7b23586 100644 --- a/src/app/views/events/eventtypes.jsx +++ b/src/app/views/events/eventtypes.jsx @@ -49,18 +49,15 @@ const EventTypeList = () => { const item = items[dataIndex]; return (
-
- - {item?.name} - - -
+
{item?.name}
+
); @@ -127,26 +124,6 @@ const EventTypeList = () => { }, }, }, - { - name: 'icon_url', // field name in the row object - label: 'URL', // column title that will be shown in table - options: { - filter: true, - customBodyRenderLite: (dataIndex) => { - const item = items[dataIndex]; - return ( -
-
- - {item?.icon_url} - -
-
-
- ); - }, - }, - }, { name: 'action', label: ' ', From 23de318d9629d40268763750d3a2c1cdae85ea2c Mon Sep 17 00:00:00 2001 From: Roberto Lopez J Date: Thu, 9 Mar 2023 01:07:41 +0000 Subject: [PATCH 12/29] [Added US flags] --- src/app/views/events/eventtypes.jsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/app/views/events/eventtypes.jsx b/src/app/views/events/eventtypes.jsx index d7b23586..742d28fb 100644 --- a/src/app/views/events/eventtypes.jsx +++ b/src/app/views/events/eventtypes.jsx @@ -51,7 +51,11 @@ const EventTypeList = () => {
Date: Thu, 9 Mar 2023 01:14:15 +0000 Subject: [PATCH 13/29] [Changed flags to work] --- src/app/views/events/eventtypes.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/views/events/eventtypes.jsx b/src/app/views/events/eventtypes.jsx index 742d28fb..1c234994 100644 --- a/src/app/views/events/eventtypes.jsx +++ b/src/app/views/events/eventtypes.jsx @@ -53,7 +53,7 @@ const EventTypeList = () => { Date: Tue, 14 Mar 2023 18:50:39 +0000 Subject: [PATCH 14/29] [Added DE to languages] --- src/app/views/events/EventTypesForm/EventTypeDetails.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/views/events/EventTypesForm/EventTypeDetails.jsx b/src/app/views/events/EventTypesForm/EventTypeDetails.jsx index b0dbefd4..5518227e 100644 --- a/src/app/views/events/EventTypesForm/EventTypeDetails.jsx +++ b/src/app/views/events/EventTypesForm/EventTypeDetails.jsx @@ -141,7 +141,7 @@ const EventTypeDetails = ({ eventype, onSubmit }) => { }} select > - {['es', 'en'].map((item) => ( + {['es', 'en', 'de'].map((item) => ( {item?.toUpperCase()} From fc4a561d43280c0c059d995417e9bbfee96413c6 Mon Sep 17 00:00:00 2001 From: Roberto Lopez J Date: Tue, 14 Mar 2023 18:59:10 +0000 Subject: [PATCH 15/29] [Added languages] --- src/app/views/events/EventTypesForm/EventTypeDetails.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/views/events/EventTypesForm/EventTypeDetails.jsx b/src/app/views/events/EventTypesForm/EventTypeDetails.jsx index 5518227e..7eb6f014 100644 --- a/src/app/views/events/EventTypesForm/EventTypeDetails.jsx +++ b/src/app/views/events/EventTypesForm/EventTypeDetails.jsx @@ -141,7 +141,7 @@ const EventTypeDetails = ({ eventype, onSubmit }) => { }} select > - {['es', 'en', 'de'].map((item) => ( + {['es', 'en', 'de', 'it', 'br'].map((item) => ( {item?.toUpperCase()} From cab8647714bce7115960a7ff6e129fd1c90704e8 Mon Sep 17 00:00:00 2001 From: Roberto Lopez J Date: Wed, 15 Mar 2023 04:04:49 +0000 Subject: [PATCH 16/29] [Added filter and language] --- src/app/services/breathecode.js | 2 +- src/app/views/events/EventTypesForm/EventTypeDetails.jsx | 3 ++- src/utils.js | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/app/services/breathecode.js b/src/app/services/breathecode.js index 0bcb8f1c..378e0063 100644 --- a/src/app/services/breathecode.js +++ b/src/app/services/breathecode.js @@ -785,7 +785,7 @@ class BreatheCodeClient { getAcademyEventType: () => axios.bcGet( "Event Type", - `${this.host}/events/academy/eventype` + `${this.host}/events/academy/eventype?allow_shared_creation=true` ), getAcademyEventTypeSlug: (slug) => axios.bcGet( diff --git a/src/app/views/events/EventTypesForm/EventTypeDetails.jsx b/src/app/views/events/EventTypesForm/EventTypeDetails.jsx index 7eb6f014..9e127620 100644 --- a/src/app/views/events/EventTypesForm/EventTypeDetails.jsx +++ b/src/app/views/events/EventTypesForm/EventTypeDetails.jsx @@ -9,6 +9,7 @@ import PropTypes from 'prop-types'; import Field from '../../../components/Field'; import { schemas } from '../../../utils'; import { getSession } from '../../../redux/actions/SessionActions'; +import { availableLanguages } from 'utils'; const eventypePropTypes = { @@ -141,7 +142,7 @@ const EventTypeDetails = ({ eventype, onSubmit }) => { }} select > - {['es', 'en', 'de', 'it', 'br'].map((item) => ( + {Object.keys(availableLanguages).map((item) => ( {item?.toUpperCase()} diff --git a/src/utils.js b/src/utils.js index 355cb3cf..79e5e9d2 100644 --- a/src/utils.js +++ b/src/utils.js @@ -10,7 +10,7 @@ export const availableLanguages = { "us": "English", "es": "Spanish", "it": "Italian", - "ge": "German", + "de": "German", "po": "Portuguese", } dayjs.extend(tz); From 0217dfa47def29ebb167085605bf80b8c4ec67f5 Mon Sep 17 00:00:00 2001 From: Tomas Gonzalez <56565994+tommygonzaleza@users.noreply.github.com> Date: Mon, 27 Mar 2023 17:57:00 -0400 Subject: [PATCH 17/29] Update ComposeAsset.js --- src/app/views/media/components/ComposeAsset.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/views/media/components/ComposeAsset.js b/src/app/views/media/components/ComposeAsset.js index 3e3e4ba4..158e6c99 100644 --- a/src/app/views/media/components/ComposeAsset.js +++ b/src/app/views/media/components/ComposeAsset.js @@ -442,7 +442,7 @@ const ComposeAsset = () => { }} open={updateStatus} title="Select a status" - options={['UNASSIGNED', 'WRITING', 'DRAFT', 'PUBLISHED']} + options={['UNASSIGNED', 'WRITING', 'DRAFT', 'PUBLISHED', 'OPTIMIZED']} /> { From 585520f5c688c525a4ee4ebc44d79fb5869f3aea Mon Sep 17 00:00:00 2001 From: Tomas Gonzalez <56565994+tommygonzaleza@users.noreply.github.com> Date: Mon, 27 Mar 2023 18:32:11 -0400 Subject: [PATCH 18/29] Update ComposeAsset.js --- src/app/views/media/components/ComposeAsset.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/views/media/components/ComposeAsset.js b/src/app/views/media/components/ComposeAsset.js index 158e6c99..5e24656f 100644 --- a/src/app/views/media/components/ComposeAsset.js +++ b/src/app/views/media/components/ComposeAsset.js @@ -442,7 +442,7 @@ const ComposeAsset = () => { }} open={updateStatus} title="Select a status" - options={['UNASSIGNED', 'WRITING', 'DRAFT', 'PUBLISHED', 'OPTIMIZED']} + options={['UNASSIGNED', 'WRITING', 'DRAFT', 'OPTIMIZED', 'PUBLISHED']} /> { From b54f10c4db86adcf26412e5c800fad346e9b6cf2 Mon Sep 17 00:00:00 2001 From: Roberto Lopez J Date: Wed, 5 Apr 2023 01:20:02 +0000 Subject: [PATCH 19/29] [Made Allowed_shared Creation] --- .../views/events/EventTypesForm/EventTypeDetails.jsx | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/app/views/events/EventTypesForm/EventTypeDetails.jsx b/src/app/views/events/EventTypesForm/EventTypeDetails.jsx index 9e127620..97ee8b97 100644 --- a/src/app/views/events/EventTypesForm/EventTypeDetails.jsx +++ b/src/app/views/events/EventTypesForm/EventTypeDetails.jsx @@ -34,14 +34,18 @@ const schema = Yup.object().shape({ }); - const EventTypeDetails = ({ eventype, onSubmit }) => { + console.log('this is eventype', eventype) const [status, setStatus] = useState({ color: "", message: "" }); const session = getSession(); const academyOwner = session.academy.id; + const sessionAcademy = session.academy.slug; + const eventypeAcademy = eventype.academy.slug; const eventypeAcademyId = eventype.academy.id; + const [checked, setChecked] = useState(false); useEffect(() => { + if (eventypeAcademyId !== academyOwner) { setStatus({ color: "warning", message: `This Event Type is owned by another academy, you can not make changes to its basic information.` }); } else { @@ -154,8 +158,10 @@ const EventTypeDetails = ({ eventype, onSubmit }) => { control={ { + setFieldValue('allow_shared_creation', e.target.checked); + }} name="shared_creation" data-cy="shared_creation" color="primary" From 38dc73b539f1e12c4cb243a2c3e84620399bc6f4 Mon Sep 17 00:00:00 2001 From: Alejandro Sanchez Date: Mon, 10 Apr 2023 21:26:24 +0000 Subject: [PATCH 20/29] trying to create UI to add github org users directly --- src/app/navigations.js | 6 -- src/app/views/admin/gitpod.jsx | 177 --------------------------------- src/app/views/admin/routes.js | 5 - 3 files changed, 188 deletions(-) delete mode 100644 src/app/views/admin/gitpod.jsx diff --git a/src/app/navigations.js b/src/app/navigations.js index 7d1ec36e..7296e9ba 100644 --- a/src/app/navigations.js +++ b/src/app/navigations.js @@ -228,12 +228,6 @@ export const navigations = [ iconText: "STA", capabilities: ["read_invite"], }, - { - name: "Gitpod", - path: "/admin/gitpod", - iconText: "STA", - capabilities: ["get_gitpod_user"], - }, { name: "Github", path: "/admin/github", diff --git a/src/app/views/admin/gitpod.jsx b/src/app/views/admin/gitpod.jsx deleted file mode 100644 index 84c59692..00000000 --- a/src/app/views/admin/gitpod.jsx +++ /dev/null @@ -1,177 +0,0 @@ -import React, { useState } from 'react'; -import { Breadcrumb } from 'matx'; -import { SmartMUIDataTable } from 'app/components/SmartDataTable'; -import { - Avatar, - Icon, - IconButton, - Button, - Tooltip, -} from '@material-ui/core'; -import { Link } from 'react-router-dom'; -import dayjs from 'dayjs'; -import bc from 'app/services/breathecode'; -import InviteDetails from 'app/components/InviteDetails'; -const relativeTime = require('dayjs/plugin/relativeTime'); -dayjs.extend(relativeTime); - -const statusColors = { - expired: 'text-white bg-error', - soon: 'text-white bg-warning', - ok: 'text-white bg-green', -}; -const roleColors = { - admin: 'text-black bg-gray', -}; - -const name = (user) => { - let _name = "" - if (user && user.first_name && user.first_name !== '') _name = user.first_name; - if (user && user.last_name && user.last_name !== '') _name += " " + user.last_name; - if (_name === "") _name = 'No name'; - return _name; -}; - -const GitpodUsers = () => { - const [userList, setUserList] = useState([]); - - const columns = [ - { - name: 'github', // field name in the row object - label: 'Github', // column title that will be shown in table - options: { - filter: true, - customBodyRenderLite: (dataIndex) => { - const { github_username, user, academy, cohort } = userList.results[dataIndex]; - return ( -
- -
-
{github_username}
- {cohort ? cohort.name : academy ? academy.name : "No academy or cohort"} -
-
- ); - }, - }, - }, - { - name: 'user', // field name in the row object - label: 'User', // column title that will be shown in table - options: { - filter: true, - customBodyRenderLite: (dataIndex) => { - const { github_username, user } = userList.results[dataIndex]; - return ( -
-
- -
{user ? name(user) : "No user found"}
- - {user?.email} -
-
- ); - }, - }, - }, - { - name: 'expires_at', - label: 'Expires At', - options: { - filter: true, - customBodyRenderLite: (i) => { - let now = dayjs() - let stage = 'ok' - let item = userList.results[i] - if(dayjs(item.expires_at).isBefore(now)) stage = 'expired'; - else if(dayjs(item.expires_at).isBefore(now.add(3,'days'))) stage = 'soon'; - return
-
-
-
{item.expires_at ? dayjs(item.expires_at).format('MM-DD-YYYY') : "Never"}
- {item.expires_at && {dayjs(item.expires_at).fromNow()}} -
-
-
- }, - }, - }, - { - name: 'assignee_id', - label: 'Gitpod ID', - options: { - filter: true, - customBodyRenderLite: (dataIndex) => { - const item = userList.results[dataIndex]; - return ( - - {item.assignee_id} - - ); - }, - }, - }, - { - name: 'action', - label: ' ', - options: { - filter: false, - customBodyRenderLite: (dataIndex) => { - const item = userList.results[dataIndex] - return (item.academy ?
- - bc.auth().updateGitpodUser(item.id, { expires_at: dayjs().subtract(1,'day') })}> - alarm_off - - - - bc.auth().updateGitpodUser(item.id, { expires_at: dayjs().add(14,'day') })}> - alarm_add - - - - bc.auth().updateGitpodUser(item.id, { expires_at: null })}> - refresh - - -
- : -
No matching student found
- ); - }, - }, - }, - ]; - - return ( -
-
-
-
- -
-
-
-
- { - const { data } = await bc.auth().getGitpodUsers(querys); - setUserList(data); - return data; - }} - /> -
-
- ); -}; - -export default GitpodUsers; diff --git a/src/app/views/admin/routes.js b/src/app/views/admin/routes.js index 9b2959f9..6f8c2c19 100644 --- a/src/app/views/admin/routes.js +++ b/src/app/views/admin/routes.js @@ -21,11 +21,6 @@ const routes = [ exact: true, component: React.lazy(() => import("./invites")), }, - { - path: "/admin/gitpod", - exact: true, - component: React.lazy(() => import("./gitpod")), - }, { path: "/admin/github", exact: true, From 5f568f4ad6e20e60d6dd8226d0bfd9e2faaf5597 Mon Sep 17 00:00:00 2001 From: Alejandro Sanchez Date: Mon, 10 Apr 2023 23:58:18 +0000 Subject: [PATCH 21/29] added devcontainers --- .devcontainer/devcontainer.json | 22 ++++++++++++++++++++++ .gitignore | 2 ++ 2 files changed, 24 insertions(+) create mode 100644 .devcontainer/devcontainer.json diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 00000000..00061eae --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,22 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the +// README at: https://github.com/devcontainers/templates/tree/main/src/javascript-node +{ + "name": "Node.js", + // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile + "image": "mcr.microsoft.com/devcontainers/javascript-node:0-16", + + // Features to add to the dev container. More info: https://containers.dev/features. + // "features": {}, + + // Use 'forwardPorts' to make a list of ports inside the container available locally. + // "forwardPorts": [], + + // Use 'postCreateCommand' to run commands after the container is created. + "postCreateCommand": "cp .env.example .env && touch /tmp/.npm-lock && npm install --legacy-peer-deps && rm /tmp/.npm-lock", + + // Configure tool-specific properties. + // "customizations": {}, + + // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. + // "remoteUser": "root" +} diff --git a/.gitignore b/.gitignore index 92975bd7..ceb7ae9a 100644 --- a/.gitignore +++ b/.gitignore @@ -30,6 +30,8 @@ yarn-error.log* # Don't ignore gitpod files !.gitignore +!.devcontainer/* +!.devcontainer !.gitpod.yml !.gitpod.Dockerfile !.husky From 6a6782825123e0b5aa0f12dee599071f9639ae5e Mon Sep 17 00:00:00 2001 From: Alejandro Sanchez Date: Tue, 11 Apr 2023 21:15:01 +0000 Subject: [PATCH 22/29] you can now add users to the github organization from your admin --- src/app/services/breathecode.js | 7 ++ .../admin/github-form/OrganizationUsers.jsx | 23 ++++- .../admin/github-form/PickCohortUserModal.jsx | 95 +++++++++++++++++++ src/app/views/admin/github.jsx | 5 +- src/index.css | 3 + 5 files changed, 129 insertions(+), 4 deletions(-) create mode 100644 src/app/views/admin/github-form/PickCohortUserModal.jsx diff --git a/src/app/services/breathecode.js b/src/app/services/breathecode.js index ee63b146..2a4d3597 100644 --- a/src/app/services/breathecode.js +++ b/src/app/services/breathecode.js @@ -343,6 +343,13 @@ class BreatheCodeClient { payload ); }, + addGithubUser: (payload) => { + return axios.bcPost( + "Invite", + `${this.host}/auth/academy/github/user`, + payload + ); + }, resendInvite: (user) => axios.bcPut( "Invite", diff --git a/src/app/views/admin/github-form/OrganizationUsers.jsx b/src/app/views/admin/github-form/OrganizationUsers.jsx index 20e860ff..2c609c32 100644 --- a/src/app/views/admin/github-form/OrganizationUsers.jsx +++ b/src/app/views/admin/github-form/OrganizationUsers.jsx @@ -16,6 +16,7 @@ import bc from '../../../services/breathecode'; import dayjs from 'dayjs'; import config from '../../../../config.js'; import { faLastfmSquare } from "@fortawesome/free-brands-svg-icons"; +import { PickCohortUserModal } from "./PickCohortUserModal"; const relativeTime = require('dayjs/plugin/relativeTime'); @@ -56,7 +57,7 @@ const getStatus = (u) => { const OrganizationUsers = ({ organization }) => { const [items, setItems] = useState([]); - + const [ userToAdd, setUserToAdd] = useState(false); const columns = [ { @@ -68,7 +69,7 @@ const OrganizationUsers = ({ organization }) => { return (
{item.user !== null &&
{item.user.first_name + " " + item.user.last_name}
} - {item.username} + {item.username ? {item.username} : No username found}
); }, @@ -105,8 +106,26 @@ const OrganizationUsers = ({ organization }) => { return data; } + const addToOrganization = async (cu) => { + if(!cu) return false; + + const result = await bc.auth().addGithubUser({ cohort: cu.cohort.id, user: cu.user.id }); + setUserToAdd(false); + loadData(); + } + return ( + { userToAdd == true && addToOrganization(_cu)} + />} +
+ +
{ + + const [cohort, setCohort] = useState(defaultCohort) + const [cohortUser, setCohortUser] = useState(defaultCohortUser) + const [ error, setError ] = useState(null) + + return ( + <> + onClose(false)} + aria-labelledby="alert-dialog-title" + aria-describedby="alert-dialog-description" + fullWidth="md" + > + + Find a cohort and user + + + setCohort(x)} + label="Search for active or prework cohorts" + value={cohort} + getOptionLabel={(option) => `${option.name} (${option.stage})`} + asyncSearch={async (searchTerm) => { + const resp = await bc.admissions().getAllCohorts({ ...cohortQuery, like: searchTerm }) + if(resp.ok) return resp.data + else setError("Error fetching cohorts") + }} + /> + {cohort && setCohortUser(x)} + label={`Search user in cohort ${cohort.name}`} + value={cohortUser} + debounced={false} + getOptionLabel={(option) => `${option.user.first_name} ${option.user.last_name} - ${option.user.email}`} + asyncSearch={async (searchTerm) => { + let q = { ...cohorUserQuery, cohorts: cohort.slug }; + if(searchTerm) q.like = searchTerm; + + const resp = await bc.admissions().getAllUserCohorts(q) + if(resp.ok) return resp.data + else setError("Error fetching cohort users") + }} + />} + {hint &&

{hint}

} +
+ + + +
+ + ) +} + +PickCohortUserModal.defaultProps = defaultProps; \ No newline at end of file diff --git a/src/app/views/admin/github.jsx b/src/app/views/admin/github.jsx index 011e7e91..a4725470 100644 --- a/src/app/views/admin/github.jsx +++ b/src/app/views/admin/github.jsx @@ -1,9 +1,10 @@ import React, { useEffect, useState } from "react"; -import { Grid } from "@material-ui/core"; +import { Grid, Button } from "@material-ui/core"; import { Alert, AlertTitle } from "@material-ui/lab"; import { useSelector } from 'react-redux'; import { Breadcrumb } from "../../../matx"; import bc from "../../services/breathecode"; +import { Link } from 'react-router-dom'; import OrganizationUsers from "./github-form/OrganizationUsers"; import GithubOrganization from "./github-form/GithubOrganization"; import { MatxLoading } from 'matx'; @@ -87,7 +88,7 @@ const GithubSettings = () => { return (
-
+
Date: Tue, 11 Apr 2023 22:33:30 +0000 Subject: [PATCH 23/29] warning for invites --- src/app/components/ConfirmAlert.jsx | 8 ++++---- .../views/admin/github-form/OrganizationUsers.jsx | 12 ++++++++++++ 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/app/components/ConfirmAlert.jsx b/src/app/components/ConfirmAlert.jsx index da40b7bb..8f804276 100644 --- a/src/app/components/ConfirmAlert.jsx +++ b/src/app/components/ConfirmAlert.jsx @@ -12,7 +12,7 @@ import PropTypes from 'prop-types'; const emptyCallback = () => {}; const defaultProps = { onOpen: emptyCallback, - onClose: emptyCallback, + onClose: null, isOpen: false, setIsOpen: emptyCallback, cancelText: 'Cancel', @@ -46,7 +46,7 @@ const ConfirmAlert = ({ { - onClose(); + onClose && onClose(); setIsOpen(false); }} aria-labelledby={titleTestId} @@ -63,7 +63,7 @@ const ConfirmAlert = ({ ) : <>} - + }
From 204ed6cf5da000eb63b9138dc90e30a51c226dc2 Mon Sep 17 00:00:00 2001 From: Roberto Lopez J Date: Thu, 27 Apr 2023 21:19:00 +0000 Subject: [PATCH 28/29] [Finished Event Types] --- src/app/services/breathecode.js | 13 ++- .../EventTypesForm/EventTypeDetails.jsx | 8 +- .../events/EventTypesForm/NewEventType.jsx | 85 +++++++++---------- .../events/EventTypesForm/ShareEventsCard.jsx | 43 ++++++---- .../events/EventTypesForm/ThumbnailCard.jsx | 76 +++++++++++++++++ src/app/views/events/EventTypesForm/index.jsx | 17 +++- 6 files changed, 175 insertions(+), 67 deletions(-) create mode 100644 src/app/views/events/EventTypesForm/ThumbnailCard.jsx diff --git a/src/app/services/breathecode.js b/src/app/services/breathecode.js index 076d2135..a9ae9df5 100644 --- a/src/app/services/breathecode.js +++ b/src/app/services/breathecode.js @@ -831,6 +831,12 @@ class BreatheCodeClient { `${this.host}/events/academy/organization`, payload ), + postAcademyEventTypeVisibilitySetting: (payload, slug) => + axios.bcPost( + "Academy event Type Visibility Setting", + `${this.host}/events/academy/eventype/${slug}/visibilitysetting`, + payload + ), putAcademyEventOrganization: (payload) => axios.bcPut( "Academy event", @@ -854,7 +860,12 @@ class BreatheCodeClient { deleteAcademyEventTypes: (org) => axios.bcDelete( "Delete Eventtype", - `${this.host}/events/academy/eventype` + `${this.host}/events/academy/` + ), + deleteAcademyEventTypeVisibilitySetting: (slug, visibilityID) => + axios.bcDelete( + "Delete Visibility Setting", + `${this.host}/events/academy/eventype/${slug}/visibilitysetting/${visibilityID}` ), getEventbriteWebhook: (query) => { const qs = serializeQuerystring(query); diff --git a/src/app/views/events/EventTypesForm/EventTypeDetails.jsx b/src/app/views/events/EventTypesForm/EventTypeDetails.jsx index b03d3142..a4a96ae0 100644 --- a/src/app/views/events/EventTypesForm/EventTypeDetails.jsx +++ b/src/app/views/events/EventTypesForm/EventTypeDetails.jsx @@ -12,6 +12,7 @@ import { getSession } from '../../../redux/actions/SessionActions'; import { availableLanguages } from 'utils'; + const eventypePropTypes = { id: PropTypes.number, slug: PropTypes.string, @@ -19,6 +20,7 @@ const eventypePropTypes = { language: PropTypes.string, onSubmit: PropTypes.func, academy_owner: PropTypes.number, + visibility_settings: PropTypes.string, }; const propTypes = { @@ -106,7 +108,7 @@ const EventTypeDetails = ({ eventype, onSubmit }) => { /> ) : ( - ({ values, isSubmitting, setFieldValue, handleChange }) => ( + ({ values, isSubmitting, setFieldValue }) => ( { name="icon_url" type="text" variant="outlined" - onChange={handleChange} + onChange={(e) => { + setFieldValue('icon_url', e.target.value); + }} value={values.icon_url} required /> diff --git a/src/app/views/events/EventTypesForm/NewEventType.jsx b/src/app/views/events/EventTypesForm/NewEventType.jsx index fff1f78f..8b998910 100644 --- a/src/app/views/events/EventTypesForm/NewEventType.jsx +++ b/src/app/views/events/EventTypesForm/NewEventType.jsx @@ -13,24 +13,18 @@ import { useHistory } from 'react-router-dom'; import * as Yup from 'yup'; import { Formik, Form } from 'formik'; import bc from '../../../services/breathecode'; -import Field from '../../../components/Field'; import { Breadcrumb } from '../../../../matx'; import { schemas } from '../../../utils'; import { getSession } from '../../../redux/actions/SessionActions'; import { availableLanguages } from 'utils'; +import ThumbnailCard from './ThumbnailCard'; const slugify = require('slugify'); const schema = Yup.object().shape({ - // academy: yup.number().required().positive().integer(), - // schedule: yup.number().required().positive().integer(), - slug: schemas.slug(), name: schemas.name(), - // schedule_type: Yup.mixed().oneOf(scheduleTypes).required(), }); - - const NewEventype = () => { const history = useHistory(); const session = getSession(); @@ -39,7 +33,7 @@ const NewEventype = () => { const addEventType = async (values, { setSubmitting }) => { try { const response = await bc.events().addAcademyEventType({ ...values, academy: session.academy.id }); - console.log(session.academy) + console.log("this is Values", values) if (response.status === 201) { setSubmitting(false); history.push('/events/eventype'); @@ -66,14 +60,15 @@ const NewEventype = () => { {({ - values, setFieldValue, isSubmitting, + values, setFieldValue, isSubmitting, handleSubmit, errors, + touched, handleChange }) => ( - + Name @@ -89,11 +84,15 @@ const NewEventype = () => { name="name" type="text" variant="outlined" - onChange={e => setName(e.target.value)} + error={errors.name && touched.name} + helperText={touched.name && errors.name} + // onChange={e => setName(e.target.value)} required + value={values.name} + onChange={(e) => {values.slug = slugify(e.target.value).toLowerCase(); handleChange(e)}} /> - + Slug @@ -108,8 +107,8 @@ const NewEventype = () => { name="slug" type="text" variant="outlined" - onChange={e => setFieldValue('slug', e.target.value)} - value={slugify(name).toLowerCase()} + onChange={handleChange} + value={values.slug} required /> @@ -135,47 +134,43 @@ const NewEventype = () => { Icon URL - setFieldValue('icon_url', e.target.value)} - required - /> + setFieldValue('icon_url', url)}> + Language - setFieldValue('lang', e.target.value)} + value={values.lang} + onChange={(e) => { + setFieldValue('lang', e.target.value); + }} select > {Object.keys(availableLanguages).map((item) => ( - {item?.toUpperCase()} + {item} ))} + - setFieldValue('allow_shared_creation', e.target.checked)} + checked={values.allow_shared_creation} + onChange={(e) => { + setFieldValue('allow_shared_creation', e.target.checked); + }} name="shared_creation" data-cy="shared_creation" color="primary" @@ -184,18 +179,18 @@ const NewEventype = () => { label="Allow Shared Creation" /> -
- -
- +
+ +
+ )} diff --git a/src/app/views/events/EventTypesForm/ShareEventsCard.jsx b/src/app/views/events/EventTypesForm/ShareEventsCard.jsx index 9a35e5fd..741e2076 100644 --- a/src/app/views/events/EventTypesForm/ShareEventsCard.jsx +++ b/src/app/views/events/EventTypesForm/ShareEventsCard.jsx @@ -32,7 +32,6 @@ const schema = Yup.object().shape({ const propTypes = { - onSubmit: PropTypes.func.isRequired, eventype: PropTypes.shape(eventypePropTypes).isRequired, }; @@ -44,7 +43,7 @@ const getVisibilitySettingMessage = (visibility) => { else return <>Everyone at {visibility.academy.name} } -const ShareEvents = ({ eventype, onSubmit, openDialogDeleteVisibility, setOpenDialogDeleteVisibility, setVisibilitySetting }) => { +const ShareEvents = ({ eventype, setEventype, openDialogDeleteVisibility, setOpenDialogDeleteVisibility, setVisibilitySetting, fetchEventype }) => { const [isLoading, setIsLoading] = useState(false); const handleOpen = () => setOpen(true); const handleClose = () => setOpen(false); @@ -64,6 +63,19 @@ const ShareEvents = ({ eventype, onSubmit, openDialogDeleteVisibility, setOpenDi p: 4, }; + + const addVisibilitySetting = async (values) => { + try { + const response = await bc.events().postAcademyEventTypeVisibilitySetting({ ...values}, eventype.slug); + if (response.status >= 200) { + await fetchEventype(); + setSubmitting(false); + } + } catch (error) { + console.error(error); + } + }; + return ( <>

Who can join these events?

@@ -81,19 +93,18 @@ const ShareEvents = ({ eventype, onSubmit, openDialogDeleteVisibility, setOpenDi )} { - onSubmit(values); + onSubmit={() => { + addVisibilitySetting({academy: eventype.academy.id, cohort: chooseCohort.id, syllabus: syllabus.id}); setSubmitting(false); }} > - {({ values, isSubmitting, handleSubmit, setFieldValue }) => ( + {({ values, isSubmitting, handleSubmit }) => (
- @@ -103,6 +114,7 @@ const ShareEvents = ({ eventype, onSubmit, openDialogDeleteVisibility, setOpenDi
setSyllabus(x)} width="100%" @@ -110,8 +122,7 @@ const ShareEvents = ({ eventype, onSubmit, openDialogDeleteVisibility, setOpenDi asyncSearch={() => bc.admissions().getAllSyllabus()} size="small" data-cy="syllabus" - label="syllabus" - + label="syllabus" getOptionLabel={(option) => `${option.name}`} value={syllabus} /> @@ -123,6 +134,7 @@ const ShareEvents = ({ eventype, onSubmit, openDialogDeleteVisibility, setOpenDi
setChooseCohort(x)} width="100%" @@ -131,7 +143,6 @@ const ShareEvents = ({ eventype, onSubmit, openDialogDeleteVisibility, setOpenDi size="small" data-cy="cohort" label="cohort" - getOptionLabel={(option) => `${option.name}`} value={chooseCohort} /> @@ -148,7 +159,6 @@ const ShareEvents = ({ eventype, onSubmit, openDialogDeleteVisibility, setOpenDi Share
- @@ -173,7 +183,7 @@ const ShareEvents = ({ eventype, onSubmit, openDialogDeleteVisibility, setOpenDi {getVisibilitySettingMessage(visibility)} -{/* +{ - */} + } )) : ( <>
There are no shared settings
- )} - -{/* + )} +{ { handleOpen() }}> @@ -203,7 +212,7 @@ const ShareEvents = ({ eventype, onSubmit, openDialogDeleteVisibility, setOpenDi add_circle - */} + }
diff --git a/src/app/views/events/EventTypesForm/ThumbnailCard.jsx b/src/app/views/events/EventTypesForm/ThumbnailCard.jsx new file mode 100644 index 00000000..27c2339c --- /dev/null +++ b/src/app/views/events/EventTypesForm/ThumbnailCard.jsx @@ -0,0 +1,76 @@ +import React, { useState, useEffect } from "react"; +import { + Table, TableCell, TableRow, Card, MenuItem, DialogContent, + Grid, Dialog, TextField, Button, Chip, Icon, Tooltip, TableHead, + TableBody +} from "@material-ui/core"; + +import dayjs from 'dayjs'; +import { toast } from 'react-toastify'; +import bc from 'app/services/breathecode'; +import relativeTime from 'dayjs/plugin/relativeTime'; +import { MediaInput } from '../../../components/MediaInput'; +import config from '../../../../config.js'; +import PropTypes from 'prop-types'; + +dayjs.extend(relativeTime) + + +toast.configure(); +const toastOption = { + position: toast.POSITION.BOTTOM_RIGHT, + autoClose: 8000, +}; + +const eventypePropTypes = { + id: PropTypes.number, + slug: PropTypes.string, + name: PropTypes.string, + icon_url: PropTypes.string, + academy_owner: PropTypes.number, + visibility_settings: PropTypes.string, + }; + + +const propTypes = { + onSubmit: PropTypes.func.isRequired, + eventype: PropTypes.shape(eventypePropTypes).isRequired, + }; + +const ThumbnailCard = ({ eventype, onChange }) => { + const [preview, setPreview] = useState(null); + const [previewURL, setPreviewURL] = useState(null); + const [edit, setEdit] = useState(null); + + useEffect(() => { + setPreview(eventype?.icon_url) + setPreviewURL(eventype?.icon_url) + }, [eventype?.icon_url]) + + return + {edit ? +
+ {setPreviewURL(v); onChange(v)}} + name="icon_url" + fullWidth + inputProps={{ style: { padding: '10px' } }} + /> + +
+ : +

No preview image has been generated for this Event Type. + setEdit(true)}> Set one now +

+ } +
; + } + + ThumbnailCard.propTypes = propTypes; + +export default ThumbnailCard; diff --git a/src/app/views/events/EventTypesForm/index.jsx b/src/app/views/events/EventTypesForm/index.jsx index 428a7ede..a334a6f4 100644 --- a/src/app/views/events/EventTypesForm/index.jsx +++ b/src/app/views/events/EventTypesForm/index.jsx @@ -21,6 +21,7 @@ import { MatxLoading } from '../../../../matx'; import ConfirmAlert from '../../../components/ConfirmAlert'; import { getSession } from '../../../redux/actions/SessionActions'; + toast.configure(); const toastOption = { position: toast.POSITION.BOTTOM_RIGHT, @@ -81,6 +82,17 @@ const Eventtype = () => { } }; + const deleteVisibilitySetting = async (visibilitySettingID) => { + try { + const response = await bc.events().deleteAcademyEventTypeVisibilitySetting(eventype.slug, visibilitySettingID); + if (response.status === 204) { + await fetchEventype(); + } + } catch (error) { + console.error(error); + } + }; + const onAccept = () => updateEventype({ private: !eventype.private }); return ( @@ -109,8 +121,9 @@ const Eventtype = () => { Disagree @@ -146,7 +159,7 @@ const Eventtype = () => { - + From cc86d9ec0d745ef56148a9ee85d15cc31c46f4d7 Mon Sep 17 00:00:00 2001 From: Roberto Lopez J Date: Mon, 31 Jul 2023 19:46:20 +0000 Subject: [PATCH 29/29] [Updated EvenType] --- src/app/services/breathecode.js | 12 +- .../EventTypesForm/EventTypeDetails.jsx | 30 +-- .../events/EventTypesForm/ShareEventsCard.jsx | 242 ++++++++++++------ .../events/EventTypesForm/ThumbnailCard.jsx | 118 ++++++--- 4 files changed, 257 insertions(+), 145 deletions(-) diff --git a/src/app/services/breathecode.js b/src/app/services/breathecode.js index 852a38af..3f12b519 100644 --- a/src/app/services/breathecode.js +++ b/src/app/services/breathecode.js @@ -127,9 +127,17 @@ class BreatheCodeClient { payload ), getCertificates: () => - axios.bcGet("Certificates", `${this.host}/admissions/syllabus`), + axios.bcGet( + "Certificates", + `${this.host}/admissions/syllabus`), getAllSyllabus: () => - axios.bcGet("Syllabus", `${this.host}/admissions/syllabus`), + axios.bcGet( + "Syllabus", + `${this.host}/admissions/syllabus`), + getAllAcademies: () => + axios.bcGet( + "Academy", + `${this.host}/admissions/academy`), getAllTimeZone: () => axios.bcGet( "TimeZone", diff --git a/src/app/views/events/EventTypesForm/EventTypeDetails.jsx b/src/app/views/events/EventTypesForm/EventTypeDetails.jsx index a4a96ae0..59f66af8 100644 --- a/src/app/views/events/EventTypesForm/EventTypeDetails.jsx +++ b/src/app/views/events/EventTypesForm/EventTypeDetails.jsx @@ -10,6 +10,7 @@ import Field from '../../../components/Field'; import { schemas } from '../../../utils'; import { getSession } from '../../../redux/actions/SessionActions'; import { availableLanguages } from 'utils'; +import ThumbnailCard from './ThumbnailCard'; @@ -37,13 +38,12 @@ const schema = Yup.object().shape({ const EventTypeDetails = ({ eventype, onSubmit }) => { - console.log('this is eventype', eventype) const [status, setStatus] = useState({ color: "", message: "" }); const session = getSession(); const academyOwner = session.academy.id; const sessionAcademy = session.academy.slug; - const eventypeAcademy = eventype.academy.slug; - const eventypeAcademyId = eventype.academy.id; + const eventypeAcademy = eventype.academy?.slug; + const eventypeAcademyId = eventype.academy?.id; const [checked, setChecked] = useState(false); useEffect(() => { @@ -158,24 +158,12 @@ const EventTypeDetails = ({ eventype, onSubmit }) => { Icon URL - - { - setFieldValue('icon_url', e.target.value); - }} - value={values.icon_url} - required - /> - + + setFieldValue('icon_url', url)}> + `` + setOpen(false); const [chooseCohort, setChooseCohort] = useState(null); const [syllabus, setSyllabus] = useState(null); + const [academy, setAcademy] = useState(null); const [open, setOpen] = React.useState(false); + const session = getSession(); + const eventypeAcademy = eventype.academy?.slug; + const eventypeAcademyId = eventype.academy?.id; + const academyOwner = session.academy?.id; + const style = { position: 'absolute', top: '50%', @@ -63,13 +70,11 @@ const ShareEvents = ({ eventype, setEventype, openDialogDeleteVisibility, setOpe p: 4, }; - const addVisibilitySetting = async (values) => { try { - const response = await bc.events().postAcademyEventTypeVisibilitySetting({ ...values}, eventype.slug); + const response = await bc.events().postAcademyEventTypeVisibilitySetting(values, eventype.slug); if (response.status >= 200) { await fetchEventype(); - setSubmitting(false); } } catch (error) { console.error(error); @@ -80,8 +85,6 @@ const ShareEvents = ({ eventype, setEventype, openDialogDeleteVisibility, setOpe <>

Who can join these events?

- - {eventype.private && ( @@ -95,70 +98,141 @@ const ShareEvents = ({ eventype, setEventype, openDialogDeleteVisibility, setOpe { - addVisibilitySetting({academy: eventype.academy.id, cohort: chooseCohort.id, syllabus: syllabus.id}); + onSubmit={(values, { setSubmitting }) => { + + let visibilitySettings = { academy: academy?.id }; + if (academy) visibilitySettings['academy'] = academy.id; + if (syllabus) visibilitySettings['syllabus'] = syllabus.id; + if (chooseCohort) visibilitySettings['cohort'] = chooseCohort.id; + + addVisibilitySetting(visibilitySettings); + handleClose(); setSubmitting(false); }} > {({ values, isSubmitting, handleSubmit }) => (
- - + {academy && academy?.id != eventype?.academy.id ? + <> + + + Academy + - - Syllabus - + +
+ bc.admissions().getAllAcademies()} + onChange={(x) => setAcademy(x)} + width="100%" + className="m-4" + size="small" + data-cy="academy" + label="academy" + getOptionLabel={(option) => `${option.name}`} + /> +
- -
- setSyllabus(x)} - width="100%" - className="m-4" - asyncSearch={() => bc.admissions().getAllSyllabus()} - size="small" - data-cy="syllabus" - label="syllabus" - getOptionLabel={(option) => `${option.name}`} - value={syllabus} - /> -
-
- - Cohort +
+ +
+ +
+ + + : + <> -
- setChooseCohort(x)} - width="100%" - className="m-4" - asyncSearch={() => bc.admissions().getAllCohorts()} - size="small" - data-cy="cohort" - label="cohort" - getOptionLabel={(option) => `${option.name}`} - value={chooseCohort} - /> -
+ + Academy + + + +
+ setAcademy(x)} + width="100%" + className="m-4" + asyncSearch={() => bc.admissions().getAllAcademies()} + size="small" + data-cy="academy" + label="academy" + getOptionLabel={(option) => `${option.name}`} + /> +
+
+ + Syllabus + + + +
+ setSyllabus(x)} + width="100%" + className="m-4" + asyncSearch={() => bc.admissions().getAllSyllabus()} + size="small" + data-cy="syllabus" + label="syllabus" + getOptionLabel={(option) => `${option.name}`} + /> +
+
+ + + Cohort + + +
+ setChooseCohort(x)} + width="100%" + className="m-4" + asyncSearch={() => bc.admissions().getAllCohorts()} + size="small" + data-cy="cohort" + label="cohort" + getOptionLabel={(option) => `${option.name}`} + /> +
+
-
-
- -
+ +
+ +
+ + + } +
@@ -183,36 +257,42 @@ const ShareEvents = ({ eventype, setEventype, openDialogDeleteVisibility, setOpe {getVisibilitySettingMessage(visibility)} -{ - - - { - setVisibilitySetting(visibility); - setOpenDialogDeleteVisibility(true); - }} - > - - delete - + { + - - } + { + setVisibilitySetting(visibility); + setOpenDialogDeleteVisibility(true); + }} + > + + delete + + + + } )) : ( <>
There are no shared settings
- )} -{ - { - handleOpen() - }}> - - add_circle - - - } + )} + {eventypeAcademyId !== academyOwner ? + "" : + <> + { + { + handleOpen() + }}> + + add_circle + + + } + + } +
diff --git a/src/app/views/events/EventTypesForm/ThumbnailCard.jsx b/src/app/views/events/EventTypesForm/ThumbnailCard.jsx index 27c2339c..ec4dd392 100644 --- a/src/app/views/events/EventTypesForm/ThumbnailCard.jsx +++ b/src/app/views/events/EventTypesForm/ThumbnailCard.jsx @@ -23,54 +23,90 @@ const toastOption = { }; const eventypePropTypes = { - id: PropTypes.number, - slug: PropTypes.string, - name: PropTypes.string, - icon_url: PropTypes.string, - academy_owner: PropTypes.number, - visibility_settings: PropTypes.string, - }; - + id: PropTypes.number, + slug: PropTypes.string, + name: PropTypes.string, + icon_url: PropTypes.string, + academy_owner: PropTypes.number, + visibility_settings: PropTypes.string, +}; + const propTypes = { - onSubmit: PropTypes.func.isRequired, - eventype: PropTypes.shape(eventypePropTypes).isRequired, - }; + onSubmit: PropTypes.func.isRequired, + eventype: PropTypes.shape(eventypePropTypes).isRequired, +}; const ThumbnailCard = ({ eventype, onChange }) => { - const [preview, setPreview] = useState(null); - const [previewURL, setPreviewURL] = useState(null); - const [edit, setEdit] = useState(null); - - useEffect(() => { - setPreview(eventype?.icon_url) - setPreviewURL(eventype?.icon_url) - }, [eventype?.icon_url]) - - return - {edit ? -
- {setPreviewURL(v); onChange(v)}} - name="icon_url" - fullWidth - inputProps={{ style: { padding: '10px' } }} - /> - -
+ const [preview, setPreview] = useState(null); + const [previewURL, setPreviewURL] = useState(null); + const [edit, setEdit] = useState(null); + const [updateIcon, setUpdateIcon] = useState(null); + + useEffect(() => { + setPreview(eventype?.icon_url) + setPreviewURL(eventype?.icon_url) + }, [eventype?.icon_url]) + + return <> + {eventype != null ? + +
+
+ + {updateIcon ? +
+ { setPreviewURL(v); onChange(v) }} + name="icon_url" + fullWidth + inputProps={{ style: { padding: '10px' } }} + /> + +
: + setUpdateIcon(true)}>Change Icon + } +
+ : +
+ {edit ? +
+ { setPreviewURL(v); onChange(v) }} + name="icon_url" + fullWidth + inputProps={{ style: { padding: '10px' } }} + /> + +
: -

No preview image has been generated for this Event Type. +

There is no Icon generated for this Event Type. setEdit(true)}> Set one now

- } - ; - } + } +
+ } + + ; +} - ThumbnailCard.propTypes = propTypes; +ThumbnailCard.propTypes = propTypes; export default ThumbnailCard;