-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add course view for searching and adding team courses.
- Loading branch information
Showing
8 changed files
with
323 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
import React, {useState, useEffect} from 'react'; | ||
import ApiHelper from "../../helpers/ApiHelper"; | ||
import moment from "moment"; //TODO | ||
|
||
|
||
const CourseTable = ({courses, totalPages}) => <> | ||
<div className="table-responsive d-none d-md-block" data-aos='fade'> | ||
<table className="table"> | ||
<thead> | ||
<tr> | ||
<td>Title</td> | ||
<td>Provider</td> | ||
<td>Date Added</td> | ||
<td></td> | ||
</tr> | ||
</thead> | ||
<tbody> | ||
{ | ||
courses.map(course => { | ||
const date = moment(course.created_at).format('MMM D, YYYY') | ||
const classes = course.unlisted ? 'bg-cream-dark' : ''; | ||
|
||
return( | ||
<tr key={course.id} className={`${classes}`}> | ||
<td><a href={course.course_page_path}>{`${course.unlisted ? "[UNLISTED] " : ""}${course.title}`}</a></td> | ||
<td>{course.provider}</td> | ||
<td>{date}</td> | ||
<td><a href={course.course_edit_path} className="p2pu-btn btn btn-sm dark">edit</a></td> | ||
</tr> | ||
) | ||
}) | ||
} | ||
</tbody> | ||
</table> | ||
</div> | ||
|
||
<div className="d-md-none"> | ||
{ | ||
courses.map((course, index) => { | ||
const date = moment(course.created_at).format('MMM D, YYYY') | ||
const classes = course.unlisted ? 'bg-cream-dark' : ''; | ||
const delay = index * 100; | ||
|
||
return( | ||
<div className={`meeting-card p-2 ${classes}`} key={course.id} data-aos='fade-up' data-aos-delay={delay}> | ||
<a className="bold" href={course.course_page_path}>{`${course.unlisted ? "[UNLISTED] " : ""}${course.title}`}</a> | ||
|
||
<div className="d-flex"> | ||
<div className="pr-2"> | ||
<div className="bold">Provider</div> | ||
<div className="bold">Date Added</div> | ||
</div> | ||
|
||
<div className="flex-grow px-2"> | ||
<div className="">{ course.provider }</div> | ||
<div className="">{ date }</div> | ||
</div> | ||
</div> | ||
|
||
<a href={ course.course_edit_path } className="p2pu-btn btn btn-sm dark m-0 my-2">edit</a> | ||
</div> | ||
) | ||
}) | ||
} | ||
</div> | ||
|
||
{ | ||
totalPages > 1 && | ||
<nav aria-label="Page navigation"> | ||
<ul className="pagination"> | ||
<li className={`page-item ${currentPage == 1 ? 'disabled' : ''}`}> | ||
<a className="page-link" href="" aria-label="Previous" onClick={this.prevPage}> | ||
<span aria-hidden="true">«</span> | ||
<span className="sr-only">Previous</span> | ||
</a> | ||
</li> | ||
<li className="page-item"> | ||
<span className="page-link disabled">{`Page ${currentPage} of ${totalPages}`}</span> | ||
</li> | ||
<li className={`page-item ${currentPage == totalPages ? 'disabled' : ''}`}> | ||
<a className="page-link" href="" aria-label="Next" onClick={this.nextPage}> | ||
<span aria-hidden="true">»</span> | ||
<span className="sr-only">Next</span> | ||
</a> | ||
</li> | ||
</ul> | ||
</nav> | ||
} | ||
|
||
</> | ||
|
||
|
||
const CourseList = props => { | ||
const {teamId} = props; | ||
const [courseList, setCourseList] = useState({courses: [], count: 0, offset:0, limit: 20}); | ||
useEffect(() => { | ||
const api = new ApiHelper('courses'); | ||
const onSuccess = (data) => { | ||
setCourseList({ | ||
courses: data.items, | ||
count: data.count, | ||
offset: data.offset, | ||
limit: data.limit | ||
}) | ||
} | ||
const params = { | ||
limit: courseList.limit, | ||
offset: courseList.offset, | ||
team: true, | ||
} | ||
api.fetchResource({ callback: onSuccess, params }) | ||
}, []) | ||
return ( | ||
<> | ||
<CourseTable | ||
courses={courseList.courses} | ||
totalPages={1} | ||
/> | ||
</> | ||
); | ||
} | ||
|
||
export default CourseList; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
import React from 'react' | ||
import ReactDOM from 'react-dom' | ||
import ErrorBoundary from './components/error-boundary' | ||
|
||
import SearchProvider from 'p2pu-components/dist/Search/SearchProvider' | ||
import SearchCourses from 'p2pu-components/dist/Courses/SearchCourses' | ||
import CourseCard from 'p2pu-components/dist/Courses/CourseCard' | ||
//import BrowseCourses from 'p2pu-components/dist/Courses/Browse' | ||
import SearchAndFilter from 'p2pu-components/dist/Courses/SearchAndFilter' | ||
import SearchSummary from 'p2pu-components/dist/Courses/SearchSummary' | ||
import SearchBar from 'p2pu-components/dist/Search/SearchBar' | ||
|
||
import OrderCoursesForm from 'p2pu-components/dist/Courses/OrderCoursesForm' | ||
import TopicsFilterForm from 'p2pu-components/dist/Courses/TopicsFilterForm' | ||
import LanguageFilterForm from 'p2pu-components/dist/Courses/LanguageFilterForm' | ||
import OerFilterForm from 'p2pu-components/dist/Courses/OerFilterForm' | ||
import FacilitatorGuideFilterForm from 'p2pu-components/dist/Courses/FacilitatorGuideFilterForm' | ||
|
||
import { t } from 'ttag'; | ||
|
||
|
||
|
||
const element = document.getElementById('team-courses') | ||
|
||
const user = element.dataset.user === "AnonymousUser" ? null : element.dataset.user; | ||
const teamId = element.dataset.teamId === "None" ? null : element.dataset.teamId; | ||
const teamName = element.dataset.teamName === "None" ? null : element.dataset.teamName; | ||
const userIsOrganizer = element.dataset.userIsOrganizer === "None" ? null : element.dataset.userIsOrganizer; | ||
|
||
|
||
const BrowseCourses = props => { | ||
const { results, updateQueryParams, onSelectResult, columnBreakpoints, isLoading } = props; | ||
|
||
if (isLoading){ | ||
return <></>; | ||
} | ||
|
||
return ( | ||
<div className="search-results"> | ||
{ | ||
results.map((course, index) => ( | ||
<CourseCard | ||
key={`course-card-${index}`} | ||
id={`course-card-${index}`} | ||
course={course} | ||
updateQueryParams={updateQueryParams} | ||
courseLink={props.courseLink} | ||
moreInfo={props.moreInfo} | ||
onSelectResult={onSelectResult} | ||
buttonText={t`Add this course`} | ||
classes="mb-4" | ||
/> | ||
)) | ||
} | ||
</div> | ||
); | ||
} | ||
|
||
// TODO dedup with frontend/components/learning_circle_form/CourseSelection.jsx | ||
const CustomCourseSearch = (props) => { | ||
return ( | ||
<> | ||
<SearchBar | ||
updateQueryParams={props.updateQueryParams} | ||
q={props.q} | ||
/> | ||
|
||
<a data-bs-toggle="collapse" href="#searchFilters" role="button" aria-expanded="false" aria-controls="searchFilters"> | ||
Advanced options <i className="fa fa-chevron-down"></i> | ||
</a> | ||
|
||
<div id="searchFilters" className="collapse"> | ||
<div className="col-12"> | ||
<OrderCoursesForm {...props} /> | ||
</div> | ||
<div className="col-12"> | ||
<TopicsFilterForm {...props} /> | ||
</div> | ||
<div className="col-12"> | ||
<LanguageFilterForm {...props} /> | ||
</div> | ||
<div className="col-12"> | ||
<FacilitatorGuideFilterForm {...props} /> | ||
</div> | ||
<div className="col-12"> | ||
<OerFilterForm {...props} /> | ||
</div> | ||
</div> | ||
|
||
<SearchSummary {...props} /> | ||
<BrowseCourses {...props} onSelectResult={ e=> console.log(e) }/> | ||
</> | ||
); | ||
} | ||
|
||
|
||
const TeamCourseSelection = props => { | ||
|
||
const handleSelectResult = selected => { | ||
props.updateFormData({ course: selected }) | ||
scrollToTop() | ||
} | ||
|
||
return ( | ||
<div id="team-course-selection"> | ||
<h1>Select team courses</h1> | ||
<SearchProvider | ||
columnBreakpoints={props.showHelp ? 1 : 3} | ||
searchSubject={'courses'} | ||
initialState={{languages: ['en']}} | ||
onSelectResult={handleSelectResult} | ||
origin={window.location.origin} | ||
scrollContainer={'#team-course-selection'} | ||
NoResultsComponent={() => <p className="my-4">{`There are no matching courses.`}<a className="btn p2pu-btn btn-secondary" href={`${window.location.origin}${window.location.pathname}`}>Start over</a></p>} | ||
> | ||
<CustomCourseSearch/> | ||
</SearchProvider> | ||
</div> | ||
); | ||
} | ||
|
||
ReactDOM.render( | ||
<ErrorBoundary scope="team-courses"> | ||
<TeamCourseSelection | ||
user={user} | ||
teamId={teamId} | ||
teamName={teamName} | ||
userIsOrganizer={userIsOrganizer} | ||
isMemberTeam={element.dataset.isMemberTeam} | ||
isStaff={element.dataset.isStaff} | ||
/> | ||
</ErrorBoundary>, | ||
element | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
{% extends 'base.html' %} | ||
{% load render_bundle from webpack_loader %} | ||
{% load static %} | ||
{% load i18n %} | ||
|
||
{% block page_title %} | ||
{% trans "Team Courses" %} | ||
{% endblock %} | ||
|
||
|
||
{% block content %} | ||
<div | ||
id='team-courses' | ||
data-user="{{ request.user }}" | ||
data-team-id="{{ team_id }}" | ||
data-team-role="{{ team_role }}" | ||
data-team-name="{{ team_name }}" | ||
data-team-organizer-name="{{ team_organizer_name }}" | ||
data-user-is-organizer="{{ user_is_organizer }}" | ||
{% if is_member_team %} | ||
data-is-member-team="true" | ||
data-member-support-url="{{ member_support_url }}" | ||
{% endif %} | ||
{% if request.user.is_staff %} | ||
data-is-staff="true" | ||
data-member-support-url="{{ member_support_url }}" | ||
{% endif %} | ||
> | ||
<div class="loader"></div> | ||
</div> | ||
|
||
{% endblock %} | ||
|
||
{% block scripts %} | ||
{% render_bundle 'team-courses' %} | ||
{% endblock %} |