Schedule serverside

This commit is contained in:
tmshv committed 2017-05-26 18:41:11 +03:00
1 parent 06b3f481bd
commit fcf45614a3
11 files changed
+311 -107

No files matched your search

+1 -12
View File
@@ -82,18 +82,7 @@ app.config(($locationProvider, $routeProvider) => {
}
}))
let routers = [
{
name: '/schedule/:period?/:semester?',
template: '<page-schedule schedules="$resolve.list"></page-schedule>',
title: 'Расписание',
resolve: {
list: api => api.schedule
.list()
.then(i => i.data)
}
}
]
let routers = []
.concat(pages)
.map(i => {
let path = i.name
+130
View File
@@ -0,0 +1,130 @@
const React = require('react')
import {getDates} from '../utils/date'
import {shortName} from '../models/collective'
const now = new Date()
const dates = getDates(now);
const days = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun'];
const isToday = weekDayIndex => (now.getDay() - 1) === weekDayIndex;
const weekDay = weekDayIndex => dates[weekDayIndex];
const short = shortName;
const todayClass = i => isToday(i)
? 'current'
: ''
const HeadDay = ({i, children}) => (
<div className={`${todayClass(i)}`}>
<p className="day">{children}</p>
<p className="date">{weekDay(i)}</p>
</div>
)
const days2 = [
'Понедельник',
'Вторник',
'Среда',
'Четверг',
'Пятница',
'Суббота',
]
const Schedule = ({groups}) => (
<div className="schedule-table">
<div className="schedule-table__head">
<div className="group">Гр.</div>
{days2.map((day, index) => (
<HeadDay key={index} i={index}>{day}</HeadDay>
))}
</div>
<div className="schedule-table__body">
{groups.map((group, index) => (
<GroupRow key={index} {...group}/>
))}
</div>
</div>
)
const GroupRow = ({name, time, week}) => (
<div className="schedule-table__body-row">
<div className="schedule-table__body-group">
<p className="name">{name}</p>
<p className="time">{time}</p>
</div>
{week.map((day, index) => (
<Group key={index} day={day} dayIndex={index}/>
))}
</div>
)
const Group = ({day, dayIndex}) => (
<div className={`schedule-table__record ${todayClass(dayIndex)}`}>
{day.map((lesson, index) => (
<Cell key={index} {...lesson}/>
))}
</div>
)
const Cell = ({course, teacher, time}) => (
<div className="schedule-table__course">
{
console.log(time)
}
<Lesson {...course}/>
<Teacher {...teacher}/>
{time
.map(range => ({range}))
.map((range, index) => (
<TimeRange key={index} {...range}/>
))}
</div>
)
const Lesson = ({title, url}) => (
<p className="lesson">
{url
? (
<a href={url}>
{title}
</a>
)
: (
<span>
{title}
</span>
)
}
</p>
)
const Teacher = ({name, url}) => (
<p className="teacher">
{url
? (
<a href={url}>
{short(name)}
</a>
)
: (
<span>
{short(name)}
</span>
)
}
</p>
)
const TimeRange = ({range}) => (
<p className="time">{(range || []).join(' — ')}</p>
)
module.exports = Schedule
+20
View File
@@ -0,0 +1,20 @@
const React = require('react')
const text = require('../core/schedule').text
const ScheduleList = ({schedules}) => (
<div className="schedule-selector">
<ul>
{schedules.map((s, index) => (
<Schedule key={index} {...s}/>
))}
</ul>
</div>
)
const Schedule = ({url, semester, period}) => (
<li>
<a href={url}>{text({semester, period})}</a>
</li>
)
module.exports = ScheduleList
+62 -30
View File
@@ -1,18 +1,20 @@
import {c} from '../core/db'
import {select} from '../utils/fn'
import {createMap} from '../utils/common'
import {getCollective} from './collective'
import {scheduleDate, getPeriod as schedulePeriod} from '../models/schedule'
import {scheduleDate, getPeriod as schedulePeriod, getPeriodString} from '../models/schedule'
import {getCourse} from '../models/course'
const last = require('../lib/array').last
const sortBy = require('../lib/sort').sortBy
const SCHEDULES = 'schedules'
export async function getSchedule(period, semester) {
async function findSchedule(period, semester) {
const schedule = await c(SCHEDULES).findOne({
$or: [
{period: period},
{period: schedulePeriod(period)}
{period: period},
{period: schedulePeriod(period)}
],
semester: semester
})
@@ -20,19 +22,44 @@ export async function getSchedule(period, semester) {
return schedule ? migrate(schedule) : null
}
export async function getSchedules(fields = ['_id', 'id', 'period', 'semester']) {
const list = await c(SCHEDULES)
.find({})
.toArray()
async function findAllScheduleParams() {
const schedules = await c(SCHEDULES)
.find({}, {
period: 1,
semester: 1,
_id: 0,
})
.toArray()
const schedules = await Promise.all(list.map(migrate))
return schedules
.sort((a, b) => {
const ad = scheduleDate(a).getTime()
const bd = scheduleDate(b).getTime()
return ad - bd
})
.map(select(fields))
.map(i => ({
...i,
period: schedulePeriod(i.period),
}))
.sort(sortBy(
i => scheduleDate(i).getTime(),
true,
))
}
async function findDefaultScheduleParams() {
const schedules = await findAllScheduleParams()
return last(schedules
.map(i => ({
...i,
period: getPeriodString(i.period),
}))
)
}
function text({semester, period}) {
const word = semester => [['spring', 'Весна'], ['autumn', 'Осень']]
.find(i => i[0] === semester)
[1]
const periodIndex = semester === 'spring' ? 1 : 0
const year = period[periodIndex]
return `${word(semester)} ${year} года`
}
async function migrate(schedule) {
@@ -49,7 +76,7 @@ async function migrate(schedule) {
function migrate10to20(schedule) {
const dayNames = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun']
const time = time => time
.map(i => i.split(' '))
.map(i => i.split(' '))
const week = days => days.reduce((week, lesson, index) => {
if (lesson) {
@@ -66,23 +93,23 @@ function migrate10to20(schedule) {
version: '2.0',
period: schedulePeriod(schedule.period),
groups: schedule.schedule
.map(group => ({
name: group.group,
time: group.time,
week: week(group.week)
}))
.map(group => ({
name: group.group,
time: group.time,
week: week(group.week)
}))
})
}
async function migrate20to30(schedule) {
const days = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun']
const days = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat']//, 'sun']
const persons = await getCollective()
const person = createMap(i => i.id, persons)
const week = week => days
.map(day => week[day] || [])
.map(lessons => lessons.map(lesson))
.map(day => week[day] || [])
.map(lessons => lessons.map(lesson))
const lesson = i => ({
time: i.time,
@@ -107,10 +134,15 @@ async function migrate20to30(schedule) {
return Object.assign(schedule, {
version: '3.0',
groups: schedule.groups
.map(group => ({
name: group.name,
time: group.time,
week: week(group.week)
}))
.map(group => ({
name: group.name,
time: group.time,
week: week(group.week)
}))
})
}
exports.findSchedule = findSchedule
exports.findAllScheduleParams = findAllScheduleParams
exports.findDefaultScheduleParams = findDefaultScheduleParams
exports.text = text
+14
View File
@@ -9,4 +9,18 @@ function splitBy(key) {
}
}
function head(list) {
return Array.isArray(list) && list.length
? list[0]
: null
}
function last(list) {
return Array.isArray(list) && list.length
? list[list.length - 1]
: null
}
exports.splitBy = splitBy
exports.head = head
exports.last = last
+7 -3
View File
@@ -10,9 +10,13 @@ export default [
],
},
{
'text': 'Расписание',
'url': '/schedule',
'color': 'green'
text: 'Расписание',
url: '/schedule',
color: 'green',
items: [
{url: '*', text: ''},
]
},
{
'text': 'Поступление',
+16
View File
@@ -28,3 +28,19 @@ export function getPeriod(i){
return i.map(Number);
}
/**
*
* f("2012-2015") -> "2012-2015"
* f(["2012", "2015"]) -> "2012-2015"
* f([2012, 2015]) -> "2012-2015"
*
* @param i
* @returns {*}
*/
function getPeriodString(i) {
return getPeriod(i)
.join('-')
}
exports.getPeriodString = getPeriodString
-24
View File
@@ -1,24 +0,0 @@
import route from 'koa-route';
import {json} from './';
import {sortByPattern} from '../utils/sort';
import db from '../core/db';
let split = d => s => s.split(d);
let toArray = split(',');
export default function () {
return route.get('/collective', json(
function *() {
this.type = 'application/json';
let pattern = toArray(this.query.sort || '');
let data = yield db.c('collective').find();
if (!data) {
this.status = 404;
return;
}
this.body = sortByPattern(data, pattern, i => i.id);
}
))
};
-4
View File
@@ -6,14 +6,10 @@ import {map, assign} from '../utils/common'
import {index as indexFile} from '../config'
import sitemap from './sitemap'
import schedule from './schedule'
import pages from './pages'
export function routes(store) {
return compose([
sitemap(),
schedule(),
pages(),
])
}
+59 -34
View File
@@ -1,40 +1,65 @@
import compose from 'koa-compose';
import route from 'koa-route';
import {json} from './';
const React = require('react')
const Share = require('../components/Share')
const Schedule = require('../components/Schedule')
const ScheduleList = require('../components/ScheduleList')
const {render} = require('../lib/render')
const getPeriodString = require('../models/schedule').getPeriodString
const getPathWithNoTrailingSlash = require('../lib/url').getPathWithNoTrailingSlash
const {get} = require('koa-route')
import {getSchedule, getSchedules} from '../core/schedule';
const {findSchedule, findDefaultScheduleParams, findAllScheduleParams} = require('../core/schedule')
const text = require('../core/schedule').text
export default function () {
return compose([
list(),
schedule()
]);
};
function list() {
return route.get('/schedule/list', json(
async(ctx) => {
ctx.type = 'application/json';
const data = await getSchedules();
if (!data) ctx.status = 404;
else ctx.body = data;
}
));
function getMeta(schedule) {
const t = text(schedule)
return {
title: t,
description: t,
}
}
function schedule() {
return route.get('/schedule/:period?/:semester?', json(
async(ctx, period, semester) => {
ctx.type = 'application/json';
function getSchedule() {
return get('/schedule/:period?/:semester?', async (ctx, period, semester) => {
const useRoute = Boolean(period) && Boolean(semester)
if (useRoute) {
const path = getPathWithNoTrailingSlash(ctx.path)
let data = await getSchedule(period, semester);
if (!data) {
ctx.status = 404;
return;
}
const data = await findSchedule(period, semester)
if (data) {
ctx.body = data;
}
))
}
//let schedules = await findAllScheduleParams()
//schedules = schedules.map(({semester, period}) => ({
// period,
// semester,
// url: `/schedule/${getPeriodString(period)}/${semester}`,
//}))
const Component = (
<div className="content content_full">
{/*<ScheduleList schedules={schedules}/>*/}
<Schedule {...data}/>
<Share/>
</div>
)
ctx.type = 'text/html'
ctx.body = await render(path, Component, getMeta(data))
} else {
ctx.status = 404
}
} else {
const route = await findDefaultScheduleParams()
if (route) {
const {period, semester} = route
ctx.redirect(`/schedule/${period}/${semester}`)
} else {
ctx.status = 404
}
}
})
}
exports.getSchedule = getSchedule
+2
View File
@@ -27,6 +27,7 @@ const gallery = require('./routes/gallery')
const teachers = require('./routes/teachers')
const documents = require('./routes/documents')
const document = require('./routes/document')
const schedule = require('./routes/schedule')
const dirPublic = path.join(__dirname, '../public')
const dirTemplates = path.join(__dirname, 'templates')
@@ -74,6 +75,7 @@ export default function (store) {
app.use(teachers.getTeacher())
app.use(documents.getDocuments())
app.use(document.getDocument())
app.use(schedule.getSchedule())
app.use(routes(store))
return Server(app.callback())