Commit 2050b1fb authored by Sandro Lutz's avatar Sandro Lutz Committed by Sandro Lutz
Browse files

Implement UX feedback for studydocuments

parent de5dd66c
......@@ -166,33 +166,40 @@ export default class FilterViewComponent {
}
_createDropdown(field) {
let data;
const options = {};
this.values[field.key] = this.values[field.key] || field.default || '';
if (typeof field.values === 'function') {
data = field.values(this.values);
options.data = field.values(this.values);
} else {
data = field.values;
options.data = field.values;
}
if (field.disabled) {
if (typeof field.disabled === 'function') {
options.disabled = field.disabled();
} else {
options.disabled = field.disabled;
}
}
let invalidSelection = true;
data.forEach(item => {
options.data.forEach(item => {
if (item.value === this.values[field.key]) {
invalidSelection = false;
}
});
if (invalidSelection === 0) {
if (invalidSelection) {
this.values[field.key] = field.default || '';
}
return m(Dropdown, {
data,
selected: this.values[field.key],
onchange: event => {
this.values[field.key] = event.target.value;
this.notify();
},
});
options.selected = this.values[field.key];
options.onchange = event => {
this.values[field.key] = event.target.value;
this.notify();
};
return m(Dropdown, options);
}
_createButton(options) {
......
......@@ -42,6 +42,10 @@ Raven.context(() => {
url: '/:language/studydocuments',
view: () => m(studydocList),
},
{
url: '/:language/studydocuments/:documentId',
view: vnode => m(studydocList, vnode.attrs),
},
{
url: '/:language/studydocuments/new',
view: () => m(studydocNew),
......
......@@ -70,6 +70,8 @@
"profile.newsletter_subscribe": "Newsletter abonnieren",
"profile.search_groups": "Gruppen durchsuchen",
"profile.expire_on": "läuft am %{date} ab",
"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",
......
......@@ -70,6 +70,8 @@
"profile.newsletter_subscribe": "subscribe to Newsletter",
"profile.search_groups": "Search groups",
"profile.expire_on": "expires on %{date}",
"studydocs.not_found": "Document not found",
"studydocs.no_selection": "No document selected",
"studydocs.searchfield": "Enter title...",
"studydocs.summaries": "Summaries",
"studydocs.old_exams": "Old exams",
......
......@@ -32,7 +32,7 @@ export function load(query = {}) {
method: 'GET',
url: `${apiUrl}/studydocuments?${queryEncoded}`,
headers: {
Authorization: `Token ${getToken()}`,
Authorization: getToken(),
},
})
.then(result => {
......@@ -40,6 +40,21 @@ export function load(query = {}) {
});
}
/**
* 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(),
},
});
}
/**
* Get Suggestions from already existing entries for a specified field of `studydocument`.
*
......@@ -60,7 +75,7 @@ export function getInputSuggestions(field, input) {
method: 'GET',
url: `${apiUrl}/studydocuments?${queryEncoded}`,
headers: {
Authorization: `Token ${getToken()}`,
Authorization: getToken(),
},
});
}
......@@ -100,7 +115,7 @@ export function addNew(doc) {
url: `${apiUrl}/studydocuments`,
data: form,
headers: {
Authorization: `Token ${getToken()}`,
Authorization: getToken(),
},
});
}
import m from 'mithril';
import { apiUrl } from 'config';
import * as studydocs from '../../models/studydocs';
import { isLoggedIn } from '../../models/auth';
import { Error401 } from '../errors';
import { Button, FilterView } from '../../components';
import { lectures } from '../studydocs/lectures';
import { i18n, currentLanguage } from '../../models/language';
import { log } from '../../models/log';
const tableHeadings = ['title', 'type'];
const tableHeadings = ['title', 'author', 'type'];
export default class studydocList {
constructor(vnode) {
export default class StudydocList {
oninit(vnode) {
this.vnode = vnode;
this.doc = {};
}
this.docLoaded = false;
this.lectureDropdownDisabled = true;
oninit() {
// initialize values for filter
this.semester = 1;
this.lecture = 'Fach';
this.search = '';
if (vnode.attrs.documentId) {
studydocs
.loadDocument(vnode.attrs.documentId)
.then(doc => {
this.selectDocument(doc);
})
.catch(() => {
this.selectDocument(undefined);
});
}
}
static selectDocument(doc) {
selectDocument(doc) {
this.docLoaded = true;
this.doc = doc;
}
isLectureDropdownDisabled() {
return this.lectureDropdownDisabled;
}
// dynamic lectures data based on selected semester and department
static loadLectures(values) {
loadLectures(values) {
if (!values.department) {
return [];
}
......@@ -57,12 +64,41 @@ export default class studydocList {
}
}
}
this.lectureDropdownDisabled = data.length <= 1;
return data;
}
static view() {
if (!isLoggedIn()) return m(Error401);
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', [
......@@ -86,18 +122,6 @@ export default class studydocList {
default: ['itet', 'mavt'],
values: [{ value: 'itet', label: 'D-ITET' }, { value: 'mavt', label: 'D-MAVT' }],
},
{
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: 'dropdown',
key: 'semester',
......@@ -115,8 +139,21 @@ export default class studydocList {
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'),
......@@ -139,7 +176,12 @@ export default class studydocList {
query[key] = value;
} else if (key === 'title' && value.length > 0) {
value = value.substring(0, value.length);
query[key] = { $regex: `^(?i).*${value}.*` };
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) {
......@@ -149,7 +191,6 @@ export default class studydocList {
delete query.type;
}
});
log(query);
studydocs.load(query);
},
}),
......@@ -162,34 +203,26 @@ export default class studydocList {
studydocs
.getList()
.map(doc => [
m('div.list-item', { onclick: () => this.selectDocument(doc) }, doc.title),
m('div.list-item', { onclick: () => this.selectDocument(doc) }, doc.type),
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
),
]),
]),
]),
// detail view of selected studydoc item
this.doc
? 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'),
},
}),
]),
])
: m(''),
documentView,
]);
}
}
......@@ -39,7 +39,7 @@
.content {
div.content-grid {
display:grid;
grid-template-columns: 70% auto;
grid-template-columns: 50% 30% auto;
grid-row-gap: 5px;
div {
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment