To receive notifications about scheduled maintenance, please subscribe to the mailing-list gitlab-operations@sympa.ethz.ch. You can subscribe to the mailing-list at https://sympa.ethz.ch

Commit e9d19d21 authored by gehril's avatar gehril Committed by Hermann
Browse files

Feature/sorting tables

parent d942c259
......@@ -18,7 +18,7 @@
"@material/drawer": "^0.30.0",
"@material/select": "^0.35.1",
"ajv": "^5.5.0",
"amiv-web-ui-components": "git+https://git@gitlab.ethz.ch/amiv/web-ui-components.git#9c3d54e1e60bba007b44c6d293c724a96be1e991",
"amiv-web-ui-components": "git+https://git@gitlab.ethz.ch/amiv/web-ui-components.git#9ff18ff584dca8282fce81ae8ace97a9dd1cbd98",
"axios": "^0.17.1",
"client-oauth2": "^4.2.0",
"mithril": "^1.1.6",
......
......@@ -59,7 +59,7 @@ export default class BlacklistTable {
return m(TableView, {
clickOnRows: false,
controller: this.ctrl,
keys: [],
keys: [null, null],
tileContent: data => this.getItemData(data),
titles: [
{ text: 'User', width: '18em' },
......
import m from 'mithril';
import { DatalistController } from 'amiv-web-ui-components';
import { events as config } from '../resourceConfig.json';
import TableView from '../views/tableView';
import { dateFormatter } from '../utils';
import { ResourceHandler } from '../auth';
......@@ -30,7 +29,7 @@ export default class EventTable {
const now = new Date();
return m(TableView, {
controller: this.ctrl,
keys: config.tableKeys,
keys: ['titel_en', 'time_start', 'time_end'],
tileContent: this.getItemData,
titles: [
{ text: 'Titel', width: 'calc(100% - 18em)' },
......
import m from 'mithril';
import { DatalistController } from 'amiv-web-ui-components';
import { joboffers as config } from '../resourceConfig.json';
import TableView from '../views/tableView';
import { dateFormatter } from '../utils';
import { ResourceHandler } from '../auth';
......@@ -14,7 +13,7 @@ import { ResourceHandler } from '../auth';
export default class JobTable {
constructor() {
this.handler = new ResourceHandler('joboffers', config.tableKeys);
this.handler = new ResourceHandler('joboffers');
this.ctrl = new DatalistController((query, search) => this.handler.get({ search, ...query }));
}
......@@ -26,13 +25,13 @@ export default class JobTable {
];
}
view() {
view(data) {
return m(TableView, {
controller: this.ctrl,
keys: config.tableKeys,
keys: [(data.title_de) ? 'title_de' : 'title_en', 'company', 'time_end'],
tileContent: this.getItemData,
titles: [
{ text: 'Titel', width: 'calc(100% - 30em)' },
{ text: 'Title', width: 'calc(100% - 30em)' },
{ text: 'Company', width: '21em' },
{ text: 'End', width: '9em' },
],
......
......@@ -28,6 +28,7 @@ export default class RelationlistController {
this.query2 = secondaryQuery || {};
this.filter = null;
this.filter2 = null;
this.sort = null;
this.includeWithoutRelation = includeWithoutRelation;
// state pointer that is counted up every time the table is refreshed so
// we can tell infinite scroll that the data-version has changed.
......@@ -63,6 +64,7 @@ export default class RelationlistController {
query.max_results = 10;
query.page = pageNum;
query.where = { ...this.filter, ...this.query.where };
query.sort = this.sort || query.sort;
return new Promise((resolve) => {
this.handler.get(query).then((data) => {
......@@ -161,4 +163,9 @@ export default class RelationlistController {
this.query = Object.assign({}, query, { search: this.query.search });
this.refresh();
}
setSort(sort) {
this.sort = sort;
this.refresh();
}
}
......@@ -47,12 +47,12 @@
},
"users": {
"keyDescriptors": {
"legi": "Legi Number",
"legi": "Legi",
"firstname": "First Name",
"lastname": "Last Name",
"rfid": "RFID",
"phone": "Phone",
"nethz": "nethz Account",
"nethz": "nethz",
"gender": "Gender",
"department": "Department",
"email": "Email"
......
import m from 'mithril';
import { DatalistController } from 'amiv-web-ui-components';
import { studydocuments as config } from '../resourceConfig.json';
import TableView from '../views/tableView';
import { ResourceHandler } from '../auth';
......@@ -8,7 +7,7 @@ import { ResourceHandler } from '../auth';
/* Table of all studydocuments */
export default class StudydocTable {
constructor() {
this.handler = new ResourceHandler('studydocuments', config.tableKeys);
this.handler = new ResourceHandler('studydocuments');
this.ctrl = new DatalistController((query, search) => this.handler.get({ search, ...query }));
}
......@@ -29,7 +28,7 @@ export default class StudydocTable {
view() {
return m(TableView, {
controller: this.ctrl,
keys: config.tableKeys,
keys: ['title', 'author', 'course_year', 'semester', 'lecture'],
tileContent: this.getItemData,
titles: [
{ text: 'Title', width: 'calc(100% - 36em)' },
......
......@@ -22,6 +22,7 @@ export const icons = {
studydoc: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M0 0h24v24H0z" fill="none"/><path d="M5 13.18v4L12 21l7-3.82v-4L12 17l-7-3.82zM12 3L1 9l11 6 9-4.91V17h2V9L12 3z"/></svg>',
blacklist: '<svg style="width:24px;height:24px" viewBox="0 0 24 24"><path fill="#000000" d="M22.5,2.09C21.6,3 20.13,3.73 18.31,4.25C16.59,2.84 14.39,2 12,2C9.61,2 7.41,2.84 5.69,4.25C3.87,3.73 2.4,3 1.5,2.09C1.53,3.72 2.35,5.21 3.72,6.4C2.63,8 2,9.92 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12C22,9.92 21.37,8 20.28,6.4C21.65,5.21 22.47,3.72 22.5,2.09M7.5,8.5L10.5,10C10.5,10.8 9.8,11.5 9,11.5C8.2,11.5 7.5,10.8 7.5,10V8.5M12,17.23C10.25,17.23 8.71,16.5 7.81,15.42L9.23,14C9.68,14.72 10.75,15.23 12,15.23C13.25,15.23 14.32,14.72 14.77,14L16.19,15.42C15.29,16.5 13.75,17.23 12,17.23M16.5,10C16.5,10.8 15.8,11.5 15,11.5C14.2,11.5 13.5,10.8 13.5,10L16.5,8.5V10Z" /></svg>',
error: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path d="M11 15h2v2h-2zm0-8h2v6h-2zm.99-5C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z"/></svg>',
sortingArrow: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M7 10l5 5 5-5z"/><path d="M0 0h24v24H0z" fill="none"/></svg>',
};
// Property as specified by material design: small, grey title and larger
......
import m from 'mithril';
import infinite from 'mithril-infinite';
import { List, ListTile, Toolbar, Search, Button } from 'polythene-mithril';
import { List, ListTile, Toolbar, Search, Button, Icon } from 'polythene-mithril';
import 'polythene-css';
import { styler } from 'polythene-core-css';
import { FilterChip } from './elements';
import { FilterChip, icons } from './elements';
const tableStyles = [
{
......@@ -40,15 +40,19 @@ export default class TableView {
constructor({
attrs: {
keys,
titles,
tileContent,
filters = null,
clickOnRows = (data) => { m.route.set(`/${data._links.self.href}`); },
clickOnTitles = (controller, title) => { controller.setSort([[title, 1]]); },
},
}) {
this.search = '';
this.tableKeys = keys || [];
this.tableTitles = titles;
this.tileContent = tileContent;
this.clickOnRows = clickOnRows;
this.clickOnTitles = clickOnTitles;
this.searchValue = '';
// make a copy of filters so we can toggle the selected status
this.filters = filters ? filters.map(filterGroup =>
......@@ -107,6 +111,18 @@ export default class TableView {
return Object.assign({}, ...selectedFilters);
}
// Display an arrow at the table title that allows sorting
arrowOrNot(controller, title) {
const titleText = title.width ? title.text : title;
if (!controller.sort) return false;
let i;
for (i = 0; i < this.tableTitles.length; i += 1) {
const tableTitlei = this.tableTitles[i].width ?
this.tableTitles[i].text : this.tableTitles[i];
if (tableTitlei === titleText) break;
}
return this.tableKeys[i] === controller.sort[0][0];
}
view({
attrs: {
......@@ -192,14 +208,25 @@ export default class TableView {
tiles: [
m(ListTile, {
className: 'tableTile',
hoverable: this.clickOnTitles,
content: m(
'div',
{ style: { width: '100%', display: 'flex' } },
// Either titles is a list of titles that are distributed equally,
// or it is a list of objects with text and width
titles.map(title => m('div', {
style: { width: title.width || `${98 / this.tableKeys.length}%` },
}, title.width ? title.text : title)),
titles.map((title, i) => m(
'div', {
onclick: () => {
if (this.clickOnTitles && this.tableKeys[i]) {
this.clickOnTitles(controller, this.tableKeys[i]);
}
},
style: { width: title.width || `${98 / this.tableKeys.length}%` },
},
[title.width ? title.text : title,
this.arrowOrNot(controller, title) ?
m(Icon, { svg: { content: m.trust(icons.sortingArrow) } }) : ''],
)),
),
}),
m(infinite, controller.infiniteScrollParams(this.item())),
......@@ -208,4 +235,3 @@ export default class TableView {
]);
}
}
Markdown is supported
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