50_make_frontend_part_independent #2
| @ -17,6 +17,8 @@ services: | |||||||
|       - ./:/var/www:cached |       - ./:/var/www:cached | ||||||
|       - ./docker/php/log.conf:/usr/local/etc/php-fpm.d/zz-log.conf |       - ./docker/php/log.conf:/usr/local/etc/php-fpm.d/zz-log.conf | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|   blackfire: |   blackfire: | ||||||
|     image: blackfire/blackfire |     image: blackfire/blackfire | ||||||
|     ports: ["8707"] |     ports: ["8707"] | ||||||
|  | |||||||
							
								
								
									
										42
									
								
								resources/components/page/providers.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								resources/components/page/providers.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,42 @@ | |||||||
|  | <main class="d-flex"> | ||||||
|  |     <div style="width: 100%"> | ||||||
|  |         <l-map :center="{ lat: 52.0194, lon: 19.1451 }" :zoom=7 :options="{ zoomControl: false }" class="map"> | ||||||
|  |             <l-vector-layer url="https://api.maptiler.com/maps/bright/style.json?key=8GX5FRUNgk4lB83GZT8Q" | ||||||
|  |                             token="not-needed" | ||||||
|  |                             attribution='<a href="https://www.maptiler.com/copyright/" target="_blank">© MapTiler</a> <a href="https://www.openstreetmap.org/copyright" target="_blank">© OpenStreetMap contributors</a>' | ||||||
|  |             /> | ||||||
|  | 
 | ||||||
|  |             <div class="provider-picker"> | ||||||
|  |                 <h2 class="provider-picker__heading">Wybierz lokaliację</h2> | ||||||
|  |                 <ul class="provider-picker__providers"> | ||||||
|  |                     <li v-for="provider in providers" :key="provider.id" class="provider-picker__provider"> | ||||||
|  |                         <a :href="`/${provider.id}`" class="provider"> | ||||||
|  |                             <ui-icon icon="line-bus" size="2x" /> | ||||||
|  |                             <div> | ||||||
|  |                                 <div class="provider__short-name">{{ provider.shortName }}</div> | ||||||
|  |                                 <div class="provider__name">{{ provider.name }}</div> | ||||||
|  |                             </div> | ||||||
|  |                             <tooltip v-if="provider.lastUpdate != null">Ostatnia akutalizacja: {{ provider.lastUpdate|moment('YYYY-MM-DD HH:mm') }}</tooltip> | ||||||
|  |                         </a> | ||||||
|  |                     </li> | ||||||
|  |                 </ul> | ||||||
|  |             </div> | ||||||
|  | 
 | ||||||
|  |             <l-marker :lat-lng="provider.location" v-for="provider in providers" :options="{ keyboard: false }" :key="provider.id"> | ||||||
|  |                 <l-icon> | ||||||
|  |                     <div class="map__label-box" tabindex="0"> | ||||||
|  |                         <a :href="`/${provider.id}`" class="provider"> | ||||||
|  |                             <ui-icon icon="line-bus" class="map__icon" /> | ||||||
|  |                             <div> | ||||||
|  |                                 <div class="provider__short-name">{{ provider.shortName }}</div> | ||||||
|  |                                 <div class="provider__name">{{ provider.name }}</div> | ||||||
|  |                             </div> | ||||||
|  |                         </a> | ||||||
|  |                     </div> | ||||||
|  |                 </l-icon> | ||||||
|  |             </l-marker> | ||||||
|  |         </l-map> | ||||||
|  |     </div> | ||||||
|  | 
 | ||||||
|  |     <portal-target name="popups" multiple/> | ||||||
|  | </main> | ||||||
							
								
								
									
										29
									
								
								resources/styles/_map.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								resources/styles/_map.scss
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,29 @@ | |||||||
|  | .map__label-box { | ||||||
|  |   @extend .popper; | ||||||
|  | 
 | ||||||
|  |   padding: .5rem; | ||||||
|  |   background: white; | ||||||
|  |   transform-origin: 50% 50%; | ||||||
|  |   transform: translateX(-50%); | ||||||
|  |   min-width: max-content; | ||||||
|  | 
 | ||||||
|  |   font-size: 9pt; | ||||||
|  | 
 | ||||||
|  |   font-weight: bold; | ||||||
|  |   align-items: center; | ||||||
|  | 
 | ||||||
|  |   @include active { | ||||||
|  |     transform: translateX(-50%) scale(1.1); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @include flex-with-spacing(.5rem); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .map__icon { | ||||||
|  |   font-size: 1.5rem; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | img.map__icon { | ||||||
|  |   width: 24px; | ||||||
|  |   height: 24px; | ||||||
|  | } | ||||||
| @ -61,6 +61,20 @@ $grid-gutter-width: $spacer * 2; | |||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @mixin active { | ||||||
|  |   &:hover, &:active, &:focus, #{&}--active { | ||||||
|  |     @content | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | @mixin flex-with-spacing($spacing) { | ||||||
|  |   display: flex; | ||||||
|  | 
 | ||||||
|  |   & > *:not(:last-child) { | ||||||
|  |     margin-right: $spacing; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| @import "common"; | @import "common"; | ||||||
| @import "stop"; | @import "stop"; | ||||||
| @import "departure"; | @import "departure"; | ||||||
| @ -72,9 +86,12 @@ $grid-gutter-width: $spacer * 2; | |||||||
| @import "favourites"; | @import "favourites"; | ||||||
| @import "trip"; | @import "trip"; | ||||||
| @import "dragscroll"; | @import "dragscroll"; | ||||||
|  | @import "map"; | ||||||
| 
 | 
 | ||||||
| @import "ui/switch"; | @import "ui/switch"; | ||||||
| 
 | 
 | ||||||
|  | @import "page/provider-picker"; | ||||||
|  | 
 | ||||||
| body { | body { | ||||||
|   min-height: 100vh; |   min-height: 100vh; | ||||||
|   display: flex; |   display: flex; | ||||||
|  | |||||||
							
								
								
									
										62
									
								
								resources/styles/page/_provider-picker.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								resources/styles/page/_provider-picker.scss
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,62 @@ | |||||||
|  | .provider__name { | ||||||
|  |   font-size: .9em; | ||||||
|  |   color: $gray-800; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .provider__short-name { | ||||||
|  |   font-weight: bold; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .provider-picker { | ||||||
|  |   @extend .popper; | ||||||
|  |   padding: 1rem; | ||||||
|  |   margin: 3rem; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .provider-picker__heading { | ||||||
|  |   font-size: 1.2rem; | ||||||
|  |   font-weight: bold; | ||||||
|  |   margin-bottom: 1rem; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .provider-picker__providers { | ||||||
|  |   list-style: none; | ||||||
|  |   padding: 0; | ||||||
|  |   margin: 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .provider-picker__provider { | ||||||
|  |   font-size: 1rem; | ||||||
|  | 
 | ||||||
|  |   .provider { | ||||||
|  |     margin: 0 -1rem; | ||||||
|  |     padding: .5rem 1rem; | ||||||
|  | 
 | ||||||
|  |     &:hover { | ||||||
|  |       background: $gray-100; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .provider { | ||||||
|  |   @include flex-with-spacing(.5rem); | ||||||
|  |   align-items: center; | ||||||
|  | 
 | ||||||
|  |   &:hover { | ||||||
|  |     text-decoration: none; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | @include media-breakpoint-down('sm') { | ||||||
|  |   .provider-picker { | ||||||
|  |     position: absolute; | ||||||
|  |     bottom: 0; | ||||||
|  |     left: 0; | ||||||
|  |     right: 0; | ||||||
|  |     margin: 1.5rem; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   .provider-picker__providers { | ||||||
|  |     max-height: 170px; | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -14,7 +14,6 @@ import VueDragscroll from 'vue-dragscroll'; | |||||||
| import { Plugin as VueFragment } from 'vue-fragment'; | import { Plugin as VueFragment } from 'vue-fragment'; | ||||||
| import { Workbox } from "workbox-window"; | import { Workbox } from "workbox-window"; | ||||||
| 
 | 
 | ||||||
| import { migrate } from "./store/migrations"; |  | ||||||
| import { Component } from "vue-property-decorator"; | import { Component } from "vue-property-decorator"; | ||||||
| import * as VueMoment from "vue-moment"; | import * as VueMoment from "vue-moment"; | ||||||
| import * as moment from 'moment'; | import * as moment from 'moment'; | ||||||
| @ -41,6 +40,8 @@ Component.registerHooks(['removed']); | |||||||
| 
 | 
 | ||||||
| // async dependencies
 | // async dependencies
 | ||||||
| (async function () { | (async function () { | ||||||
|  |     const { migrate } = await import('./store/migrations'); | ||||||
|  | 
 | ||||||
|     await migrate("vuex"); |     await migrate("vuex"); | ||||||
| 
 | 
 | ||||||
|     const [ components, { default: store } ] = await Promise.all([ |     const [ components, { default: store } ] = await Promise.all([ | ||||||
| @ -50,17 +51,16 @@ Component.registerHooks(['removed']); | |||||||
|         import('bootstrap'), |         import('bootstrap'), | ||||||
|     ] as const); |     ] as const); | ||||||
| 
 | 
 | ||||||
|  |     const appRoot = document.getElementById('app'); | ||||||
|  | 
 | ||||||
|     // here goes "public" API
 |     // here goes "public" API
 | ||||||
|     window['app'] = Object.assign({ |     window['app'] = Object.assign({ | ||||||
|         state: {} |         state: {} | ||||||
|     }, window['app'], { |     }, window['app'], { | ||||||
|         components, |         components, | ||||||
|         application: new components.Application({ el: '#app' }) |         application: appRoot ? new components.Application({ el: '#app' }) : new components.PageProviderList({ el: '#provider-picker' }), | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     store.dispatch('messages/update'); |  | ||||||
|     store.dispatch('load', window['app'].state); |  | ||||||
| 
 |  | ||||||
|     if ('serviceWorker' in navigator) { |     if ('serviceWorker' in navigator) { | ||||||
|         const wb = new Workbox("/service-worker.js"); |         const wb = new Workbox("/service-worker.js"); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,7 +1,7 @@ | |||||||
| import Vue from 'vue' | import Vue from 'vue' | ||||||
| import store from '../store' | import store from '../store' | ||||||
| import { Component, Watch } from "vue-property-decorator"; | import { Component, Watch } from "vue-property-decorator"; | ||||||
| import { Mutation, Action } from 'vuex-class' | import { Action, Mutation } from 'vuex-class' | ||||||
| import { Stop } from "../model"; | import { Stop } from "../model"; | ||||||
| import { DeparturesSettingsState } from "../store/settings/departures"; | import { DeparturesSettingsState } from "../store/settings/departures"; | ||||||
| import { MessagesSettingsState } from "../store/settings/messages"; | import { MessagesSettingsState } from "../store/settings/messages"; | ||||||
| @ -48,6 +48,9 @@ export class Application extends Vue { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     created() { |     created() { | ||||||
|  |         this.$store.dispatch('messages/update'); | ||||||
|  |         this.$store.dispatch('load', window['app'].state); | ||||||
|  | 
 | ||||||
|         this.initDeparturesRefreshInterval(); |         this.initDeparturesRefreshInterval(); | ||||||
|         this.initMessagesRefreshInterval(); |         this.initMessagesRefreshInterval(); | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -11,5 +11,7 @@ export * from './favourites' | |||||||
| export * from './trip' | export * from './trip' | ||||||
| export * from './ui' | export * from './ui' | ||||||
| export * from './settings' | export * from './settings' | ||||||
|  | export * from "./page" | ||||||
|  | 
 | ||||||
| export { Departures } from "../store"; | export { Departures } from "../store"; | ||||||
| export { Messages } from "../store"; | export { Messages } from "../store"; | ||||||
|  | |||||||
| @ -1,4 +1,4 @@ | |||||||
| import { LMap, LTileLayer, LMarker } from 'vue2-leaflet'; | import { LControl, LIcon, LMap, LMarker, LPopup, LTileLayer } from 'vue2-leaflet'; | ||||||
| import Vue from 'vue'; | import Vue from 'vue'; | ||||||
| 
 | 
 | ||||||
| import * as L from 'leaflet' | import * as L from 'leaflet' | ||||||
| @ -48,5 +48,8 @@ Vue.component('LMap', LMap); | |||||||
| Vue.component('LTileLayer', LTileLayer); | Vue.component('LTileLayer', LTileLayer); | ||||||
| Vue.component('LVectorLayer', LVectorLayer); | Vue.component('LVectorLayer', LVectorLayer); | ||||||
| Vue.component('LMarker', LMarker); | Vue.component('LMarker', LMarker); | ||||||
|  | Vue.component('LControl', LControl); | ||||||
|  | Vue.component('LPopup', LPopup) | ||||||
|  | Vue.component('LIcon', LIcon); | ||||||
| 
 | 
 | ||||||
| export { LMap, LTileLayer, LMarker } from 'vue2-leaflet'; | export { LMap, LTileLayer, LMarker, LIcon, LControl, LPopup } from 'vue2-leaflet'; | ||||||
|  | |||||||
							
								
								
									
										1
									
								
								resources/ts/components/page/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								resources/ts/components/page/index.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | |||||||
|  | export * from "./providers" | ||||||
							
								
								
									
										26
									
								
								resources/ts/components/page/providers.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								resources/ts/components/page/providers.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,26 @@ | |||||||
|  | import Vue from 'vue' | ||||||
|  | import { Component } from 'vue-property-decorator' | ||||||
|  | import { Provider } from "../../model"; | ||||||
|  | import { Jsonified } from "../../utils"; | ||||||
|  | import * as moment from 'moment'; | ||||||
|  | 
 | ||||||
|  | @Component({ | ||||||
|  |     template: require('../../../components/page/providers.html'), | ||||||
|  | }) | ||||||
|  | export class PageProviderList extends Vue { | ||||||
|  |     private providers: Provider[] = []; | ||||||
|  | 
 | ||||||
|  |     async created() { | ||||||
|  |         const response = await fetch('/api/v1/providers'); | ||||||
|  |         const result = await response.json() as Jsonified<Provider>[]; | ||||||
|  | 
 | ||||||
|  |         this.providers = result.map<Provider>(provider => { | ||||||
|  |             return { | ||||||
|  |                 ...provider, | ||||||
|  |                 lastUpdate: provider.lastUpdate && moment(provider.lastUpdate) | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Vue.component('PageProviderList', PageProviderList); | ||||||
							
								
								
									
										4
									
								
								resources/ts/model/common.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								resources/ts/model/common.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,4 @@ | |||||||
|  | export interface Location { | ||||||
|  |     lat: number, | ||||||
|  |     lng: number, | ||||||
|  | } | ||||||
| @ -3,3 +3,5 @@ export * from './departure' | |||||||
| export * from './line' | export * from './line' | ||||||
| export * from './error' | export * from './error' | ||||||
| export * from './identity' | export * from './identity' | ||||||
|  | export * from './common' | ||||||
|  | export * from './provider' | ||||||
|  | |||||||
							
								
								
									
										11
									
								
								resources/ts/model/provider.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								resources/ts/model/provider.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | |||||||
|  | import { Moment } from "moment"; | ||||||
|  | import { Location } from "./common"; | ||||||
|  | 
 | ||||||
|  | export interface Provider { | ||||||
|  |     id: string; | ||||||
|  |     name: string; | ||||||
|  |     shortName: string; | ||||||
|  |     attribution?: string; | ||||||
|  |     lastUpdate?: Moment; | ||||||
|  |     location: Location; | ||||||
|  | } | ||||||
| @ -1,13 +1,11 @@ | |||||||
| import { Line } from "./line"; | import { Line } from "./line"; | ||||||
|  | import { Location } from "./common"; | ||||||
| 
 | 
 | ||||||
| export interface Stop { | export interface Stop { | ||||||
|     id: any; |     id: any; | ||||||
|     name: string; |     name: string; | ||||||
|     description?: string; |     description?: string; | ||||||
|     location?: { |     location?: Location; | ||||||
|         lat: number, |  | ||||||
|         lng: number, |  | ||||||
|     }; |  | ||||||
|     onDemand?: boolean; |     onDemand?: boolean; | ||||||
|     variant?: string; |     variant?: string; | ||||||
| } | } | ||||||
|  | |||||||
| @ -5,6 +5,7 @@ import { ensureArray } from "../utils"; | |||||||
| 
 | 
 | ||||||
| export interface RootState { | export interface RootState { | ||||||
|     stops: Stop[], |     stops: Stop[], | ||||||
|  |     provider: any, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export interface SavedState { | export interface SavedState { | ||||||
| @ -13,7 +14,8 @@ export interface SavedState { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export const state: RootState = { | export const state: RootState = { | ||||||
|     stops: [] |     stops: [], | ||||||
|  |     provider: null, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| export const mutations: MutationTree<RootState> = { | export const mutations: MutationTree<RootState> = { | ||||||
|  | |||||||
| @ -1,3 +1,5 @@ | |||||||
|  | import store from "./store"; | ||||||
|  | 
 | ||||||
| export type UrlParams = { | export type UrlParams = { | ||||||
|     [name: string]: any |     [name: string]: any | ||||||
| } | } | ||||||
| @ -61,5 +63,5 @@ export default { | |||||||
|         tracks:  `${base}/stops/{id}/tracks` |         tracks:  `${base}/stops/{id}/tracks` | ||||||
|     }, |     }, | ||||||
|     trip: `${base}/trips/{id}`, |     trip: `${base}/trips/{id}`, | ||||||
|     prepare: (url: string, params: UrlParams = { }) => prepare(url, Object.assign({}, { provider: window['data'].provider }, params)) |     prepare: (url: string, params: UrlParams = { }) => prepare(url, Object.assign({}, { provider: store.state.provider }, params)) | ||||||
| } | } | ||||||
|  | |||||||
| @ -49,6 +49,12 @@ class Provider implements Fillable, Referable | |||||||
|      */ |      */ | ||||||
|     private $lastUpdate; |     private $lastUpdate; | ||||||
| 
 | 
 | ||||||
|  |     /** | ||||||
|  |      * Location of provider centre of interest. | ||||||
|  |      * @var Location | ||||||
|  |      */ | ||||||
|  |     private $location; | ||||||
|  | 
 | ||||||
|     public function getId(): string |     public function getId(): string | ||||||
|     { |     { | ||||||
|         return $this->id; |         return $this->id; | ||||||
| @ -98,4 +104,14 @@ class Provider implements Fillable, Referable | |||||||
|     { |     { | ||||||
|         $this->lastUpdate = $lastUpdate; |         $this->lastUpdate = $lastUpdate; | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     public function getLocation(): Location | ||||||
|  |     { | ||||||
|  |         return $this->location; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public function setLocation(Location $location): void | ||||||
|  |     { | ||||||
|  |         $this->location = $location; | ||||||
|  |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -3,6 +3,7 @@ | |||||||
| namespace App\Provider\Dummy; | namespace App\Provider\Dummy; | ||||||
| 
 | 
 | ||||||
| use App\Exception\NotSupportedException; | use App\Exception\NotSupportedException; | ||||||
|  | use App\Model\Location; | ||||||
| use App\Provider\DepartureRepository; | use App\Provider\DepartureRepository; | ||||||
| use App\Provider\LineRepository; | use App\Provider\LineRepository; | ||||||
| use App\Provider\MessageRepository; | use App\Provider\MessageRepository; | ||||||
| @ -78,6 +79,11 @@ class DummyProvider implements Provider | |||||||
|         return null; |         return null; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     public function getLocation(): Location | ||||||
|  |     { | ||||||
|  |         return new Location(21.4474, 54.7837); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     public function getTripRepository(): TripRepository |     public function getTripRepository(): TripRepository | ||||||
|     { |     { | ||||||
|         throw new NotSupportedException(); |         throw new NotSupportedException(); | ||||||
|  | |||||||
| @ -2,6 +2,7 @@ | |||||||
| 
 | 
 | ||||||
| namespace App\Provider; | namespace App\Provider; | ||||||
| 
 | 
 | ||||||
|  | use App\Model\Location; | ||||||
| use Carbon\Carbon; | use Carbon\Carbon; | ||||||
| 
 | 
 | ||||||
| interface Provider | interface Provider | ||||||
| @ -17,6 +18,7 @@ interface Provider | |||||||
|     public function getShortName(): string; |     public function getShortName(): string; | ||||||
|     public function getIdentifier(): string; |     public function getIdentifier(): string; | ||||||
|     public function getAttribution(): ?string; |     public function getAttribution(): ?string; | ||||||
|  |     public function getLocation(): Location; | ||||||
| 
 | 
 | ||||||
|     public function getLastUpdate(): ?Carbon; |     public function getLastUpdate(): ?Carbon; | ||||||
| } | } | ||||||
|  | |||||||
| @ -4,6 +4,7 @@ | |||||||
| namespace App\Provider\ZtmGdansk; | namespace App\Provider\ZtmGdansk; | ||||||
| 
 | 
 | ||||||
| use App\Entity\ProviderEntity; | use App\Entity\ProviderEntity; | ||||||
|  | use App\Model\Location; | ||||||
| use App\Provider\Database\GenericLineRepository; | use App\Provider\Database\GenericLineRepository; | ||||||
| use App\Provider\Database\GenericScheduleRepository; | use App\Provider\Database\GenericScheduleRepository; | ||||||
| use App\Provider\Database\GenericStopRepository; | use App\Provider\Database\GenericStopRepository; | ||||||
| @ -13,11 +14,9 @@ use App\Provider\DepartureRepository; | |||||||
| use App\Provider\LineRepository; | use App\Provider\LineRepository; | ||||||
| use App\Provider\MessageRepository; | use App\Provider\MessageRepository; | ||||||
| use App\Provider\Provider; | use App\Provider\Provider; | ||||||
| use App\Provider\ScheduleRepository; |  | ||||||
| use App\Provider\StopRepository; | use App\Provider\StopRepository; | ||||||
| use App\Provider\TrackRepository; | use App\Provider\TrackRepository; | ||||||
| use App\Provider\TripRepository; | use App\Provider\TripRepository; | ||||||
| use App\Provider\ZtmGdansk\{ZtmGdanskDepartureRepository, ZtmGdanskMessageRepository}; |  | ||||||
| use App\Service\Proxy\ReferenceFactory; | use App\Service\Proxy\ReferenceFactory; | ||||||
| use Carbon\Carbon; | use Carbon\Carbon; | ||||||
| use Doctrine\ORM\EntityManagerInterface; | use Doctrine\ORM\EntityManagerInterface; | ||||||
| @ -54,6 +53,11 @@ class ZtmGdanskProvider implements Provider | |||||||
|         return '<a href="http://ztm.gda.pl/otwarty_ztm">Otwarte Dane</a> Zarządu Transportu Miejskiego w Gdańsku'; |         return '<a href="http://ztm.gda.pl/otwarty_ztm">Otwarte Dane</a> Zarządu Transportu Miejskiego w Gdańsku'; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     public function getLocation(): Location | ||||||
|  |     { | ||||||
|  |         return new Location(18.6466, 54.3520); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     public function __construct( |     public function __construct( | ||||||
|         EntityManagerInterface $em, |         EntityManagerInterface $em, | ||||||
|         GenericLineRepository $lines, |         GenericLineRepository $lines, | ||||||
|  | |||||||
| @ -17,6 +17,7 @@ class ProviderConverter implements Converter | |||||||
|             'name'        => $entity->getName(), |             'name'        => $entity->getName(), | ||||||
|             'attribution' => $entity->getAttribution(), |             'attribution' => $entity->getAttribution(), | ||||||
|             'lastUpdate'  => $entity->getLastUpdate() ? clone $entity->getLastUpdate() : null, |             'lastUpdate'  => $entity->getLastUpdate() ? clone $entity->getLastUpdate() : null, | ||||||
|  |             'location'    => $entity->getLocation(), | ||||||
|         ]); |         ]); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -25,3 +26,4 @@ class ProviderConverter implements Converter | |||||||
|         return $entity instanceof Provider; |         return $entity instanceof Provider; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | |||||||
| @ -3,6 +3,7 @@ | |||||||
| {% block manifest path('webapp_manifest', { provider: provider.identifier }) %} | {% block manifest path('webapp_manifest', { provider: provider.identifier }) %} | ||||||
| 
 | 
 | ||||||
| {% block body %} | {% block body %} | ||||||
|  |     <main id="app" class="container not-ready"> | ||||||
|         <div class="row"> |         <div class="row"> | ||||||
|             <div class="col-md-8 order-md-last"> |             <div class="col-md-8 order-md-last"> | ||||||
|                 <section class="section messages" v-show="messages.count > 0"> |                 <section class="section messages" v-show="messages.count > 0"> | ||||||
| @ -37,7 +38,6 @@ | |||||||
|                         <messages></messages> |                         <messages></messages> | ||||||
|                     </fold> |                     </fold> | ||||||
|                 </section> |                 </section> | ||||||
| 
 |  | ||||||
|                 <section class="section"> |                 <section class="section"> | ||||||
|                     <header class="section__title flex"> |                     <header class="section__title flex"> | ||||||
|                         <h2> |                         <h2> | ||||||
| @ -143,6 +143,7 @@ | |||||||
|         </div> |         </div> | ||||||
| 
 | 
 | ||||||
|         <portal-target name="popups" multiple></portal-target> |         <portal-target name="popups" multiple></portal-target> | ||||||
|  |     </main> | ||||||
| {% endblock %} | {% endblock %} | ||||||
| 
 | 
 | ||||||
| {% block javascripts %} | {% block javascripts %} | ||||||
|  | |||||||
| @ -33,9 +33,7 @@ | |||||||
|         {% endif %} |         {% endif %} | ||||||
|     </head> |     </head> | ||||||
|     <body> |     <body> | ||||||
|         <main role="main" class="container not-ready" id="app"> |         {% block body '' %} | ||||||
|             {% block body %}{% endblock %} |  | ||||||
|         </main> |  | ||||||
|         <footer class="container"> |         <footer class="container"> | ||||||
|             {% block footer %} |             {% block footer %} | ||||||
|                 <span> |                 <span> | ||||||
|  | |||||||
| @ -1,17 +1,5 @@ | |||||||
| {% extends 'base.html.twig' %} | {% extends 'base.html.twig' %} | ||||||
| 
 | 
 | ||||||
| {% block body %} | {% block body %} | ||||||
|     <div class="alert alert-primary"> |     <main class="d-flex" id="provider-picker"></main> | ||||||
|         <ui-icon icon="info-circle"></ui-icon> |  | ||||||
|         Wybierz źródło danych |  | ||||||
|     </div> |  | ||||||
|     <ul class="list-underlined"> |  | ||||||
|         {% for provider in providers %} |  | ||||||
|             <li title="Aktualizacja: {{ provider.lastUpdate ? provider.lastUpdate.format('Y.m.d H:i') : 'live' }}"> |  | ||||||
|                 <a href="{{ path('app', { provider: provider.identifier }) }}" class="btn btn-block btn-action text-left"> |  | ||||||
|                     {{ provider.name }} |  | ||||||
|                 </a> |  | ||||||
|             </li> |  | ||||||
|         {% endfor %} |  | ||||||
|     </ul> |  | ||||||
| {% endblock %} | {% endblock %} | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user