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