better responsiveness
This commit is contained in:
parent
8c36299596
commit
b6948ef0f1
@ -1,5 +1,5 @@
|
|||||||
<div class="fold">
|
<div class="fold" :aria-expanded="visible ? 'true' : 'false'">
|
||||||
<div class="fold__inner" ref="inner">
|
<div class="fold__inner" ref="inner" :tabindex="visible ? false : -1">
|
||||||
<lazy v-if="lazy" :activate="visible">
|
<lazy v-if="lazy" :activate="visible">
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</lazy>
|
</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="flex align-items-stretch">
|
||||||
<span class="icon">
|
<span class="icon">
|
||||||
<fa :icon="['fac', line.type]" fixed-width></fa>
|
<fa :icon="['fac', line.type]" fixed-width></fa>
|
||||||
|
@ -1,6 +1,15 @@
|
|||||||
<ul class="messages list-unstyled">
|
<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>
|
<fa :icon="icon(message)" fixed-width></fa>
|
||||||
{{ message.message }}
|
{{ 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>
|
</li>
|
||||||
</ul>
|
</ul>
|
@ -1,37 +1,35 @@
|
|||||||
<div v-if="ready">
|
<div v-if="ready" class="stop__details" v-responsive>
|
||||||
<div class="row">
|
<section>
|
||||||
<div class="col-md">
|
<strong>Linie:</strong>
|
||||||
<strong>Linie:</strong>
|
<ul class="stop__lines list-unstyled list-inline">
|
||||||
<ul class="stop__lines list-unstyled list-inline">
|
<li v-for="line in lines" class="list-inline-item mb-2">
|
||||||
<li v-for="line in lines" class="list-inline-item mb-2">
|
<line-symbol :line="line"></line-symbol>
|
||||||
<line-symbol :line="line"></line-symbol>
|
</li>
|
||||||
</li>
|
</ul>
|
||||||
</ul>
|
|
||||||
|
|
||||||
<strong>Na mapie:</strong>
|
<strong>Trasy:</strong>
|
||||||
<div style="height: 350px">
|
<ul class="stop__tracks list-underlined">
|
||||||
<l-map :center="stop.location" :zoom=17>
|
<li v-for="{ track, order } in tracks" class="track">
|
||||||
<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>
|
<div class="track__line">
|
||||||
<l-marker :lat-lng="stop.location"></l-marker>
|
<line-symbol :line="track.line"></line-symbol>
|
||||||
</l-map>
|
</div>
|
||||||
</div>
|
<div class="track__description">
|
||||||
</div>
|
{{ track.description }}
|
||||||
|
</div>
|
||||||
|
<span class="badge badge-pill badge-light track__order">#{{ order }}</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
|
||||||
<div class="col-md">
|
<section>
|
||||||
<strong>Trasy:</strong>
|
<strong>Na mapie:</strong>
|
||||||
<ul class="stop__tracks list-underlined">
|
<div style="height: 350px" tabindex="-1">
|
||||||
<li v-for="{ track, order } in tracks" class="track">
|
<l-map :center="stop.location" :zoom=17>
|
||||||
<div class="track__line">
|
<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>
|
||||||
<line-symbol :line="track.line"></line-symbol>
|
<l-marker :lat-lng="stop.location"></l-marker>
|
||||||
</div>
|
</l-map>
|
||||||
<div class="track__description">
|
|
||||||
{{ track.description }}
|
|
||||||
</div>
|
|
||||||
<span class="badge badge-pill badge-light track__order">#{{ order }}</span>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="text-center">
|
<div v-else class="text-center">
|
||||||
<fa icon="spinner-third" pulse></fa>
|
<fa icon="spinner-third" pulse></fa>
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
</slot>
|
</slot>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<fold :visible="details" class="stop__details" lazy>
|
<fold :visible="details" class="stop__details-fold" lazy>
|
||||||
<stop-details :stop="stop"></stop-details>
|
<stop-details :stop="stop"></stop-details>
|
||||||
</fold>
|
</fold>
|
||||||
|
|
||||||
|
@ -3,6 +3,10 @@
|
|||||||
@extend .btn-link;
|
@extend .btn-link;
|
||||||
|
|
||||||
color: black;
|
color: black;
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
outline: 2px solid rgba($blue, .2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.btn-outline-action {
|
&.btn-outline-action {
|
||||||
|
@ -8,9 +8,25 @@
|
|||||||
padding: 0 .2rem;
|
padding: 0 .2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.line--#{$type} .icon {
|
&.line--#{$type} {
|
||||||
background-color: $color;
|
.icon {
|
||||||
color: color-yiq($color);
|
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;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stop__details {
|
.stop__details-fold {
|
||||||
flex-basis: 100%;
|
flex-basis: 100%;
|
||||||
.fold__inner { padding-bottom: .75rem; }
|
.fold__inner { padding-bottom: .75rem; }
|
||||||
}
|
}
|
||||||
@ -29,4 +29,21 @@
|
|||||||
|
|
||||||
.stop__tracks .line__symbol .badge {
|
.stop__tracks .line__symbol .badge {
|
||||||
flex-grow: 1;
|
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
|
'unknown': $dark
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$default-spacing: .5rem;
|
||||||
|
|
||||||
|
$alert-margin-bottom: $default-spacing;
|
||||||
|
$headings-margin-bottom: $default-spacing;
|
||||||
|
|
||||||
@import "~bootstrap/scss/bootstrap";
|
@import "~bootstrap/scss/bootstrap";
|
||||||
|
|
||||||
@import "common";
|
@import "common";
|
||||||
|
@ -4,6 +4,8 @@ import { Message } from "../model/message";
|
|||||||
import urls from "../urls";
|
import urls from "../urls";
|
||||||
|
|
||||||
import { faInfoCircle, faExclamationTriangle, faQuestionCircle } from "@fortawesome/pro-light-svg-icons";
|
import { faInfoCircle, faExclamationTriangle, faQuestionCircle } from "@fortawesome/pro-light-svg-icons";
|
||||||
|
import { Jsonified } from "../utils";
|
||||||
|
import moment = require("moment");
|
||||||
|
|
||||||
@Component({ template: require("../../components/messages.html") })
|
@Component({ template: require("../../components/messages.html") })
|
||||||
export class MessagesComponent extends Vue {
|
export class MessagesComponent extends Vue {
|
||||||
@ -18,7 +20,15 @@ export class MessagesComponent extends Vue {
|
|||||||
const response = await fetch(urls.prepare(urls.messages));
|
const response = await fetch(urls.prepare(urls.messages));
|
||||||
|
|
||||||
if (response.ok) {
|
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);
|
this.$emit('update', this.messages);
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
export interface Decorator<TArgs extends any[], FArgs extends any[], TRet, FRet> {
|
export interface Decorator<TArgs extends any[], FArgs extends any[], TRet extends any, FRet extends any> {
|
||||||
decorate(f: (...farg: FArgs) => FRet, ...args: TArgs): (...farg: FArgs) => TRet;
|
decorate(f: (...farg: FArgs) => any, ...args: TArgs): (...farg: FArgs) => TRet;
|
||||||
|
|
||||||
(...args: TArgs): (target, name: string | symbol, descriptor: TypedPropertyDescriptor<(...farg: FArgs) => FRet>) => void;
|
(...args: TArgs): (target, name: string | symbol, descriptor: TypedPropertyDescriptor<(...farg: FArgs) => FRet>) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function decorator<TArgs extends any[], FArgs extends any[], TRet, FRet>
|
export function decorator<TArgs extends any[], FArgs extends any[], TRet extends any, FRet extends any>
|
||||||
(decorate: (f: (...fargs: FArgs) => FRet, ...args: TArgs) => (...fargs: FArgs) => TRet)
|
(decorate: (f: (...farg: FArgs) => FRet, ...args: TArgs) => (...farg: FArgs) => TRet)
|
||||||
: Decorator<TArgs, FArgs, TRet, FRet> {
|
: Decorator<TArgs, FArgs, TRet, FRet> {
|
||||||
|
|
||||||
const factory = function (this: Decorator<TArgs, FArgs, TRet, FRet>, ...args: TArgs) {
|
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);
|
}, 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 { signed } from "./utils";
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
|
import { condition } from "./decorators";
|
||||||
|
|
||||||
Vue.filter('signed', signed);
|
Vue.filter('signed', signed);
|
||||||
|
|
||||||
@ -18,6 +19,40 @@ Vue.directive('hover', (el, binding, node) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
el.addEventListener('mouseenter', e => update(true, e));
|
const activate = event => update(true, event);
|
||||||
el.addEventListener('mouseleave', e => update(false, e));
|
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