Skip to content

Commit

Permalink
Calendar of exams (#143)
Browse files Browse the repository at this point in the history
Fixes #80.

Co-authored-by: Peter Vašut <[email protected]>
Co-authored-by: Adrián Goga <[email protected]>
  • Loading branch information
3 people authored Jan 29, 2020
1 parent 72aca99 commit 55e6ccd
Show file tree
Hide file tree
Showing 5 changed files with 250 additions and 10 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@
"jquery": "^3.4.1",
"lodash": "^4.17.11",
"mini-css-extract-plugin": "^0.7.0",
"moment": "^2.24.0",
"node-sass": "^4.12.0",
"prop-types": "^15.7.2",
"react": "^16.8.6",
"react-big-calendar": "^0.22.0",
"react-dom": "^16.8.6",
"sass-loader": "^7.1.0",
"url-loader": "^2.0.0",
Expand Down
20 changes: 20 additions & 0 deletions votrfront/css/main.scss
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ $table-condensed-cell-padding: 4px;
@import "votr-bootstrap";
@import "layout";
@import "forms";
@import "~react-big-calendar/lib/css/react-big-calendar";


html, body {
Expand Down Expand Up @@ -87,6 +88,25 @@ a, .btn.btn-link {
margin-bottom: $line-height-computed;
}

.skusky-calendar-menu {
margin-left: 10px;
}

/* "html" = specificity tie breaker */
/* must win vs ".rbc-calendar", ".rbc-event", ".rbc-event.rbc-selected" */
html .skusky-calendar {
height: 90vh;
.rbc-event {
cursor: inherit; /* there is no onClick event - for now */
}
.skusky-calendar-registered {
background-color: #337ab7;
}
.skusky-calendar-unregistered {
background-color: #999999;
}
}

.loading {
background-image: url(spinner.svg);
background-repeat: no-repeat;
Expand Down
113 changes: 104 additions & 9 deletions votrfront/js/MojeSkuskyPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import { CacheRequester, Loading, RequestCache, sendRpc } from './ajax';
import { PageLayout, PageTitle } from './layout';
import { Link, queryConsumer } from './router';
import { sortAs, SortableTable } from './sorting';
import { Calendar, momentLocalizer } from 'react-big-calendar';
import moment from 'moment';


// TODO: Oddelit Aktualne terminy hodnotenia vs Stare terminy hodnotenia

Expand Down Expand Up @@ -177,10 +180,97 @@ function convertToICAL(terminy) {
return lines.map((l) => l.replace(/\n/g, "\\n")).join("\r\n");
}

function MojeSkuskyMenuLink(props) {
return (<Link className={"btn btn-default" + (props.active ? " active" : "")} href={props.href}>{props.label}</Link>);
}

export function MojeSkuskyMenu() {
return queryConsumer(query => {
var {action, kalendar, zapisnyListKey} = query;
return(
<div className="pull-left">
<div className="skusky-calendar-menu">
<div className="btn-group">
<MojeSkuskyMenuLink
label="Zoznam"
href={{ action: 'mojeSkusky', kalendar: 0, zapisnyListKey }}
active={kalendar != 1}
/>
<MojeSkuskyMenuLink
label="Kalendár"
href={{ action: 'mojeSkusky', kalendar: 1, zapisnyListKey }}
active={kalendar == 1}
/>
</div>
</div>
</div>)
});
}

function convertToEvents(terminy){
return terminy.map((termin, i) => {
return {id: i,
title: `${termin.nazov_predmetu} (${termin.cas}${termin.miestnost ? ", " + termin.miestnost : ""})`,
start: moment(termin.datum+" "+termin.cas, 'DD.MM.YYYY HH:mm').toDate(),
end: moment(termin.datum+" "+termin.cas, 'DD.MM.YYYY HH:mm').add(3,"hours").toDate(),
prihlaseny: termin.datum_prihlasenia && !termin.datum_odhlasenia};
})
}

function defaultDate(eventList) {
var today = new Date();

if (eventList.length) {
var lastExamDate = _.maxBy(eventList, 'start').start;
if (lastExamDate < today) return lastExamDate;
}

return today;
}

export function KalendarUdalosti(props) {
const localizer = momentLocalizer(moment)

return (
<Calendar
localizer={localizer}
events={props.eventList}
views={["month", "week", "day"]}
defaultDate = {defaultDate(props.eventList)}
className="skusky-calendar"
messages={{
allDay: "Celý deň",
previous: "Späť",
next: "Ďalej",
today: "Dnes",
month: "Mesiac",
week: "Týždeň",
day: "Deň",
agenda: "Agenda",
date: "Dátum",
time: "Čas",
event: "Skúška"
}}
culture={"sk"}
eventPropGetter={
event => {
return {
className: event.prihlaseny ? "skusky-calendar-registered" : "skusky-calendar-unregistered"
};
}
}
//remove start and end times (we need only one included in title)
formats={{
eventTimeRangeFormat: ({ start, end }, culture, local) => {}
}}
/>
)
}

export function MojeSkuskyPageContent() {
return queryConsumer(query => {
var cache = new CacheRequester();
var {zapisnyListKey} = query;
var {zapisnyListKey, kalendar} = query;

var vidim = cache.get('get_vidim_terminy_hodnotenia', zapisnyListKey);

Expand Down Expand Up @@ -213,14 +303,18 @@ export function MojeSkuskyPageContent() {
}

return <React.Fragment>
<SortableTable
items={terminy}
columns={MojeSkuskyColumns}
queryKey="skuskySort"
withButtons={true}
message={message}
expandedContentOffset={1}
/>
{kalendar == 1?
<KalendarUdalosti eventList={convertToEvents(terminy)} />
:
<SortableTable
items={terminy}
columns={MojeSkuskyColumns}
queryKey="skuskySort"
withButtons={true}
message={message}
expandedContentOffset={1}
/>
}
{terminy.length && <button type="button" onClick={handleClickICal} className="btn">Stiahnuť ako iCal</button>}
</React.Fragment>;
});
Expand Down Expand Up @@ -288,6 +382,7 @@ export function MojeSkuskyPage() {
<ZapisnyListSelector>
<div className="header">
<PageTitle>Moje skúšky</PageTitle>
<MojeSkuskyMenu />
</div>
<MojeSkuskyPageContent />
</ZapisnyListSelector>
Expand Down
2 changes: 2 additions & 0 deletions webpack.config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const fs = require('fs');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const webpack = require('webpack');

const bootstrapPath = __dirname + '/node_modules/bootstrap-sass/assets/stylesheets';

Expand Down Expand Up @@ -93,6 +94,7 @@ module.exports = function (env, args) {
new MiniCssExtractPlugin({ filename: 'style.css' }),
new StatusFilePlugin(mode == 'development' ? 'dev' : 'prod'),
new CleanMapFilesPlugin(),
new webpack.ContextReplacementPlugin(/moment[/\\]locale$/, /sk/),
],
module: {
rules: [
Expand Down
Loading

0 comments on commit 55e6ccd

Please sign in to comment.