Commit 8f99219f authored by Sandro Lutz's avatar Sandro Lutz
Browse files

Make filtered list page responsive

parent 4d5e61dc
<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="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z"/>
</svg>
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
height="24px" viewBox="0 0 24 24" enable-background="new 0 0 24 24" xml:space="preserve">
<g id="Bounding_Boxes">
<path fill="none" d="M0,0h24v24H0V0z"/>
</g>
<g id="Sharp">
<path d="M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41z"/>
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<path d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"/>
<path d="M0 0h24v24H0z" fill="none"/>
</svg>
......@@ -98,6 +98,10 @@
"studydocs.upload": "Dokument(e) hochladen",
"studydocs.uploading": "lädt hoch...",
"studydocs.access_denied": "Studienunterlagen sind nur für ETH Studenten verfügbar.",
"events.header_open_registration": "Anmeldung offen",
"events.header_upcoming": "Bevorstehende Events",
"events.header_past": "Vergangene Events",
"events.no_upcoming": "Keine bevorstehenden Events.",
"events.searchfield": "Suchtext eingeben...",
"events.price": "Preis",
"events.free": "Gratis",
......@@ -137,6 +141,9 @@
"errors.access_denied.default_reason": "Diese Seite ist nur für eingeloggte Benutzer verfügbar.",
"errors.not_found.text": "Die gewünschte Seite konnte nicht gefunden werden.",
"errors.translation_unavailable": "Übersetzung nicht verfügbar.",
"errors.shown_language": "Zeige Text in %{shown_language}"
"errors.shown_language": "Zeige Text in %{shown_language}",
"filtered_list.show_filter": "Filter anzeigen",
"filtered_list.hide_filter": "Filter verstecken",
"filtered_list.show_list": "Zurück zur Übersicht"
}
}
......@@ -98,6 +98,10 @@
"studydocs.upload": "Upload study document(s)",
"studydocs.uploading": "Uploading...",
"studydocs.access_denied": "Study documents are available only for ETH students.",
"events.header_open_registration": "Open Registration",
"events.header_upcoming": "Upcoming Events",
"events.header_past": "Past Events",
"events.no_upcoming": "No upcoming events.",
"events.searchfield": "Enter search text...",
"events.price": "Price",
"events.free": "Free",
......@@ -137,6 +141,9 @@
"errors.access_denied.default_reason": "This page is accessible only for authenticated users.",
"errors.not_found.text": "The page you are looking for could not be found.",
"errors.translation_unavailable": "Translation not available.",
"errors.shown_language": "Showing text in %{shown_language}"
"errors.shown_language": "Showing text in %{shown_language}",
"filtered_list.show_filter": "Show filter",
"filtered_list.hide_filter": "Hide filter",
"filtered_list.show_list": "Back to the list"
}
}
......@@ -89,6 +89,19 @@ export default class PaginationController {
return this._pages.map(page => callback(page.items));
}
/**
* Get number of loaded items
*
* @return {int}
*/
get length() {
let length = 0;
this._pages.forEach(page => {
length += page.items.length;
});
return length;
}
/**
* Get data of a specific page
*
......
......@@ -10,8 +10,10 @@
@import './legalNotice.less';
@import './header.less';
@import './footer.less';
@import './filteredListPage.less';
@import './eventList.less';
@import './eventDetails.less';
@import './studydocList.less';
@import './jobofferList.less';
html,body {
......@@ -59,7 +61,6 @@ section {
main {
width: 100%;
min-height: 100%;
> * {
max-width: @dimension-max-content-width;
......
@import './listview.less';
#event-list {
.listview;
div {
border: none;
}
.registration {
background-color: #fff;
}
......
@import './colors.less';
.filtered-list {
min-height: 100%;
display: grid;
grid-template-columns: 25% 40% auto;
@media @tablet {
grid-template-columns: 40% auto;
}
@media @mobile {
display: block;
padding: 0;
}
&.no-details {
grid-template-columns: 20% auto;
}
&.mobile-show-details {
@media @mobile, @tablet {
div.filter-container {
display: none;
}
.content {
display: none;
}
}
}
&.mobile-show-filter {
@media @mobile {
div.filter-container {
display: block;
}
}
}
.action-button {
display: none;
cursor: pointer;
padding: .5em;
text-align: center;
background-color: @color-grey;
line-height: 1.5em;
height: 1.5em;
z-index: 100;
@media @mobile {
display: block;
}
&:hover {
color: @color-red;
}
img {
height: 100%;
margin-right: .5em;
}
span {
vertical-align: super;
}
}
div.filter,div.details {
position: sticky;
top: 0;
padding: 5px;
@media @mobile {
position: relative;
top: 0 !important;
padding: 0;
}
}
.filter-container {
@media @mobile {
display: none;
border-bottom: 1em solid @color-grey;
padding: 1em;
}
}
.filter {
display: grid;
align-content: start;
grid-gap: 20px;
h4 {
margin: 0;
}
form {
display: grid;
grid-row: auto auto;
}
.check,.drop,.radio {
display: grid;
grid-row: auto auto;
grid-gap: 10px;
}
}
.content {
border: 3px solid @color-grey;
border-width: 0 3px;
@media @mobile {
border: none;
}
div.list-header {
position: sticky;
top: 0;
z-index: 10;
background-color: @color-dark-blue;
color: @color-white;
}
div.list-placeholder {
display: inline-block;
width: 100%;
padding: 2em 0;
text-align: center;
background-color: @color-white;
}
div.list-item {
border-bottom: 1px solid @color-grey;
cursor: pointer;
&:last-of-type {
border: none;
}
}
h2,h4 {
margin: 0;
padding: 1em;
}
}
div.load-more-items {
display: inline-block;
width: 100%;
padding: 1em 0;
text-align: center;
&.active {
cursor: pointer;
}
}
.details-container {
@media @tablet {
grid-column: ~'1 / 3';
}
}
div.details {
z-index: 101;
@media @mobile, @tablet {
&.mobile-hide {
display: none;
}
}
}
.tablet-show {
@media @tablet {
display: block;
grid-column: ~'1 / 3';
background-color: @color-white;
border-top: 3px solid @color-white;
border-bottom: 3px solid @color-grey;
}
}
}
@import './listview.less';
#joboffer-list {
.listview;
div {
border: none;
}
.list-item {
border-bottom: 1px solid #000;
cursor: pointer;
......
.listview {
min-height: 100%;
display: grid;
grid-template-columns: 20% 30% auto;
&.no-details {
grid-template-columns: 20% auto;
}
div.content {
border: 1px solid #000;
border-width: 0 1px;
}
div.filter,div.details {
position: sticky;
top: 0;
padding: 5px;
}
.filter {
display: grid;
grid-template-rows: auto auto auto auto;
align-content: start;
grid-gap: 20px;
form {
display: grid;
grid-row: auto auto;
}
.check,.drop {
display: grid;
grid-row: auto auto;
grid-gap: 10px;
}
}
.content {
div.list-item {
border-bottom: 1px solid #000;
cursor: pointer;
h2 {
margin: 0;
padding: 1em 0;
}
}
}
div.load-more-items {
display: inline-block;
width: 100%;
padding: 1em 0;
text-align: center;
&.active {
cursor: pointer;
}
}
}
@import './listview.less';
#studydoc-list {
.listview;
div {
border: none;
}
div.list-item {
display: grid;
grid-template-columns: auto 20% 40%;
......
......@@ -110,25 +110,42 @@ export default class EventList extends FilteredListPage {
}
get _listView() {
return [
m(
'div.registration',
controller.openRegistrationEvents.map(page =>
const openRegistrationList = [];
const upcomingList = [];
console.log(controller.openRegistrationEvents.length);
console.log(controller.upcomingEvents.length);
console.log(controller.pastEvents.length);
if (controller.openRegistrationEvents.length > 0) {
openRegistrationList.push(
m('div.list-header', m('h4', i18n('events.header_open_registration'))),
...controller.openRegistrationEvents.map(page =>
page.map(event => this.constructor._renderEventListItem(event, 'registration'))
)
),
m(
'div.upcoming',
controller.upcomingEvents.map(page =>
);
}
if (controller.upcomingEvents.length > 0) {
upcomingList.push(
m('div.list-header', m('h4', i18n('events.header_upcoming'))),
...controller.upcomingEvents.map(page =>
page.map(event => this.constructor._renderEventListItem(event, 'upcoming'))
)
),
m(
'div.past',
controller.pastEvents.map(page =>
);
} else if (controller.openRegistrationEvents.length === 0) {
upcomingList.push(m('div.list-placeholder', i18n('events.no_upcoming')));
}
return [
m('div.registration', openRegistrationList),
m('div.upcoming', upcomingList),
m('div.past', [
m('div.list-header', m('h4', i18n('events.header_past'))),
...controller.pastEvents.map(page =>
page.map(event => this.constructor._renderEventListItem(event, 'past'))
)
),
),
]),
];
}
......
......@@ -2,6 +2,9 @@ import m from 'mithril';
import { error } from '../models/log';
import { i18n } from '../models/language';
import { FilterView } from '../components';
import filterIcon from '../images/filterList.svg';
import closeIcon from '../images/close.svg';
import backIcon from '../images/back.svg';
/**
* FilteredListDataStore class
......@@ -106,6 +109,7 @@ export class FilteredListPage {
this.name = name;
this.dataStore = dataStore;
this.hasDetailsPage = hasDetailsPage;
this.mobileViewShowFilter = false;
}
/**
......@@ -282,30 +286,77 @@ export class FilteredListPage {
}
view() {
const classes = ['filtered-list'];
if (!this.hasDetailsPage) {
classes.push('no-details');
}
if (this.mobileViewShowFilter) {
classes.push('mobile-show-filter');
}
if (this.detailsItemId) {
classes.push('mobile-show-details');
}
let mobileButton;
if (this.detailsItemId) {
mobileButton = m(
'div.action-button.tablet-show',
{
onclick: () => {
const route = m.route.get();
m.route.set(route.substring(0, route.lastIndexOf('/')));
},
},
[m('img', { src: backIcon }), m('span', i18n('filtered_list.show_list'))]
);
} else if (this.mobileViewShowFilter) {
mobileButton = m(
'div.action-button',
{
onclick: () => {
this.mobileViewShowFilter = false;
},
},
[m('img', { src: closeIcon }), m('span', i18n('filtered_list.hide_filter'))]
);
} else {
mobileButton = m(
'div.action-button',
{
onclick: () => {
this.mobileViewShowFilter = true;
},
},
[m('img', { src: filterIcon }), m('span', i18n('filtered_list.show_filter'))]
);
}
return m(
`div#${this.name}-list`,
{
class: !this.hasDetailsPage ? 'no-details' : '',
class: classes.join(' '),
},
[
m('div', this._filterView),
mobileButton,
m('div.filter-container', this._filterView),
m('div.content', this._listContainerView),
this.hasDetailsPage ? m('div', this._detailsContainerView) : m(''),
this.hasDetailsPage ? m('div.details-container', this._detailsContainerView) : m(''),
]
);
}
get _filterView() {
return m(
'div.filter',
{
id: `${this.name}ListFilterView`,
style: {
top: `${this.dataStore.getPositionTop('filterView')}px`,
return [
m(
'div.filter',
{
id: `${this.name}ListFilterView`,
style: {
top: `${this.dataStore.getPositionTop('filterView')}px`,
},
},
},
m(FilterView, { ...{ values: this.dataStore }, ...this._filterViewAttributes })
);
m(FilterView, { ...{ values: this.dataStore }, ...this._filterViewAttributes })
),
];
}
get _listContainerView() {
......@@ -363,9 +414,10 @@ export class FilteredListPage {
return m('');
}
return m(
'div.details',
'div',
{
id: `${this.name}ListDetailsView`,
class: 'details mobile-hide',
style: {
top: `${this.dataStore.getPositionTop('detailsView')}px`,
},
......
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