add messages support

This commit is contained in:
Kacper Donat 2018-09-11 20:58:37 +02:00
parent 205bcaa588
commit 3ce3f6d3d2
16 changed files with 149 additions and 18 deletions

View File

@ -0,0 +1,6 @@
<ul class="messages list-unstyled">
<li class="messages__message alert" :class="`alert-${type(message)}`" v-for="message in messages">
<fa :icon="icon(message)" fixed-width></fa>
{{ message.message }}
</li>
</ul>

View File

@ -34,7 +34,21 @@
padding-bottom: .5rem;
}
%flex {
.flex {
display: flex;
align-items: center;
}
.section__title {
@extend .alert;
@extend .alert-dark;
font-size: medium;
background: transparent;
padding-top: .5rem;
padding-bottom: .5rem;
&:hover {
background: none;
}
}

View File

@ -8,7 +8,7 @@
}
.departure__stop {
@extend %flex;
@extend .flex;
width: 100%;
.stop {
@ -27,12 +27,10 @@
}
.departures__actions {
display: flex;
align-items: center;
@extend .flex;
.departures__auto-refresh {
display: flex;
align-items: center;
@extend .flex;
}
.form-control {

View File

@ -1,5 +1,5 @@
.line {
@extend %flex;
@extend .flex;
.line__symbol {
min-width: 4rem;
@ -7,7 +7,7 @@
}
.track {
@extend %flex;
@extend .flex;
flex-shrink: 0;
flex-grow: 0;

View File

@ -1,5 +1,5 @@
.stop, .stop-group__header {
@extend %flex;
@extend .flex;
flex-wrap: wrap;
}

View File

@ -15,11 +15,23 @@ window['Popper'] = Popper;
// dependencies
import 'bootstrap'
import Vue from 'vue';
import { Vue } from "vue-property-decorator";
// here goes "public" API
window['czydojade'] = {
components
};
window['app'] = new Vue({ el: '#app' });
window['app'] = new Vue({
el: '#app',
data: {
messages: {
count: 0,
visible: true
}
}, methods: {
handleMessagesUpdate(messages) {
this.messages.count = messages.length;
}
}
});

View File

@ -0,0 +1,5 @@
import Vue from 'vue'
export class Application extends Vue {
private messages: boolean = true;
}

View File

@ -1,4 +1,5 @@
export * from './utils'
export * from './picker'
export * from './departures'
export * from './stop'
export * from './stop'
export * from './messages'

View File

@ -0,0 +1,45 @@
import Vue from 'vue';
import { Component, Prop, Watch } from "vue-property-decorator";
import messages = require("../../components/messages.html");
import { Message } from "../model/message";
import urls from "../urls";
import { faInfoCircle, faExclamationTriangle, faQuestionCircle } from "@fortawesome/pro-light-svg-icons";
@Component({ template: messages })
export class MessagesComponent extends Vue {
public messages: Message[] = [];
async mounted() {
this.update();
}
async update() {
const response = await fetch(urls.prepare(urls.messages));
if (response.ok) {
this.messages = await response.json();
}
this.$emit('updated', this.messages);
}
public icon(message: Message) {
switch (message.type) {
case "breakdown": return faExclamationTriangle;
case "info": return faInfoCircle;
case "unknown": return faQuestionCircle;
}
}
public type(message: Message) {
switch (message.type) {
case "breakdown": return "danger";
case "info": return "info";
case "unknown": return "warning";
}
}
}
Vue.component('Messages', MessagesComponent);

View File

@ -0,0 +1,10 @@
import { Moment } from "moment";
export type MessageType = "info" | "breakdown" | "unknown";
export interface Message {
type: MessageType;
message: string;
validFrom: Moment;
validTo: Moment;
}

View File

@ -49,6 +49,7 @@ const base = '/{provider}/api/v1';
export default {
departures: `${base}/departures`,
messages: `${base}/messages`,
stops: {
all: `${base}/stops`,
search: `${base}/stops/search`,

View File

@ -18,13 +18,15 @@ class ZtmGdanskMessageRepository implements MessageRepository
const MESSAGES_URL = "http://87.98.237.99:88/displayMessages";
private $cache;
private $classifier;
/**
* ZtmGdanskStopRepository constructor.
*/
public function __construct(AdapterInterface $cache)
public function __construct(AdapterInterface $cache, ZtmGdanskMessageTypeClassifier $classifier)
{
$this->cache = $cache;
$this->cache = $cache;
$this->classifier = $classifier;
}
public function getAll(): Collection
@ -32,12 +34,15 @@ class ZtmGdanskMessageRepository implements MessageRepository
return collect($this->queryZtmApi())->unique(function ($message) {
return $message['messagePart1'] . $message['messagePart2'];
})->map(function ($message) {
return Message::createFromArray([
$message = Message::createFromArray([
'message' => trim($message['messagePart1'] . $message['messagePart2']),
'type' => Message::TYPE_UNKNOWN,
'validFrom' => new Carbon($message['startDate']),
'validTo' => new Carbon($message['endDate']),
]);
$message->setType($this->classifier->classify($message));
return $message;
});
}

View File

@ -0,0 +1,22 @@
<?php
namespace App\Provider\ZtmGdansk;
use App\Model\Message;
class ZtmGdanskMessageTypeClassifier
{
public function classify(Message $message): string
{
switch (true) {
case preg_match('/(awari|opóźnie)/i', $message->getMessage()):
return Message::TYPE_BREAKDOWN;
case preg_match('#gdansk.pl/powietrze#i', $message->getMessage()):
return Message::TYPE_INFO;
default:
return Message::TYPE_UNKNOWN;
}
}
}

View File

@ -20,7 +20,7 @@ class ZtmGdanskProvider implements Provider
public function getName()
{
return 'MZKZG Trójmiasto';
return 'MZKZG - Trójmiasto';
}
public function getIdentifier()

View File

@ -2,6 +2,18 @@
{% block title "#{parent()} - #{provider.name}" %}
{% block body %}
<section class="messages" v-if="messages.count > 0">
<h2 class="section__title flex">
<fa :icon="['fal', 'bullhorn']" fixed-width class="mr-2"></fa>
Komunikaty <span class="ml-2 badge badge-pill badge-dark">{{ '{{ messages.count }}' }}</span>
<button class="btn btn-action btn-sm flex-space-left" @click="messages.visible = !messages.visible">
<fa :icon="['fal', messages.visible ? 'chevron-up' : 'chevron-down']" fixed-width />
</button>
</h2>
<fold :visible="messages.visible">
<messages @update="handleMessagesUpdate"></messages>
</fold>
</section>
<stop-picker></stop-picker>
{% endblock %}

View File

@ -12,7 +12,7 @@
{% block body %}{% endblock %}
</main>
<script src="bundle.js"></script>
{% block javascripts %}{% endblock %}
<script src="bundle.js"></script>
</body>
</html>