better responsiveness
This commit is contained in:
parent
8c36299596
commit
b6948ef0f1
@ -1,5 +1,5 @@
|
||||
<div class="fold">
|
||||
<div class="fold__inner" ref="inner">
|
||||
<div class="fold" :aria-expanded="visible ? 'true' : 'false'">
|
||||
<div class="fold__inner" ref="inner" :tabindex="visible ? false : -1">
|
||||
<lazy v-if="lazy" :activate="visible">
|
||||
<slot></slot>
|
||||
</lazy>
|
||||
|
@ -1,4 +1,4 @@
|
||||
<span class="line__symbol flex" :class="[`line--${line.type}`]">
|
||||
<span class="line__symbol flex" :class="{ [`line--${line.type}`]: true, 'line--night': line.night, 'line--fast': line.fast }">
|
||||
<span class="flex align-items-stretch">
|
||||
<span class="icon">
|
||||
<fa :icon="['fac', line.type]" fixed-width></fa>
|
||||
|
@ -1,6 +1,15 @@
|
||||
<ul class="messages list-unstyled">
|
||||
<li class="messages__message alert" :class="`alert-${type(message)}`" v-for="message in messages">
|
||||
<li class="message alert" :class="`alert-${type(message)}`" v-for="message in messages">
|
||||
<fa :icon="icon(message)" fixed-width></fa>
|
||||
{{ message.message }}
|
||||
|
||||
<div class="message__info">
|
||||
<small class="message__date">
|
||||
Komunikat ważny od
|
||||
{{ message.validFrom.format('HH:mm') }}
|
||||
do
|
||||
{{ message.validTo.format('HH:mm') }}
|
||||
</small>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
@ -1,37 +1,35 @@
|
||||
<div v-if="ready">
|
||||
<div class="row">
|
||||
<div class="col-md">
|
||||
<strong>Linie:</strong>
|
||||
<ul class="stop__lines list-unstyled list-inline">
|
||||
<li v-for="line in lines" class="list-inline-item mb-2">
|
||||
<line-symbol :line="line"></line-symbol>
|
||||
</li>
|
||||
</ul>
|
||||
<div v-if="ready" class="stop__details" v-responsive>
|
||||
<section>
|
||||
<strong>Linie:</strong>
|
||||
<ul class="stop__lines list-unstyled list-inline">
|
||||
<li v-for="line in lines" class="list-inline-item mb-2">
|
||||
<line-symbol :line="line"></line-symbol>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<strong>Na mapie:</strong>
|
||||
<div style="height: 350px">
|
||||
<l-map :center="stop.location" :zoom=17>
|
||||
<l-tile-layer url="http://{s}.tile.osm.org/{z}/{x}/{y}.png" attribution='© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'></l-tile-layer>
|
||||
<l-marker :lat-lng="stop.location"></l-marker>
|
||||
</l-map>
|
||||
</div>
|
||||
</div>
|
||||
<strong>Trasy:</strong>
|
||||
<ul class="stop__tracks list-underlined">
|
||||
<li v-for="{ track, order } in tracks" class="track">
|
||||
<div class="track__line">
|
||||
<line-symbol :line="track.line"></line-symbol>
|
||||
</div>
|
||||
<div class="track__description">
|
||||
{{ track.description }}
|
||||
</div>
|
||||
<span class="badge badge-pill badge-light track__order">#{{ order }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<div class="col-md">
|
||||
<strong>Trasy:</strong>
|
||||
<ul class="stop__tracks list-underlined">
|
||||
<li v-for="{ track, order } in tracks" class="track">
|
||||
<div class="track__line">
|
||||
<line-symbol :line="track.line"></line-symbol>
|
||||
</div>
|
||||
<div class="track__description">
|
||||
{{ track.description }}
|
||||
</div>
|
||||
<span class="badge badge-pill badge-light track__order">#{{ order }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
<section>
|
||||
<strong>Na mapie:</strong>
|
||||
<div style="height: 350px" tabindex="-1">
|
||||
<l-map :center="stop.location" :zoom=17>
|
||||
<l-tile-layer url="http://{s}.tile.osm.org/{z}/{x}/{y}.png" attribution='© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'></l-tile-layer>
|
||||
<l-marker :lat-lng="stop.location"></l-marker>
|
||||
</l-map>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
<div v-else class="text-center">
|
||||
<fa icon="spinner-third" pulse></fa>
|
||||
|
@ -16,7 +16,7 @@
|
||||
</slot>
|
||||
</div>
|
||||
|
||||
<fold :visible="details" class="stop__details" lazy>
|
||||
<fold :visible="details" class="stop__details-fold" lazy>
|
||||
<stop-details :stop="stop"></stop-details>
|
||||
</fold>
|
||||
|
||||
|
@ -3,6 +3,10 @@
|
||||
@extend .btn-link;
|
||||
|
||||
color: black;
|
||||
|
||||
&:focus {
|
||||
outline: 2px solid rgba($blue, .2);
|
||||
}
|
||||
}
|
||||
|
||||
&.btn-outline-action {
|
||||
|
@ -8,9 +8,25 @@
|
||||
padding: 0 .2rem;
|
||||
}
|
||||
|
||||
&.line--#{$type} .icon {
|
||||
background-color: $color;
|
||||
color: color-yiq($color);
|
||||
&.line--#{$type} {
|
||||
.icon {
|
||||
background-color: $color;
|
||||
color: color-yiq($color);
|
||||
}
|
||||
|
||||
.badge {
|
||||
background-color: transparent;
|
||||
color: $color;
|
||||
border: 1px solid $color;
|
||||
}
|
||||
}
|
||||
|
||||
&.line--night {
|
||||
.badge {
|
||||
background-color: $dark;
|
||||
color: $white;
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.stop__details {
|
||||
.stop__details-fold {
|
||||
flex-basis: 100%;
|
||||
.fold__inner { padding-bottom: .75rem; }
|
||||
}
|
||||
@ -29,4 +29,21 @@
|
||||
|
||||
.stop__tracks .line__symbol .badge {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.stop__details {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin: 0 (-$grid-gutter-width/2);
|
||||
|
||||
section {
|
||||
flex: 0 0 100%;
|
||||
padding: 0 $grid-gutter-width/2;
|
||||
}
|
||||
|
||||
&.size-lg {
|
||||
section {
|
||||
flex: 0 0 50%;
|
||||
}
|
||||
}
|
||||
}
|
@ -15,6 +15,11 @@ $line-types: (
|
||||
'unknown': $dark
|
||||
);
|
||||
|
||||
$default-spacing: .5rem;
|
||||
|
||||
$alert-margin-bottom: $default-spacing;
|
||||
$headings-margin-bottom: $default-spacing;
|
||||
|
||||
@import "~bootstrap/scss/bootstrap";
|
||||
|
||||
@import "common";
|
||||
|
@ -4,6 +4,8 @@ import { Message } from "../model/message";
|
||||
import urls from "../urls";
|
||||
|
||||
import { faInfoCircle, faExclamationTriangle, faQuestionCircle } from "@fortawesome/pro-light-svg-icons";
|
||||
import { Jsonified } from "../utils";
|
||||
import moment = require("moment");
|
||||
|
||||
@Component({ template: require("../../components/messages.html") })
|
||||
export class MessagesComponent extends Vue {
|
||||
@ -18,7 +20,15 @@ export class MessagesComponent extends Vue {
|
||||
const response = await fetch(urls.prepare(urls.messages));
|
||||
|
||||
if (response.ok) {
|
||||
this.messages = await response.json();
|
||||
const messages = (await response.json()) as Jsonified<Message>[];
|
||||
this.messages = messages.map(m => {
|
||||
const message = m as Message;
|
||||
|
||||
message.validFrom = moment(m.validFrom);
|
||||
message.validTo = moment(m.validTo);
|
||||
|
||||
return message;
|
||||
});
|
||||
}
|
||||
|
||||
this.$emit('update', this.messages);
|
||||
|
@ -1,11 +1,11 @@
|
||||
export interface Decorator<TArgs extends any[], FArgs extends any[], TRet, FRet> {
|
||||
decorate(f: (...farg: FArgs) => FRet, ...args: TArgs): (...farg: FArgs) => TRet;
|
||||
export interface Decorator<TArgs extends any[], FArgs extends any[], TRet extends any, FRet extends any> {
|
||||
decorate(f: (...farg: FArgs) => any, ...args: TArgs): (...farg: FArgs) => TRet;
|
||||
|
||||
(...args: TArgs): (target, name: string | symbol, descriptor: TypedPropertyDescriptor<(...farg: FArgs) => FRet>) => void;
|
||||
}
|
||||
|
||||
export function decorator<TArgs extends any[], FArgs extends any[], TRet, FRet>
|
||||
(decorate: (f: (...fargs: FArgs) => FRet, ...args: TArgs) => (...fargs: FArgs) => TRet)
|
||||
export function decorator<TArgs extends any[], FArgs extends any[], TRet extends any, FRet extends any>
|
||||
(decorate: (f: (...farg: FArgs) => FRet, ...args: TArgs) => (...farg: FArgs) => TRet)
|
||||
: Decorator<TArgs, FArgs, TRet, FRet> {
|
||||
|
||||
const factory = function (this: Decorator<TArgs, FArgs, TRet, FRet>, ...args: TArgs) {
|
||||
@ -43,3 +43,11 @@ export const debounce = decorator(function (decorated, time: number, max: number
|
||||
}, time);
|
||||
}
|
||||
});
|
||||
|
||||
export const condition = decorator(function <Args extends any[], Ret extends any>(decorated: (...args: Args) => Ret, predicate: (...args: Args) => boolean) {
|
||||
return function (this: any, ...args: Args) {
|
||||
if (predicate(...args)) {
|
||||
return decorated(...args);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { signed } from "./utils";
|
||||
import Vue from 'vue';
|
||||
import { condition } from "./decorators";
|
||||
|
||||
Vue.filter('signed', signed);
|
||||
|
||||
@ -18,6 +19,40 @@ Vue.directive('hover', (el, binding, node) => {
|
||||
}
|
||||
};
|
||||
|
||||
el.addEventListener('mouseenter', e => update(true, e));
|
||||
el.addEventListener('mouseleave', e => update(false, e));
|
||||
});
|
||||
const activate = event => update(true, event);
|
||||
const deactivate = event => update(false, event);
|
||||
|
||||
el.addEventListener('mouseenter', activate);
|
||||
el.addEventListener('click', activate);
|
||||
el.addEventListener('keydown', condition.decorate(deactivate, e => e.keyCode == 27));
|
||||
el.addEventListener('mouseleave', deactivate);
|
||||
el.addEventListener('blur', deactivate);
|
||||
});
|
||||
|
||||
Vue.directive('responsive', (el, binding) => {
|
||||
const breakpoints = typeof binding.value === 'object' ? binding.value : {
|
||||
'xs': 0,
|
||||
'sm': 576,
|
||||
'md': 768,
|
||||
'lg': 1024,
|
||||
'xl': 1200,
|
||||
};
|
||||
|
||||
const resize = () => {
|
||||
const width = el.scrollWidth;
|
||||
el.classList.remove(...Object.keys(breakpoints).map(breakpoint => `size-${breakpoint}`));
|
||||
|
||||
for (let [ breakpoint, size ] of Object.entries(breakpoints)) {
|
||||
if (width < size) {
|
||||
break;
|
||||
}
|
||||
|
||||
el.classList.add(`size-${breakpoint}`);
|
||||
}
|
||||
};
|
||||
|
||||
resize();
|
||||
if (!binding.modifiers['once']) {
|
||||
window.addEventListener('resize', resize);
|
||||
}
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user