Display empty courses in new class table
This commit is contained in:
parent
b400d010e0
commit
667887c06c
|
@ -234,6 +234,8 @@ class CardViewSet(Base, Create, Retrieve, Update, Destroy):
|
||||||
utils_stats.changed_card()
|
utils_stats.changed_card()
|
||||||
|
|
||||||
|
|
||||||
|
# TODO: return nested list of sessions, limited with Prefetch:
|
||||||
|
# https://stackoverflow.com/a/58689019
|
||||||
class CourseViewSet(Base, List, Retrieve, Create, Update):
|
class CourseViewSet(Base, List, Retrieve, Create, Update):
|
||||||
permission_classes = [AllowMetadata | IsAuthenticatedOrReadOnly, IsAdminOrReadOnly | IsInstructorOrReadOnly]
|
permission_classes = [AllowMetadata | IsAuthenticatedOrReadOnly, IsAdminOrReadOnly | IsInstructorOrReadOnly]
|
||||||
queryset = models.Course.objects.annotate(date=Max('sessions__datetime')).order_by('-date')
|
queryset = models.Course.objects.annotate(date=Max('sessions__datetime')).order_by('-date')
|
||||||
|
|
|
@ -6,6 +6,7 @@ import moment from 'moment-timezone';
|
||||||
import { apiUrl, isAdmin, isInstructor, getInstructor, BasicTable, requester } from './utils.js';
|
import { apiUrl, isAdmin, isInstructor, getInstructor, BasicTable, requester } from './utils.js';
|
||||||
import { NotFound, PleaseLogin } from './Misc.js';
|
import { NotFound, PleaseLogin } from './Misc.js';
|
||||||
import { InstructorClassDetail, InstructorClassAttendance } from './InstructorClasses.js';
|
import { InstructorClassDetail, InstructorClassAttendance } from './InstructorClasses.js';
|
||||||
|
import { courseCache } from './Courses.js';
|
||||||
import { PayPalPayNow } from './PayPal.js';
|
import { PayPalPayNow } from './PayPal.js';
|
||||||
import { tags } from './Courses.js';
|
import { tags } from './Courses.js';
|
||||||
|
|
||||||
|
@ -61,9 +62,10 @@ function ClassTable(props) {
|
||||||
};
|
};
|
||||||
|
|
||||||
function NewClassTable(props) {
|
function NewClassTable(props) {
|
||||||
const { classes } = props;
|
const { classes, courses } = props;
|
||||||
|
|
||||||
let sortedClasses = [];
|
let sortedClasses = [];
|
||||||
|
let seenCourseIds = [];
|
||||||
if (classes.length) {
|
if (classes.length) {
|
||||||
for (const clazz of classes) {
|
for (const clazz of classes) {
|
||||||
const course_data = clazz.course_data;
|
const course_data = clazz.course_data;
|
||||||
|
@ -76,6 +78,9 @@ function NewClassTable(props) {
|
||||||
course: course_data,
|
course: course_data,
|
||||||
classes: [clazz],
|
classes: [clazz],
|
||||||
});
|
});
|
||||||
|
seenCourseIds.push(
|
||||||
|
course_data.id
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -84,17 +89,17 @@ function NewClassTable(props) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div style={{ margin: '0 -1.5rem 0 -0.5rem', display: 'flex', flexWrap: 'wrap' }}>
|
<div className='newclasstable'>
|
||||||
{sortedClasses.map(x =>
|
{sortedClasses.map(x =>
|
||||||
<Segment style={{ margin: '1rem 1rem 0 0', width: '22rem' }}>
|
<Segment style={{ margin: '1rem 1rem 0 0', width: '22rem' }}>
|
||||||
<Header size='medium'>
|
<Header size='small'>
|
||||||
<Link to={'/courses/'+x.course.id}>
|
<Link to={'/courses/'+x.course.id}>
|
||||||
{x.course.name}
|
{x.course.name}
|
||||||
</Link>
|
</Link>
|
||||||
</Header>
|
</Header>
|
||||||
|
|
||||||
{!!x.course.tags && x.course.tags.split(',').map(name =>
|
{!!x.course.tags && x.course.tags.split(',').map(name =>
|
||||||
<Label color={tags[name]} tag>
|
<Label color={tags[name]} tag size='small'>
|
||||||
{name}
|
{name}
|
||||||
</Label>
|
</Label>
|
||||||
)}
|
)}
|
||||||
|
@ -136,6 +141,22 @@ function NewClassTable(props) {
|
||||||
</Table>
|
</Table>
|
||||||
</Segment>
|
</Segment>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{courses.filter(x => !seenCourseIds.includes(x.id)).map(x =>
|
||||||
|
<Segment style={{ margin: '1rem 1rem 0 0', width: '22rem' }}>
|
||||||
|
<Header size='small'>
|
||||||
|
<Link to={'/courses/'+x.id}>
|
||||||
|
{x.name}
|
||||||
|
</Link>
|
||||||
|
</Header>
|
||||||
|
|
||||||
|
{!!x.tags && x.tags.split(',').map(name =>
|
||||||
|
<Label color={tags[name]} tag>
|
||||||
|
{name}
|
||||||
|
</Label>
|
||||||
|
)}
|
||||||
|
</Segment>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -184,10 +205,22 @@ export function ClassFeed(props) {
|
||||||
|
|
||||||
export function Classes(props) {
|
export function Classes(props) {
|
||||||
const [classes, setClasses] = useState(classesCache);
|
const [classes, setClasses] = useState(classesCache);
|
||||||
|
const [courses, setCourses] = useState(courseCache);
|
||||||
const [sortByCourse, setSortByCourse] = useState(sortCache);
|
const [sortByCourse, setSortByCourse] = useState(sortCache);
|
||||||
const [tagFilter, setTagFilter] = useState(tagFilterCache);
|
const [tagFilter, setTagFilter] = useState(tagFilterCache);
|
||||||
const { token, user } = props;
|
const { token, user } = props;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
requester('/courses/', 'GET', token)
|
||||||
|
.then(res => {
|
||||||
|
setCourses(res.results);
|
||||||
|
courseCache = res.results;
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.log(err);
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
requester('/sessions/', 'GET', token)
|
requester('/sessions/', 'GET', token)
|
||||||
.then(res => {
|
.then(res => {
|
||||||
|
@ -201,7 +234,8 @@ export function Classes(props) {
|
||||||
|
|
||||||
const byTeaching = (x) => x.instructor_id === user.member.id;
|
const byTeaching = (x) => x.instructor_id === user.member.id;
|
||||||
const byDate = (a, b) => a.datetime > b.datetime ? 1 : -1;
|
const byDate = (a, b) => a.datetime > b.datetime ? 1 : -1;
|
||||||
const byTag = (x) => tagFilter ? x.course_data.tags.includes(tagFilter) : true;
|
const classesByTag = (x) => tagFilter ? x.course_data.tags.includes(tagFilter) : true;
|
||||||
|
const coursesByTag = (x) => tagFilter ? x.tags.includes(tagFilter) : true;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
|
@ -268,11 +302,14 @@ export function Classes(props) {
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
||||||
{classes.length ?
|
{classes.length && courses.length ?
|
||||||
sortByCourse ?
|
sortByCourse ?
|
||||||
<NewClassTable classes={classes.filter(byTag)} />
|
<NewClassTable
|
||||||
|
classes={classes.filter(classesByTag)}
|
||||||
|
courses={courses.filter(coursesByTag)}
|
||||||
|
/>
|
||||||
:
|
:
|
||||||
<ClassTable classes={classes.slice().filter(byTag).sort(byDate)} />
|
<ClassTable classes={classes.slice().filter(classesByTag).sort(byDate)} />
|
||||||
:
|
:
|
||||||
<p>Loading...</p>
|
<p>Loading...</p>
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ export const tags = {
|
||||||
Misc: 'grey',
|
Misc: 'grey',
|
||||||
};
|
};
|
||||||
|
|
||||||
let courseCache = false;
|
export let courseCache = false;
|
||||||
let tagFilterCache = false;
|
let tagFilterCache = false;
|
||||||
|
|
||||||
export function Courses(props) {
|
export function Courses(props) {
|
||||||
|
|
|
@ -132,6 +132,16 @@ body {
|
||||||
.coursetags .ui.tag.label {
|
.coursetags .ui.tag.label {
|
||||||
margin-top: 1rem;
|
margin-top: 1rem;
|
||||||
}
|
}
|
||||||
|
.newclasstable {
|
||||||
|
margin: 0 -1.5rem 0 -0.5rem;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.newclasstable .ui.tag.label {
|
||||||
|
padding-left: 1rem;
|
||||||
|
padding-right: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
.usage {
|
.usage {
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user