Commit c73f39be authored by Sandro Lutz's avatar Sandro Lutz Committed by Sandro Lutz
Browse files

Add StudydocsController

parent 67c9e553
......@@ -74,10 +74,10 @@
"studydocs.not_found": "Dokument nicht gefunden",
"studydocs.no_selection": "Kein Dokument ausgewählt",
"studydocs.searchfield": "Titel eingeben...",
"studydocs.summaries": "Zusammenfassungen",
"studydocs.old_exams": "Alte Prüfungen",
"studydocs.lecture_documents": "Unterrichtsmaterialien",
"studydocs.exercises": "Übungen",
"cheat sheets": "Zusammenfassungen",
"exams": "Alte Prüfungen",
"lecture documents": "Unterrichtsmaterialien",
"exercises": "Übungen",
"studydocs.semester_all": "Alle Semester",
"studydocs.semester1": "1. Semester",
"studydocs.semester2": "2. Semester",
......
......@@ -74,10 +74,10 @@
"studydocs.not_found": "Document not found",
"studydocs.no_selection": "No document selected",
"studydocs.searchfield": "Enter title...",
"studydocs.summaries": "Summaries",
"studydocs.old_exams": "Old exams",
"studydocs.lecture_documents": "Lecture documents",
"studydocs.exercises": "Exercises",
"cheat sheets": "Summaries",
"exams": "Old exams",
"lecture documents": "Lecture documents",
"exercises": "Exercises",
"studydocs.semester_all": "All semesters",
"studydocs.semester1": "1. semester",
"studydocs.semester2": "2. semester",
......
import m from 'mithril';
import { apiUrl } from 'config';
import { getToken } from './auth';
import Query from './query';
let querySaved = {};
import PaginationController from './pagination';
/**
* Get the loaded list of studydocuments.
* StudydocsController class
*
* @return {array}
* Managing studydocument list and handling of the currently selected event.
*/
export function getList() {
if (typeof this.list === 'undefined') {
return [];
export default class StudydocsController extends PaginationController {
constructor(query = {}, additionalQuery = {}) {
super('studydocuments', query, additionalQuery);
}
return this.list;
}
/**
* Load studydocuments from the AMIV API
*
* @param {*} query filter and sort query for the API request.
* @return {Promise} exports for additional response handling
*/
export function load(query = {}) {
querySaved = Query.copy(query);
const queryEncoded = Query.buildQueryString({ where: query });
/**
* Set a new query to load the configured resource
*
* @public
*/
async setQuery(query) {
const newQuery = JSON.stringify(query || {});
const oldQuery = JSON.stringify(this.query);
// ignore if query has not changed
if (newQuery === oldQuery) return false;
return m
.request({
super.setQuery(query);
return this.loadPageData(1);
}
/**
* Load a specific document from the AMIV API
*
* @param {String} documentId
* @public
*/
async loadDocument(documentId) {
this._selectedDocument = await m.request({
method: 'GET',
url: `${apiUrl}/studydocuments?${queryEncoded}`,
url: `${apiUrl}/studydocuments/${documentId}`,
headers: {
Authorization: getToken(),
},
})
.then(result => {
this.list = result._items;
});
}
/**
* Load a single document from the AMIV API
*
* @param {string} id
*/
export async function loadDocument(id) {
return m.request({
method: 'GET',
url: `${apiUrl}/studydocuments/${id}`,
headers: {
Authorization: getToken(),
},
});
}
return this._selectedDocument;
}
/**
* Get Suggestions from already existing entries for a specified field of `studydocument`.
*
* @param {String} field entity field which should be searched.
* @param {String} input search string
*/
export function getInputSuggestions(field, input) {
const query = {};
query[field] = { $regex: `^(?i).*${input}.*` };
// TODO: debug Error 502 Bad Gateway returned by API
// const projection = {};
// projection[field] = 1;
const queryEncoded = Query.buildQueryString({
where: query,
// projection: JSON.stringify(projection),
});
return m.request({
method: 'GET',
url: `${apiUrl}/studydocuments?${queryEncoded}`,
headers: {
Authorization: getToken(),
},
});
}
/**
* Get the previously loaded event
* @return {object} studydocument from the AMIV API
* @public
*/
get selectedDocument() {
return this._selectedDocument;
}
/**
* Reload studydocument list with the same query as before.
*
* @return {Promise} exports for additional response handling
*/
export function reload() {
return load(querySaved);
}
/**
* Store a new studydocument in the AMIV API.
*
* @param {Object} doc studydocument object to be stored in the AMIV API.
* @return {Promise}
* @static
*/
static addNew(doc) {
if (typeof doc !== 'object') {
return new Promise(() => {}); // empty promise
}
const form = new FormData();
Object.keys(doc).forEach(key => {
if (key === 'files') {
for (let i = 0; i < doc.files.length; i += 1) {
form.append('files', doc.files[i]);
}
} else {
form.append(key, doc[key]);
}
});
/**
* Store a new studydocument in the AMIV API.
*
* @param {Object} doc studydocument object to be stored in the AMIV API.
* @return {Promise} exports for additional response handling
*/
export function addNew(doc) {
if (typeof doc !== 'object') {
return new Promise(() => {}); // empty promise
return m.request({
method: 'POST',
url: `${apiUrl}/studydocuments`,
data: form,
headers: {
Authorization: getToken(),
},
});
}
const form = new FormData();
Object.keys(doc).forEach(key => {
if (key === 'files') {
for (let i = 0; i < doc.files.length; i += 1) {
form.append('files', doc.files[i]);
}
} else {
form.append(key, doc[key]);
}
});
return m.request({
method: 'POST',
url: `${apiUrl}/studydocuments`,
data: form,
headers: {
Authorization: getToken(),
},
});
/**
* Get Suggestions from already existing entries for a specified field of `studydocument`.
*
* @param {String} field entity field which should be searched.
* @param {String} input search string
* @return {String} suggestion
* @static
*/
static getInputSuggestions(field, input) {
const query = {};
query[field] = { $regex: `^(?i).*${input}.*` };
// TODO: debug Error 502 Bad Gateway returned by API
// const projection = {};
// projection[field] = 1;
const queryEncoded = m.buildQueryString({
where: JSON.stringify(query),
// projection: JSON.stringify(projection),
});
return m.request({
method: 'GET',
url: `${apiUrl}/studydocuments?${queryEncoded}`,
headers: {
Authorization: getToken(),
},
});
}
}
import m from 'mithril';
import { apiUrl } from 'config';
import { i18n } from '../../models/language';
import { Button } from '../../components';
export default class StudydocDetails {
oninit(vnode) {
this.controller = vnode.attrs.controller;
}
view() {
const document = this.controller.selectedDocument;
if (!document) {
return m('h1', i18n('studydocs.not_found'));
}
return [
m('table', [
m('tr', [m('td', m('b', i18n('studydocs.title'))), m('td', document.title)]),
m('tr', [m('td', m('b', i18n('studydocs.lecture'))), m('td', document.lecture)]),
m('tr', [m('td', m('b', i18n('studydocs.professor'))), m('td', document.professor)]),
m('tr', [m('td', m('b', i18n('studydocs.semester'))), m('td', document.semester)]),
m('tr', [m('td', m('b', i18n('studydocs.author'))), m('td', document.author)]),
m('tr', [m('td', m('b', i18n('studydocs.department'))), m('td', document.department)]),
m(Button, {
label: 'Download',
events: {
onclick: () => window.open(`${apiUrl}${document.files[0].file}`, '_blank'),
},
}),
]),
];
}
}
import m from 'mithril';
import { apiUrl } from 'config';
import * as studydocs from '../../models/studydocs';
import { Button, FilterView } from '../../components';
import StudydocsController from '../../models/studydocs';
import { lectures } from '../studydocs/lectures';
import { i18n, currentLanguage } from '../../models/language';
import { FilteredListDataStore, FilteredListPage } from '../filteredListPage';
import StudydocDetails from './studydocDetails';
const tableHeadings = ['title', 'author', 'type'];
const controller = new StudydocsController();
const dataStore = new FilteredListDataStore();
export default class StudydocList extends FilteredListPage {
constructor() {
super('studydoc', dataStore, true);
export default class StudydocList {
oninit(vnode) {
this.vnode = vnode;
this.docLoaded = false;
this.lectureDropdownDisabled = true;
}
if (vnode.attrs.documentId) {
studydocs
.loadDocument(vnode.attrs.documentId)
.then(doc => {
this.selectDocument(doc);
})
.catch(() => {
this.selectDocument(undefined);
});
}
oninit(vnode) {
super.oninit(vnode, vnode.attrs.documentId);
}
// eslint-disable-next-line class-methods-use-this
_loadItem(documentId) {
return controller.loadDocument(documentId);
}
selectDocument(doc) {
this.docLoaded = true;
this.doc = doc;
// eslint-disable-next-line class-methods-use-this
_reloadData() {
return controller.loadPageData(1);
}
isLectureDropdownDisabled() {
_isLectureDropdownDisabled() {
return this.lectureDropdownDisabled;
}
// dynamic lectures data based on selected semester and department
loadLectures(values) {
_loadLectures(values) {
if (!values.department) {
return [];
}
......@@ -69,171 +68,156 @@ export default class StudydocList {
return data;
}
view(vnode) {
let documentView;
if (this.docLoaded) {
if (this.doc) {
documentView = m('div.details', [
m('table', [
m('tr', [m('td', m('b', i18n('studydocs.title'))), m('td', this.doc.title)]),
m('tr', [m('td', m('b', i18n('studydocs.lecture'))), m('td', this.doc.lecture)]),
m('tr', [m('td', m('b', i18n('studydocs.professor'))), m('td', this.doc.professor)]),
m('tr', [m('td', m('b', i18n('studydocs.semester'))), m('td', this.doc.semester)]),
m('tr', [m('td', m('b', i18n('studydocs.author'))), m('td', this.doc.author)]),
m('tr', [m('td', m('b', i18n('studydocs.department'))), m('td', this.doc.department)]),
m(Button, {
label: 'Download',
events: {
onclick: () => window.open(`${apiUrl}${this.doc.files[0].file}`, '_blank'),
},
}),
]),
]);
} else {
documentView = m('div.details', m('h1', i18n('studydocs.not_found')));
}
} else if (vnode.attrs.documentId) {
// do not show anything until document has loaded.
documentView = m('');
} else {
documentView = m('div.details', m('h1', i18n('studydocs.no_selection')));
}
return m('div#studydoc-list', [
m('div.filter', [
// create filterview with checkboxes
m(FilterView, {
fields: [
{
type: 'text',
key: 'title',
label: i18n('studydocs.searchfield'),
min_length: 3,
},
{
type: 'button',
label: i18n('search'),
events: {
onclick: 'search',
},
},
{
type: 'button',
label: i18n('reset'),
className: 'flat-button',
events: {
onclick: 'reset',
},
},
{
type: 'checkbox',
key: 'department',
label: i18n('studydocs.department'),
default: ['itet', 'mavt'],
values: [{ value: 'itet', label: 'D-ITET' }, { value: 'mavt', label: 'D-MAVT' }],
},
{
type: 'dropdown',
key: 'semester',
default: 'all',
values: [
{ value: 'all', label: i18n('studydocs.semester_all') },
{ value: '1', label: i18n('studydocs.semester1') },
{ value: '2', label: i18n('studydocs.semester2') },
{ value: '3', label: i18n('studydocs.semester3') },
{ value: '4', label: i18n('studydocs.semester4') },
{ value: '5+', label: i18n('studydocs.semester5+') },
],
},
{
type: 'dropdown',
key: 'lecture',
default: 'all',
disabled: this.isLectureDropdownDisabled,
values: this.loadLectures,
},
{
type: 'checkbox',
key: 'type',
label: i18n('studydocs.type'),
default: ['cheat sheets', 'exams', 'lecture documents', 'exercises'],
values: [
{ value: 'cheat sheets', label: i18n('studydocs.summaries') },
{ value: 'exams', label: i18n('studydocs.old_exams') },
{ value: 'lecture documents', label: i18n('studydocs.lecture_documents') },
{ value: 'exercises', label: i18n('studydocs.exercises') },
],
},
{
type: 'button',
label: i18n('studydocs.upload'),
events: {
onclick: () => m.route.set(`/${currentLanguage()}/studydocuments/new`),
},
},
get _filterViewAttributes() {
return {
fields: [
{
type: 'text',
key: 'title',
label: i18n('studydocs.searchfield'),
min_length: 3,
},
{
type: 'button',
label: i18n('search'),
events: {
onclick: 'search',
},
},
{
type: 'button',
label: i18n('reset'),
className: 'flat-button',
events: {
onclick: 'reset',
},
},
{
type: 'checkbox',
key: 'department',
label: i18n('studydocs.department'),
default: ['itet', 'mavt'],
values: [{ value: 'itet', label: 'D-ITET' }, { value: 'mavt', label: 'D-MAVT' }],
},
{
type: 'dropdown',
key: 'semester',
default: 'all',
values: [
{ value: 'all', label: i18n('studydocs.semester_all') },
{ value: '1', label: i18n('studydocs.semester1') },
{ value: '2', label: i18n('studydocs.semester2') },
{ value: '3', label: i18n('studydocs.semester3') },
{ value: '4', label: i18n('studydocs.semester4') },
{ value: '5+', label: i18n('studydocs.semester5+') },
],
},
{
type: 'dropdown',
key: 'lecture',
default: 'all',
disabled: this._isLectureDropdownDisabled,
values: this._loadLectures,
},
{
type: 'checkbox',
key: 'type',
label: i18n('studydocs.type'),
default: ['cheat sheets', 'exams', 'lecture documents', 'exercises'],
values: [
{ value: 'cheat sheets', label: i18n('cheat sheets') },
{ value: 'exams', label: i18n('exams') },
{ value: 'lecture documents', label: i18n('lecture documents') },
{ value: 'exercises', label: i18n('exercises') },
],
onchange: values => {
const query = {};
Object.keys(values).forEach(key => {
let value = values[key];
if (Array.isArray(value)) {
query[key] = { $in: value };
} else if (key === 'semester' && value !== 'all') {
query[key] = value;
} else if (key === 'lecture' && value !== 'all') {
query[key] = value;
} else if (key === 'title' && value.length > 0) {
value = value.substring(0, value.length);
query.$or = [
{ title: { $regex: `^(?i).*${value}.*` } },
{ lecture: { $regex: `^(?i).*${value}.*` } },
{ author: { $regex: `^(?i).*${value}.*` } },
{ professor: { $regex: `^(?i).*${value}.*` } },
];
}
if (query.department && query.department.$in.length === 2) {
delete query.department;
}
if (query.type && query.type.$in.length === 4) {
delete query.type;
}
});
studydocs.load(query);
},
{
type: 'button',
label: i18n('studydocs.upload'),
events: {
onclick: () => m.route.set(`/${currentLanguage()}/studydocuments/new`),
},
}),
]),
// filtered content view
m('div.content', [
m('div.content-grid', [
tableHeadings.map(header => m('div.list-header', header)),
studydocs
.getList()
.map(doc => [
m(
'div.list-item',
{ onclick: () => m.route.set(`/${currentLanguage()}/studydocuments/${doc._id}`) },
doc.title
),
m(
'div.list-item',
{ onclick: () => m.route.set(`/${currentLanguage()}/studydocuments/${doc._id}`) },
doc.author
),
m(
'div.list-item',
{ onclick: () => m.route.set(`/${currentLanguage()}/studydocuments/${doc._id}`) },
doc.type
),
]),
]),
]),
documentView,
]);
},
],
onchange: values => {
const query = {};
Object.keys(values).forEach(key => {
let value = values[key];
if (Array.isArray(value)) {
query[key] = { $in: value };
} else if (<