Skip to content
Snippets Groups Projects
Commit 28b2773c authored by Hermann's avatar Hermann
Browse files

basics for filtering in lists

parent c579178b
No related branches found
No related tags found
No related merge requests found
...@@ -14,6 +14,7 @@ export default class DatalistController { ...@@ -14,6 +14,7 @@ export default class DatalistController {
} }
this.query = query || {}; this.query = query || {};
this.search = null; this.search = null;
this.filter = null;
// state pointer that is counted up every time the table is refreshed so // state pointer that is counted up every time the table is refreshed so
// we can tell infinite scroll that the data-version has changed. // we can tell infinite scroll that the data-version has changed.
this.stateCounter = Stream(0); this.stateCounter = Stream(0);
...@@ -45,6 +46,7 @@ export default class DatalistController { ...@@ -45,6 +46,7 @@ export default class DatalistController {
const query = Object.assign({}, this.query); const query = Object.assign({}, this.query);
query.max_results = 10; query.max_results = 10;
query.page = pageNum; query.page = pageNum;
query.where = { ...this.filter, ...this.query.where };
return new Promise((resolve) => { return new Promise((resolve) => {
this.handler.get(query).then((data) => { this.handler.get(query).then((data) => {
...@@ -100,6 +102,11 @@ export default class DatalistController { ...@@ -100,6 +102,11 @@ export default class DatalistController {
} }
} }
setFilter(filter) {
this.filter = filter;
this.refresh();
}
setQuery(query) { setQuery(query) {
this.query = query; this.query = query;
this.query.search = this.search; this.query.search = this.search;
......
...@@ -289,33 +289,37 @@ export class chip { ...@@ -289,33 +289,37 @@ export class chip {
view({ view({
attrs: { attrs: {
svg, svg,
color = '#000000', background = '#ffffff',
background = '#dddddd', textColor = '#000000',
...styleAttrs svgColor = '#000000',
svgBackground = '#dddddd',
...attrs
}, },
children, children,
}) { }) {
return m('div', { return m('div', {
style: { style: {
height: '32px', height: '32px',
'background-color': '#ffffff', 'background-color': background,
color: textColor,
'border-radius': '16px', 'border-radius': '16px',
// if there is a border, things are weirdly shifted // if there is a border, things are weirdly shifted
padding: styleAttrs.border ? '3px 8px 4px 6px' : '4px 8px', padding: attrs.border ? '3px 8px 4px 6px' : '4px 8px',
display: 'inline-flex', display: 'inline-flex',
...styleAttrs, ...attrs,
}, },
...attrs.onclick ? { onclick: attrs.onclick } : {},
}, [ }, [
svg && m('div', { svg && m('div', {
style: { style: {
'background-color': background, 'background-color': svgBackground,
'border-radius': '12px', 'border-radius': '12px',
margin: '0px 4px 0px -2px', margin: '0px 4px 0px -2px',
height: '24px', height: '24px',
width: '24px', width: '24px',
padding: '2px 2px 2px 4px', padding: '2px 2px 2px 4px',
}, },
}, m(Icon, { svg: { content: m.trust(svg) }, size: 'small', style: { color } })), }, m(Icon, { svg: { content: m.trust(svg) }, size: 'small', style: { svgColor } })),
m('div', { style: { 'line-height': '24px' } }, children), m('div', { style: { 'line-height': '24px' } }, children),
]); ]);
} }
......
...@@ -3,22 +3,14 @@ import infinite from 'mithril-infinite'; ...@@ -3,22 +3,14 @@ import infinite from 'mithril-infinite';
import { List, ListTile, Toolbar, Search, Button } from 'polythene-mithril'; import { List, ListTile, Toolbar, Search, Button } from 'polythene-mithril';
import 'polythene-css'; import 'polythene-css';
import { styler } from 'polythene-core-css'; import { styler } from 'polythene-core-css';
import { chip, icons } from './elements';
const tableStyles = [ const tableStyles = [
{ {
'.tabletool': {
display: 'grid',
height: '100%',
'grid-template-rows': '48px calc(100% - 78px)',
'background-color': 'white',
},
'.toolbar': { '.toolbar': {
'grid-row': 1, 'grid-row': 1,
display: 'flex', display: 'flex',
}, },
'.scrollTable': {
'grid-row': 2,
},
'.tableTile': { '.tableTile': {
padding: '10px', padding: '10px',
'border-bottom': '1px solid rgba(0, 0, 0, 0.12)', 'border-bottom': '1px solid rgba(0, 0, 0, 0.12)',
...@@ -29,6 +21,22 @@ const tableStyles = [ ...@@ -29,6 +21,22 @@ const tableStyles = [
styler.add('tableview', tableStyles); styler.add('tableview', tableStyles);
class FilterChip {
view({ attrs: { selected = false, onclick = () => {} }, children }) {
return m(chip, {
'margin-left': '5px',
'margin-right': '5px',
background: selected ? '#aaaaaa' : '#dddddd',
svgBackground: '#aaaaaa',
textColor: selected ? '#000000' : '#999999',
svgColor: '#000000',
svg: selected ? icons.checked : null,
onclick,
}, children);
}
}
export default class TableView { export default class TableView {
/* Shows a table of objects for a given API resource. /* Shows a table of objects for a given API resource.
* *
...@@ -40,11 +48,16 @@ export default class TableView { ...@@ -40,11 +48,16 @@ export default class TableView {
* Works with embedded resources, i.e. if you add * Works with embedded resources, i.e. if you add
* { embedded: { event: 1 } } to a list of eventsignups, * { embedded: { event: 1 } } to a list of eventsignups,
* you can display event.title_de as a table key * you can display event.title_de as a table key
* - filters: list of list of objects, each inner list is a group of mutual exclusive
* filters.
* A filter can have properties 'name', 'query' and optionally 'selected' for
* the initial selection state.
*/ */
constructor({ constructor({
attrs: { attrs: {
keys, keys,
tileContent, tileContent,
filters = null,
clickOnRows = (data) => { m.route.set(`/${data._links.self.href}`); }, clickOnRows = (data) => { m.route.set(`/${data._links.self.href}`); },
}, },
}) { }) {
...@@ -53,6 +66,9 @@ export default class TableView { ...@@ -53,6 +66,9 @@ export default class TableView {
this.tileContent = tileContent; this.tileContent = tileContent;
this.clickOnRows = clickOnRows; this.clickOnRows = clickOnRows;
this.searchValue = ''; this.searchValue = '';
// make a copy of filters so we can toggle the selected status
this.filters = filters ? filters.map(filterGroup =>
filterGroup.map(filter => Object.assign({}, filter))) : null;
} }
getItemData(data) { getItemData(data) {
...@@ -93,7 +109,15 @@ export default class TableView { ...@@ -93,7 +109,15 @@ export default class TableView {
tableHeight = false, tableHeight = false,
}, },
}) { }) {
return m('div.tabletool', [ return m('div.tabletool', {
style: {
display: 'grid',
height: '100%',
'grid-template-rows': this.filters ?
'48px 40px calc(100% - 78px)' : '48px calc(100% - 78px)',
'background-color': 'white',
},
}, [
m(Toolbar, { m(Toolbar, {
className: 'toolbar', className: 'toolbar',
compact: true, compact: true,
...@@ -119,9 +143,45 @@ export default class TableView { ...@@ -119,9 +143,45 @@ export default class TableView {
}) : '', }) : '',
], ],
}), }),
// please beare with this code, it is the only way possible to track the selection
// status of all the filters of the same group and make sure that they are really
// mutually exclusive (that way when you click on one filter in the group, the other
// ones in this group will be deselected)
this.filters && m('div', {
style: {
height: '40px',
'overflow-x': 'scroll',
'white-space': 'nowrap',
padding: '0px 5px',
},
}, [].concat(['Filters: '], ...[...this.filters.keys()].map(filterGroupIdx =>
[...this.filters[filterGroupIdx].keys()].map((filterIdx) => {
const thisFilter = this.filters[filterGroupIdx][filterIdx];
return m(FilterChip, {
selected: thisFilter.selected,
onclick: () => {
if (!thisFilter.selected) {
// set all filters in this group to false
[...this.filters[filterGroupIdx].keys()].forEach((i) => {
this.filters[filterGroupIdx][i].selected = false;
});
// now set this filter to selected
this.filters[filterGroupIdx][filterIdx].selected = true;
console.log('filter set: ', thisFilter.query);
controller.setFilter(thisFilter.query);
} else {
this.filters[filterGroupIdx][filterIdx].selected = false;
controller.setFilter({});
}
},
}, thisFilter.name);
})))),
m(List, { m(List, {
className: 'scrollTable', className: 'scrollTable',
style: tableHeight ? { height: tableHeight } : {}, style: {
'grid-row': this.filters ? 3 : 2,
...tableHeight ? { height: tableHeight } : {},
},
tiles: [ tiles: [
m(ListTile, { m(ListTile, {
className: 'tableTile', className: 'tableTile',
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment