diff --git a/resources/components/departures.html b/resources/components/departures.html
index 5daf4a4..faa0a73 100644
--- a/resources/components/departures.html
+++ b/resources/components/departures.html
@@ -41,11 +41,15 @@
{{ departure.estimated.format('HH:mm') }}
-
-
-
-
-
+
+
+
+
+
+
+
+ Wybierz przystanki korzystając z wyszukiwarki poniżej, aby zobaczyć listę odjazdów.
+
\ No newline at end of file
diff --git a/resources/components/finder.html b/resources/components/finder.html
index d2173b3..7816bff 100644
--- a/resources/components/finder.html
+++ b/resources/components/finder.html
@@ -20,15 +20,12 @@
-
-
-
-
-
-
-
-
-
+
diff --git a/resources/components/fold.html b/resources/components/fold.html
new file mode 100644
index 0000000..540b679
--- /dev/null
+++ b/resources/components/fold.html
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/components/lazy.html b/resources/components/lazy.html
new file mode 100644
index 0000000..2d93330
--- /dev/null
+++ b/resources/components/lazy.html
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/resources/components/picker.html b/resources/components/picker.html
index e2e4092..19c7f8d 100644
--- a/resources/components/picker.html
+++ b/resources/components/picker.html
@@ -2,14 +2,11 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
diff --git a/resources/components/popper.html b/resources/components/popper.html
new file mode 100644
index 0000000..8812778
--- /dev/null
+++ b/resources/components/popper.html
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/resources/components/stop-details.html b/resources/components/stop-details.html
new file mode 100644
index 0000000..1a4e689
--- /dev/null
+++ b/resources/components/stop-details.html
@@ -0,0 +1,43 @@
+
+
+
+
Linie:
+
+
+
+
+
+
+
+
+ {{ line.symbol }}
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/components/stop.html b/resources/components/stop.html
index aee5ca7..c0c0cb9 100644
--- a/resources/components/stop.html
+++ b/resources/components/stop.html
@@ -1,19 +1,22 @@
-
-
-
-
{{ stop.name }}
{{ stop.variant }}
+
-
-
-
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/styles/_common.scss b/resources/styles/_common.scss
index b9982a8..f881228 100644
--- a/resources/styles/_common.scss
+++ b/resources/styles/_common.scss
@@ -1,7 +1,7 @@
.list-underlined {
@extend .list-unstyled;
- li {
+ > li {
border-bottom: 1px solid $text-muted;
}
}
@@ -29,3 +29,12 @@
}
}
}
+
+.collapse {
+ padding-bottom: .5rem;
+}
+
+%flex {
+ display: flex;
+ align-items: center;
+}
\ No newline at end of file
diff --git a/resources/styles/_departure.scss b/resources/styles/_departure.scss
index 0609bfb..ef0d611 100644
--- a/resources/styles/_departure.scss
+++ b/resources/styles/_departure.scss
@@ -8,7 +8,12 @@
}
.departure__stop {
+ @extend %flex;
width: 100%;
+
+ .stop {
+ flex: 1 1 auto;
+ }
}
.departure__time {
diff --git a/resources/styles/_line.scss b/resources/styles/_line.scss
index 52d283e..48d62f5 100644
--- a/resources/styles/_line.scss
+++ b/resources/styles/_line.scss
@@ -1,8 +1,23 @@
.line {
- display: flex;
- align-items: center;
+ @extend %flex;
.line__symbol {
min-width: 4rem;
}
+}
+
+.track {
+ @extend %flex;
+ flex-shrink: 0;
+ flex-grow: 0;
+
+ .track__line {
+ width: 6rem;
+ flex-shrink: 0;
+ }
+
+ .track__description {
+ flex: 1 1 auto;
+ white-space: normal;
+ }
}
\ No newline at end of file
diff --git a/resources/styles/_popper.scss b/resources/styles/_popper.scss
new file mode 100644
index 0000000..0ef1ad0
--- /dev/null
+++ b/resources/styles/_popper.scss
@@ -0,0 +1,108 @@
+@mixin triangle-border($color, $orientation, $size) {
+ border-width:
+ if($orientation == top, 0, $size)
+ if($orientation == right, 0, $size)
+ if($orientation == bottom, 0, $size)
+ if($orientation == left, 0, $size)
+;
+
+ border-color:
+ if($orientation == bottom, $color, transparent)
+ if($orientation == left, $color, transparent)
+ if($orientation == top, $color, transparent)
+ if($orientation == right, $color, transparent)
+;
+
+ #{$orientation}: -$size;
+ @if ($orientation == top) or ($orientation == bottom) {
+ left: 50%;
+ transform: translateX(-50%);
+ } @else {
+ top: 50%;
+ transform: translateY(-50%);
+ }
+}
+
+@mixin triangle($orientation, $size, $color, $border: none) {
+ background: $color;
+
+ &::after {
+ width: 0;
+ height: 0;
+ border-style: solid;
+ content: "";
+ position: absolute;
+
+ @include triangle-border($color, $orientation, $size);
+ }
+
+ @if $border != none {
+ &::before {
+ width: 0;
+ height: 0;
+ border-style: solid;
+ content: "";
+ position: absolute;
+
+ @include triangle-border($border, $orientation, $size + 1);
+ }
+ }
+}
+
+@mixin triangle-top($size, $color, $border: none) { @include triangle(top, $size, $color, $border); }
+@mixin triangle-bottom($size, $color, $border: none) { @include triangle(bottom, $size, $color, $border); }
+@mixin triangle-left($size, $color, $border: none) { @include triangle(left, $size, $color, $border); }
+@mixin triangle-right($size, $color, $border: none) { @include triangle(right, $size, $color, $border); }
+
+.popper {
+ $arrow-base: 10px;
+ $arrow-color: white;
+ $arrow-border: black;
+
+ $popper-padding: .5rem;
+
+ padding: $popper-padding;
+ background: white;
+ border: 1px solid black;
+ z-index: 1000;
+ position: relative;
+
+ max-width: 500px;
+ min-width: 200px;
+
+ border-radius: 2px;
+
+ .popper-arrow {
+ position: absolute;
+ width: 0;
+ height: 0;
+ }
+
+ @mixin placement($placement) {
+ $opposite: (
+ left: right,
+ right: left,
+ top: bottom,
+ bottom: top
+ );
+
+ &[x-placement^="#{$placement}"] {
+ margin-#{map-get($opposite, $placement)}: $arrow-base;
+
+ .popper-arrow {
+ #{map-get($opposite, $placement)}: 0;
+ @include triangle(map-get($opposite, $placement), $arrow-base, $arrow-color, $arrow-border);
+ }
+ }
+ }
+
+ &.has-arrow {
+ @include placement("left");
+ @include placement("right");
+ @include placement("top");
+ @include placement("bottom");
+ }
+
+ animation: ease-in fade-in 150ms
+}
+
diff --git a/resources/styles/_stop.scss b/resources/styles/_stop.scss
index 11bfe05..23ca5fc 100644
--- a/resources/styles/_stop.scss
+++ b/resources/styles/_stop.scss
@@ -1,6 +1,7 @@
.stop, .stop-group__header {
- display: flex;
- align-items: center;
+ @extend %flex;
+
+ flex-wrap: wrap;
}
.stop__name {
@@ -14,6 +15,9 @@
display: flex;
}
+.stop__details {
+ flex-basis: 100%;
+}
.stop-group__name {
font-size: $font-size-base;
diff --git a/resources/styles/main.scss b/resources/styles/main.scss
index 7359c14..4b05596 100644
--- a/resources/styles/main.scss
+++ b/resources/styles/main.scss
@@ -15,3 +15,4 @@ $custom-control-indicator-active-bg: $dark;
@import "departure";
@import "line";
@import "controls";
+@import "popper";
\ No newline at end of file
diff --git a/resources/ts/app.ts b/resources/ts/app.ts
index 8c27c52..ec9aed6 100644
--- a/resources/ts/app.ts
+++ b/resources/ts/app.ts
@@ -1,4 +1,3 @@
-///
///
import '../styles/main.scss'
@@ -6,13 +5,13 @@ import '../styles/main.scss'
import './font-awesome'
import './filters'
-import * as Popper from 'popper.js';
+import Popper from 'popper.js';
import * as $ from "jquery";
import * as components from './components';
window['$'] = window['jQuery'] = $;
-window['popper'] = Popper;
+window['Popper'] = Popper;
// dependencies
import 'bootstrap'
diff --git a/resources/ts/components/departures.ts b/resources/ts/components/departures.ts
index 4a0a398..874e88b 100644
--- a/resources/ts/components/departures.ts
+++ b/resources/ts/components/departures.ts
@@ -7,7 +7,7 @@ import moment = require("moment");
import { Jsonified } from "../utils";
import { debounce } from "../decorators";
-@Component({template})
+@Component({ template })
export class Departures extends Vue {
private _intervalId: number;
diff --git a/resources/ts/components/index.ts b/resources/ts/components/index.ts
index c737a45..b523d5c 100644
--- a/resources/ts/components/index.ts
+++ b/resources/ts/components/index.ts
@@ -1,2 +1,4 @@
+export * from './utils'
export * from './picker'
-export * from './departures'
\ No newline at end of file
+export * from './departures'
+export * from './stop'
\ No newline at end of file
diff --git a/resources/ts/components/picker.ts b/resources/ts/components/picker.ts
index 0dc69c6..110975c 100644
--- a/resources/ts/components/picker.ts
+++ b/resources/ts/components/picker.ts
@@ -70,12 +70,5 @@ export class FinderComponent extends Vue {
}
}
-@Component({ template: stop })
-export class StopComponent extends Vue {
- @Prop(Object)
- public stop: Stop;
-}
-
Vue.component('StopPicker', PickerComponent);
Vue.component('StopFinder', FinderComponent);
-Vue.component('Stop', StopComponent);
diff --git a/resources/ts/components/stop.ts b/resources/ts/components/stop.ts
new file mode 100644
index 0000000..75e3433
--- /dev/null
+++ b/resources/ts/components/stop.ts
@@ -0,0 +1,50 @@
+import { Component, Prop } from "vue-property-decorator";
+import { Line, Stop, Track } from "../model";
+import Vue from 'vue';
+
+import template = require('../../components/stop.html');
+import details = require('../../components/stop-details.html');
+import urls from "../urls";
+
+@Component({ template: details })
+class StopDetailsComponent extends Vue {
+ @Prop(Object)
+ public stop: Stop;
+
+ private ready: boolean = false;
+
+ tracks: { order: number, track: Track }[] = [];
+
+ get types() {
+ return this.tracks.map(t => t.track.line.type).filter((value, index, array) => {
+ return array.indexOf(value) === index;
+ });
+ }
+
+ get lines(): Line[] {
+ return this.tracks.map(t => t.track.line).reduce((lines, line: Line) => {
+ return Object.assign(lines, { [line.symbol]: line });
+ }, {} as any);
+ }
+
+ async mounted() {
+ const response = await fetch(urls.prepare(urls.stops.tracks, { id: this.stop.id }));
+
+ if (response.ok) {
+ this.tracks = await response.json();
+ }
+
+ this.ready = true;
+ }
+}
+
+@Component({ template })
+export class StopComponent extends Vue {
+ @Prop(Object)
+ public stop: Stop;
+
+ details: boolean = false;
+}
+
+Vue.component('Stop', StopComponent);
+Vue.component('StopDetails', StopDetailsComponent);
diff --git a/resources/ts/components/utils.ts b/resources/ts/components/utils.ts
new file mode 100644
index 0000000..f166145
--- /dev/null
+++ b/resources/ts/components/utils.ts
@@ -0,0 +1,72 @@
+import Vue from 'vue';
+import { Component, Prop, Watch } from "vue-property-decorator";
+import Popper, { Placement } from "popper.js";
+import * as $ from 'jquery';
+
+import popper = require("../../components/popper.html");
+import lazy = require("../../components/lazy.html");
+import collapse = require("../../components/fold.html");
+
+@Component({ template: popper })
+export class PopperComponent extends Vue {
+ @Prop(String)
+ public reference: string;
+
+ @Prop({ type: String, default: "auto" })
+ public placement: Placement;
+
+ @Prop(Boolean)
+ public arrow: boolean;
+
+ @Prop({ type: Boolean, default: false })
+ public visible: boolean;
+
+ private _popper;
+
+ mounted() {
+ const reference = this.$parent.$refs[this.reference] as HTMLElement;
+
+ this._popper = new Popper(reference, this.$el, {
+ placement: this.placement,
+ modifiers: {
+ arrow: { enabled: this.arrow, element: this.$refs['arrow'] as Element }
+ }
+ });
+ }
+
+ @Watch('visible')
+ private onVisibilityUpdate() {
+ this._popper.update();
+ }
+}
+
+@Component({ template: collapse })
+export class FoldComponent extends Vue {
+ @Prop(Boolean)
+ public visible: boolean;
+
+ @Prop(Boolean)
+ public lazy: boolean;
+
+ @Watch('visible')
+ private onVisibilityChange(value) {
+ const action = () => $(this.$el).collapse(value ? 'show' : 'hide');
+ setTimeout(action);
+ }
+}
+
+@Component({ template: lazy })
+export class LazyComponent extends Vue {
+ @Prop(Boolean)
+ public activate: boolean;
+ protected visible: boolean = false;
+
+ @Watch('activate')
+ private onVisibilityChange(value, old) {
+ this.visible = value || old;
+ }
+}
+
+Vue.component('Popper', PopperComponent);
+Vue.component('Fold', FoldComponent);
+Vue.component('Lazy', LazyComponent);
diff --git a/resources/ts/filters.ts b/resources/ts/filters.ts
index 6407753..d8cd5db 100644
--- a/resources/ts/filters.ts
+++ b/resources/ts/filters.ts
@@ -1,4 +1,8 @@
import { signed } from "./utils";
import Vue from 'vue';
-Vue.filter('signed', signed);
\ No newline at end of file
+Vue.filter('signed', signed);
+Vue.directive('hover', (el, binding) => {
+ el.addEventListener('mouseenter', binding.value);
+ el.addEventListener('mouseleave', binding.value);
+});
\ No newline at end of file
diff --git a/resources/ts/model/line.ts b/resources/ts/model/line.ts
index ad30c6a..f1d019d 100644
--- a/resources/ts/model/line.ts
+++ b/resources/ts/model/line.ts
@@ -6,4 +6,10 @@ export interface Line {
type: LineType;
night: boolean;
fast: boolean;
+}
+
+export interface Track {
+ id: string;
+ description: string;
+ line: Line;
}
\ No newline at end of file
diff --git a/resources/ts/types/popper.js.d.ts b/resources/ts/types/popper.js.d.ts
deleted file mode 100644
index a95552e..0000000
--- a/resources/ts/types/popper.js.d.ts
+++ /dev/null
@@ -1,131 +0,0 @@
-declare class Popper {
- static modifiers: (Popper.BaseModifier & { name: string })[];
- static placements: Popper.Placement[];
- static Defaults: Popper.PopperOptions;
-
- options: Popper.PopperOptions;
-
- constructor(reference: Element | Popper.ReferenceObject, popper: Element, options?: Popper.PopperOptions);
-
- destroy(): void;
- update(): void;
- scheduleUpdate(): void;
- enableEventListeners(): void;
- disableEventListeners(): void;
-}
-
-declare namespace Popper {
- export type Position = 'top' | 'right' | 'bottom' | 'left';
-
- export type Placement = 'auto-start'
- | 'auto'
- | 'auto-end'
- | 'top-start'
- | 'top'
- | 'top-end'
- | 'right-start'
- | 'right'
- | 'right-end'
- | 'bottom-end'
- | 'bottom'
- | 'bottom-start'
- | 'left-end'
- | 'left'
- | 'left-start';
-
- export type Boundary = 'scrollParent' | 'viewport' | 'window';
-
- export type Behavior = 'flip' | 'clockwise' | 'counterclockwise';
-
- export type ModifierFn = (data: Data, options: Object) => Data;
-
- export interface BaseModifier {
- order?: number;
- enabled?: boolean;
- fn?: ModifierFn;
- }
-
- export interface Modifiers {
- shift?: BaseModifier;
- offset?: BaseModifier & {
- offset?: number | string,
- };
- preventOverflow?: BaseModifier & {
- priority?: Position[],
- padding?: number,
- boundariesElement?: Boundary | Element,
- escapeWithReference?: boolean
- };
- keepTogether?: BaseModifier;
- arrow?: BaseModifier & {
- element?: string | Element,
- };
- flip?: BaseModifier & {
- behavior?: Behavior | Position[],
- padding?: number,
- boundariesElement?: Boundary | Element,
- };
- inner?: BaseModifier;
- hide?: BaseModifier;
- applyStyle?: BaseModifier & {
- onLoad?: Function,
- gpuAcceleration?: boolean,
- };
- computeStyle?: BaseModifier & {
- gpuAcceleration?: boolean;
- x?: 'bottom' | 'top',
- y?: 'left' | 'right'
- };
-
- [name: string]: (BaseModifier & Record) | undefined;
- }
-
- export interface Offset {
- top: number;
- left: number;
- width: number;
- height: number;
- }
-
- export interface Data {
- instance: Popper;
- placement: Placement;
- originalPlacement: Placement;
- flipped: boolean;
- hide: boolean;
- arrowElement: Element;
- styles: CSSStyleDeclaration;
- boundaries: Object;
- offsets: {
- popper: Offset,
- reference: Offset,
- arrow: {
- top: number,
- left: number,
- },
- };
- }
-
- export interface PopperOptions {
- placement?: Placement;
- positionFixed?: boolean;
- eventsEnabled?: boolean;
- modifiers?: Modifiers;
- removeOnDestroy?: boolean;
-
- onCreate?(data: Data): void;
-
- onUpdate?(data: Data): void;
- }
-
- export interface ReferenceObject {
- clientHeight: number;
- clientWidth: number;
-
- getBoundingClientRect(): ClientRect;
- }
-}
-
-declare module "popper.js" {
- export = Popper;
-}
diff --git a/resources/ts/urls.ts b/resources/ts/urls.ts
index 0114a69..73c59c8 100644
--- a/resources/ts/urls.ts
+++ b/resources/ts/urls.ts
@@ -52,7 +52,8 @@ export default {
stops: {
all: `${base}/stops`,
search: `${base}/stops/search`,
- get: `${base}/stops/{id}`
+ get: `${base}/stops/{id}`,
+ tracks: `${base}/stops/{id}/tracks`
},
prepare: (url: string, params: UrlParams = { }) => prepare(url, Object.assign({}, { provider: window['app'].provider }, params))
}
\ No newline at end of file
diff --git a/resources/ts/utils.ts b/resources/ts/utils.ts
index 748cbe4..a42cf3b 100644
--- a/resources/ts/utils.ts
+++ b/resources/ts/utils.ts
@@ -7,6 +7,7 @@ type Simplify = string |
export type Jsonified = { [K in keyof T]: Simplify }
export type Optionalify = { [K in keyof T]?: T[K] }
+export type Dictionary = { [key: string]: T };
export type Index = string | symbol | number;
diff --git a/src/Controller/Api/v1/StopsController.php b/src/Controller/Api/v1/StopsController.php
index 9494f30..3611189 100644
--- a/src/Controller/Api/v1/StopsController.php
+++ b/src/Controller/Api/v1/StopsController.php
@@ -4,7 +4,10 @@
namespace App\Controller\Api\v1;
use App\Controller\Controller;
+use App\Model\Stop;
use App\Provider\StopRepository;
+use App\Provider\TrackRepository;
+use App\Service\Proxy\ReferenceFactory;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
@@ -47,4 +50,16 @@ class StopsController extends Controller
{
return $this->json($stops->getById($id));
}
+
+ /**
+ * @Route("/{id}/tracks", methods={"GET"})
+ */
+ public function tracks(ReferenceFactory $reference, TrackRepository $tracks, $id)
+ {
+ $stop = $reference->get(Stop::class, $id);
+
+ return $this->json($tracks->getByStop($stop)->map(function ($tuple) {
+ return array_combine(['track', 'order'], $tuple);
+ }));
+ }
}
\ No newline at end of file
diff --git a/src/Entity/TrackEntity.php b/src/Entity/TrackEntity.php
index b3d2482..6ba5901 100644
--- a/src/Entity/TrackEntity.php
+++ b/src/Entity/TrackEntity.php
@@ -45,7 +45,7 @@ class TrackEntity implements Entity, Fillable
/**
* Stops in track
* @var Collection
- * @ORM\OneToMany(targetEntity=StopInTrack::class, mappedBy="track", cascade={"persist"})
+ * @ORM\OneToMany(targetEntity=StopInTrack::class, fetch="EXTRA_LAZY", mappedBy="track", cascade={"persist"})
* @ORM\OrderBy({"order": "ASC"})
*/
private $stopsInTrack;
@@ -104,9 +104,4 @@ class TrackEntity implements Entity, Fillable
{
$this->stopsInTrack = new ArrayCollection($stopsInTrack);
}
-
- public function getStops()
- {
- return $this->getStopsInTrack()->map(t\property('stop'));
- }
}
\ No newline at end of file
diff --git a/src/Provider/Database/DatabaseRepository.php b/src/Provider/Database/DatabaseRepository.php
index 1581733..4d174dc 100644
--- a/src/Provider/Database/DatabaseRepository.php
+++ b/src/Provider/Database/DatabaseRepository.php
@@ -4,6 +4,7 @@ namespace App\Provider\Database;
use App\Entity\Entity;
use App\Entity\ProviderEntity;
+use App\Model\Referable;
use App\Service\EntityConverter;
use App\Service\IdUtils;
use Doctrine\ORM\EntityManagerInterface;
@@ -48,4 +49,11 @@ class DatabaseRepository
{
return $this->converter->convert($entity);
}
+
+ protected function reference($class, Referable $referable)
+ {
+ $id = $this->id->generate($this->provider, $referable->getId());
+
+ return $this->em->getReference($class, $id);
+ }
}
\ No newline at end of file
diff --git a/src/Provider/Database/GenericTrackRepository.php b/src/Provider/Database/GenericTrackRepository.php
new file mode 100644
index 0000000..1047093
--- /dev/null
+++ b/src/Provider/Database/GenericTrackRepository.php
@@ -0,0 +1,61 @@
+em->getRepository(TrackEntity::class)->findAll();
+
+ return collect($tracks)->map(f\ref([$this, 'convert']));
+ }
+
+ public function getById($id): Track
+ {
+ // TODO: Implement getById() method.
+ }
+
+ public function getManyById($ids): Collection
+ {
+ // TODO: Implement getManyById() method.
+ }
+
+ public function getByStop($stop): Collection
+ {
+ $tracks = $this->em->createQueryBuilder()
+ ->from(StopInTrack::class, 'st')
+ ->join('st.track', 't')
+ ->where('st.stop = :stop')
+ ->select(['st', 't'])
+ ->getQuery()
+ ->execute(['stop' => $this->reference(StopEntity::class, $stop)]);
+
+ return collect($tracks)->map(function (StopInTrack $entity) {
+ return [ $this->convert($entity->getTrack()), $entity->getOrder() ];
+ });
+ }
+
+ public function getByLine($line): Collection
+ {
+ $tracks = $this->em->createQueryBuilder()
+ ->from(StopInTrack::class, 'st')
+ ->join('st.track', 't')
+ ->join('t.stops', 's')
+ ->where('st.line = :line')
+ ->select(['st', 't', 's'])
+ ->getQuery()
+ ->execute(['stop' => $this->reference(LineEntity::class, $line)]);
+
+ return collect($tracks)->map(f\ref([$this, 'convert']));
+ }
+}
\ No newline at end of file
diff --git a/src/Provider/Provider.php b/src/Provider/Provider.php
index 386ecc4..f346fec 100644
--- a/src/Provider/Provider.php
+++ b/src/Provider/Provider.php
@@ -8,6 +8,7 @@ interface Provider
public function getLineRepository(): LineRepository;
public function getStopRepository(): StopRepository;
public function getMessageRepository(): MessageRepository;
+ public function getTrackRepository(): TrackRepository;
public function getName();
public function getIdentifier();
diff --git a/src/Provider/TrackRepository.php b/src/Provider/TrackRepository.php
new file mode 100644
index 0000000..708e329
--- /dev/null
+++ b/src/Provider/TrackRepository.php
@@ -0,0 +1,17 @@
+logger->info(sprintf('Saving %d tracks from ZTM Gdańsk', count($stops)));
return collect($tracks)->map(function ($track) use ($provider, $stops) {
- $track = TrackEntity::createFromArray([
- 'id' => $track['id'],
+ $entity = TrackEntity::createFromArray([
+ 'id' => $this->ids->generate($provider, $track['id']),
'line' => $this->em->getReference(
LineEntity::class,
$this->ids->generate($provider, $track['routeId'])
@@ -169,20 +169,20 @@ class ZtmGdanskDataUpdateSubscriber implements EventSubscriberInterface
'provider' => $provider,
]);
- $stops = $stops->get($track->getId())->map(function ($stop) use ($track, $provider) {
+ $stops = $stops->get($track['id'])->map(function ($stop) use ($entity, $provider) {
return StopInTrack::createFromArray([
'stop' => $this->em->getReference(
StopEntity::class,
$this->ids->generate($provider, $stop['stopId'])
),
- 'track' => $track,
+ 'track' => $entity,
'order' => $stop['stopSequence'],
]);
});
- $track->setStopsInTrack($stops->all());
+ $entity->setStopsInTrack($stops->all());
- return $track;
+ return $entity;
});
}
diff --git a/src/Provider/ZtmGdanskProvider.php b/src/Provider/ZtmGdanskProvider.php
index 12e9c8e..95ba876 100644
--- a/src/Provider/ZtmGdanskProvider.php
+++ b/src/Provider/ZtmGdanskProvider.php
@@ -6,6 +6,7 @@ namespace App\Provider;
use App\Entity\ProviderEntity;
use App\Provider\Database\GenericLineRepository;
use App\Provider\Database\GenericStopRepository;
+use App\Provider\Database\GenericTrackRepository;
use App\Provider\ZtmGdansk\{ZtmGdanskDepartureRepository, ZtmGdanskMessageRepository};
use Doctrine\ORM\EntityManagerInterface;
@@ -14,6 +15,7 @@ class ZtmGdanskProvider implements Provider
private $lines;
private $departures;
private $stops;
+ private $tracks;
private $messages;
public function getName()
@@ -30,17 +32,20 @@ class ZtmGdanskProvider implements Provider
EntityManagerInterface $em,
GenericLineRepository $lines,
GenericStopRepository $stops,
+ GenericTrackRepository $tracks,
ZtmGdanskMessageRepository $messages
) {
$provider = $em->getReference(ProviderEntity::class, $this->getIdentifier());
- $lines = $lines->withProvider($provider);
- $stops = $stops->withProvider($provider);
+ $lines = $lines->withProvider($provider);
+ $stops = $stops->withProvider($provider);
+ $tracks = $tracks->withProvider($provider);
$this->lines = $lines;
$this->departures = new ZtmGdanskDepartureRepository($lines);
$this->stops = $stops;
$this->messages = $messages;
+ $this->tracks = $tracks;
}
public function getDepartureRepository(): DepartureRepository
@@ -62,4 +67,9 @@ class ZtmGdanskProvider implements Provider
{
return $this->messages;
}
+
+ public function getTrackRepository(): TrackRepository
+ {
+ return $this->tracks;
+ }
}
\ No newline at end of file
diff --git a/src/Service/EntityConverter.php b/src/Service/EntityConverter.php
index 9a2e3e2..c36aa39 100644
--- a/src/Service/EntityConverter.php
+++ b/src/Service/EntityConverter.php
@@ -11,10 +11,11 @@ use App\Model\Line;
use App\Model\Operator;
use App\Model\Stop;
use App\Model\Track;
-use App\Service\Proxy\ReferenceObjectFactory;
+use App\Service\Proxy\ReferenceFactory;
use Doctrine\ORM\PersistentCollection;
use Doctrine\ORM\Proxy\Proxy;
use Kadet\Functional as f;
+use Kadet\Functional\Transforms as t;
use const Kadet\Functional\_;
final class EntityConverter
@@ -22,7 +23,7 @@ final class EntityConverter
private $id;
private $reference;
- public function __construct(IdUtils $id, ReferenceObjectFactory $reference)
+ public function __construct(IdUtils $id, ReferenceFactory $reference)
{
$this->id = $id;
$this->reference = $reference;
@@ -66,7 +67,7 @@ final class EntityConverter
'operator' => $convert($entity->getOperator()),
'night' => $entity->isNight(),
'fast' => $entity->isFast(),
- 'tracks' => $this->collection($entity->getTracks(), $convert),
+ 'tracks' => $this->collection($entity->getTracks())->map($convert),
]);
break;
@@ -74,7 +75,9 @@ final class EntityConverter
$result->fill([
'variant' => $entity->getVariant(),
'description' => $entity->getDescription(),
- 'stops' => $this->collection($entity->getStops(), $convert),
+ 'stops' => $this->collection($entity->getStopsInTrack())
+ ->map(t\property('stop'))
+ ->map($convert),
'line' => $convert($entity->getLine()),
]);
break;
@@ -89,6 +92,7 @@ final class EntityConverter
$entity->getLongitude(),
],
]);
+ break;
}
return $result;
@@ -106,10 +110,10 @@ final class EntityConverter
return $entity->getId();
}
- private function collection(PersistentCollection $collection, $converter)
+ private function collection($collection)
{
- if ($collection->isInitialized()) {
- return collect($collection)->map($converter);
+ if (!$collection instanceof PersistentCollection || $collection->isInitialized()) {
+ return collect($collection);
}
return collect();
diff --git a/src/Service/Normalizer/JustReferenceNormalizer.php b/src/Service/Normalizer/JustReferenceNormalizer.php
index d30deea..54a8cd4 100644
--- a/src/Service/Normalizer/JustReferenceNormalizer.php
+++ b/src/Service/Normalizer/JustReferenceNormalizer.php
@@ -26,7 +26,7 @@ class JustReferenceNormalizer implements NormalizerInterface
*/
public function normalize($object, $format = null, array $context = [])
{
- return [ 'id' => $object->getId() ];
+ return [ 'id' => $object->getId(), 'href' => '#' ];
}
/**
diff --git a/src/Service/Proxy/ReferenceObjectFactory.php b/src/Service/Proxy/ReferenceFactory.php
similarity index 89%
rename from src/Service/Proxy/ReferenceObjectFactory.php
rename to src/Service/Proxy/ReferenceFactory.php
index fdb0dd4..72b170b 100644
--- a/src/Service/Proxy/ReferenceObjectFactory.php
+++ b/src/Service/Proxy/ReferenceFactory.php
@@ -5,7 +5,7 @@ namespace App\Service\Proxy;
use ProxyManager\Factory\AbstractBaseFactory;
use ProxyManager\ProxyGenerator\ProxyGeneratorInterface;
-class ReferenceObjectFactory extends AbstractBaseFactory
+class ReferenceFactory extends AbstractBaseFactory
{
public function get($class, $id)
{
diff --git a/src/Service/RepositoryParameterConverter.php b/src/Service/RepositoryParameterConverter.php
index 02f8ca9..d5b6704 100644
--- a/src/Service/RepositoryParameterConverter.php
+++ b/src/Service/RepositoryParameterConverter.php
@@ -9,6 +9,7 @@ use App\Provider\DepartureRepository;
use App\Provider\LineRepository;
use App\Provider\MessageRepository;
use App\Provider\StopRepository;
+use App\Provider\TrackRepository;
use const Kadet\Functional\_;
use function Kadet\Functional\any;
use function Kadet\Functional\curry;
@@ -59,6 +60,10 @@ class RepositoryParameterConverter implements ParamConverterInterface
$request->attributes->set($configuration->getName(), $provider->getMessageRepository());
break;
+ case is_a($class, TrackRepository::class, true):
+ $request->attributes->set($configuration->getName(), $provider->getTrackRepository());
+ break;
+
default:
return false;
}
@@ -75,7 +80,8 @@ class RepositoryParameterConverter implements ParamConverterInterface
StopRepository::class,
LineRepository::class,
DepartureRepository::class,
- MessageRepository::class
+ MessageRepository::class,
+ TrackRepository::class,
]));
return $supports($configuration->getClass());
diff --git a/templates/app.html.twig b/templates/app.html.twig
index fe97015..f65462b 100644
--- a/templates/app.html.twig
+++ b/templates/app.html.twig
@@ -1,5 +1,6 @@
{% extends 'base.html.twig' %}
{% block title "#{parent()} - #{provider.name}" %}
+
{% block body %}
{% endblock %}