Add final stop info to track
This commit is contained in:
parent
f3fc6cb071
commit
38e6ae52e1
@ -22,11 +22,14 @@
|
||||
</div>
|
||||
<ul class="stop-group__stops list-underlined">
|
||||
<li v-for="stop in group" :key="stop.id" class="d-flex">
|
||||
<button @click="select(stop, $event)" class="btn btn-action align-self-start">
|
||||
<tooltip>dodaj przystanek</tooltip>
|
||||
<fa :icon="['fal', 'check']" />
|
||||
</button>
|
||||
<picker-stop :stop="stop" class="flex-grow-1"></picker-stop>
|
||||
<picker-stop :stop="stop" class="flex-grow-1">
|
||||
<template v-slot:primary-action>
|
||||
<button @click="select(stop, $event)" class="btn btn-action align-self-start">
|
||||
<tooltip>dodaj przystanek</tooltip>
|
||||
<fa :icon="['fal', 'check']" />
|
||||
</button>
|
||||
</template>
|
||||
</picker-stop>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -1,19 +1,27 @@
|
||||
<div class="d-flex flex-wrap">
|
||||
<stop :stop="stop" />
|
||||
<div class="finder__stop">
|
||||
<div class="d-flex">
|
||||
<slot name="primary-action" />
|
||||
<div style="overflow: hidden">
|
||||
<stop :stop="stop" />
|
||||
<!-- <div style="white-space: nowrap">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Earum, ut!</div>-->
|
||||
<ul class="stop__destinations">
|
||||
<li class="stop__destination" v-for="destination in stop.destinations" :key="destination.id"><stop :stop="destination"/></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="stop__actions flex-space-left">
|
||||
<slot name="actions">
|
||||
<button class="btn btn-action" ref="action-info" @click="details = !details">
|
||||
<tooltip>dodatkowe informacje</tooltip>
|
||||
<fa :icon="['fal', details ? 'chevron-circle-up' : 'info-circle']"/>
|
||||
</button>
|
||||
<div class="stop__actions flex-space-left">
|
||||
<slot name="actions">
|
||||
<button class="btn btn-action" ref="action-info" @click="details = !details">
|
||||
<tooltip>dodatkowe informacje</tooltip>
|
||||
<fa :icon="['fal', details ? 'chevron-circle-up' : 'info-circle']"/>
|
||||
</button>
|
||||
|
||||
<button class="btn btn-action" ref="action-map" v-hover:map>
|
||||
<fa :icon="['fal', 'map-marker-alt']"/>
|
||||
</button>
|
||||
</slot>
|
||||
<button class="btn btn-action" ref="action-map" v-hover:map>
|
||||
<fa :icon="['fal', 'map-marker-alt']"/>
|
||||
</button>
|
||||
</slot>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<fold :visible="details" class="stop__details-fold" lazy>
|
||||
<stop-details :stop="stop"/>
|
||||
</fold>
|
||||
|
@ -11,6 +11,7 @@
|
||||
font-size: $small-font-size;
|
||||
overflow-x: hidden;
|
||||
text-overflow: ellipsis;
|
||||
max-width: 100%;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
|
@ -5,7 +5,7 @@
|
||||
}
|
||||
|
||||
.stop__name {
|
||||
flex: 1 0;
|
||||
//flex: 1 0;
|
||||
line-height: 1.1;
|
||||
margin-right: .5em;
|
||||
}
|
||||
@ -46,3 +46,15 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.stop__destinations {
|
||||
@extend .favourite__stops;
|
||||
}
|
||||
|
||||
.stop__destination {
|
||||
@extend .favourite__stop;
|
||||
}
|
||||
|
||||
.finder__stop {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ export interface Stop {
|
||||
};
|
||||
onDemand?: boolean;
|
||||
variant?: string;
|
||||
destinations?: Stop[];
|
||||
}
|
||||
|
||||
export type StopGroup = Stop[];
|
||||
|
@ -4,32 +4,42 @@ namespace App\Entity;
|
||||
|
||||
use App\Model\Fillable;
|
||||
use App\Model\FillTrait;
|
||||
use App\Model\Referable;
|
||||
use App\Model\ReferableTrait;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
/**
|
||||
* @ORM\Entity
|
||||
* @ORM\Table("track_stop")
|
||||
* @ORM\Table("track_stop", uniqueConstraints={
|
||||
* @ORM\UniqueConstraint(name="stop_in_track_idx", columns={"stop_id", "track_id", "sequence"})
|
||||
* })
|
||||
*/
|
||||
class StopInTrack implements Fillable
|
||||
class StopInTrack implements Fillable, Referable
|
||||
{
|
||||
use FillTrait;
|
||||
use FillTrait, ReferableEntityTrait;
|
||||
|
||||
/**
|
||||
* Identifier for stop coming from provider
|
||||
*
|
||||
* @ORM\Column(type="integer")
|
||||
* @ORM\Id
|
||||
* @ORM\GeneratedValue
|
||||
*/
|
||||
private $id;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity=StopEntity::class, fetch="EAGER")
|
||||
* @ORM\Id
|
||||
*/
|
||||
private $stop;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity=TrackEntity::class, fetch="EAGER", inversedBy="stopsInTrack")
|
||||
* @ORM\Id
|
||||
*/
|
||||
private $track;
|
||||
|
||||
/**
|
||||
* Order in track
|
||||
* @var int
|
||||
* @ORM\Id
|
||||
* @ORM\Column(name="sequence", type="integer")
|
||||
*/
|
||||
private $order;
|
||||
|
@ -4,6 +4,7 @@ namespace App\Entity;
|
||||
|
||||
use App\Model\Fillable;
|
||||
use App\Model\FillTrait;
|
||||
use App\Service\IterableUtils;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
@ -50,6 +51,12 @@ class TrackEntity implements Entity, Fillable
|
||||
*/
|
||||
private $stopsInTrack;
|
||||
|
||||
/**
|
||||
* Final stop in this track.
|
||||
* @var StopInTrack
|
||||
* @ORM\OneToOne(targetEntity=StopInTrack::class, fetch="LAZY")
|
||||
*/
|
||||
private $final;
|
||||
|
||||
/**
|
||||
* Track constructor.
|
||||
@ -98,15 +105,17 @@ class TrackEntity implements Entity, Fillable
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $stopsInTrack
|
||||
* @param iterable $stopsInTrack
|
||||
*/
|
||||
public function setStopsInTrack(array $stopsInTrack): void
|
||||
public function setStopsInTrack(iterable $stopsInTrack): void
|
||||
{
|
||||
$this->stopsInTrack = new ArrayCollection($stopsInTrack);
|
||||
$this->stopsInTrack = IterableUtils::toArrayCollection($stopsInTrack);
|
||||
|
||||
$this->final = $this->stopsInTrack->last();
|
||||
}
|
||||
|
||||
public function getFinal(): StopInTrack
|
||||
{
|
||||
return $this->getStopsInTrack()->last();
|
||||
return $this->final;
|
||||
}
|
||||
}
|
||||
|
57
src/Migrations/Version20200206183956.php
Normal file
57
src/Migrations/Version20200206183956.php
Normal file
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DoctrineMigrations;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20200206183956 extends AbstractMigration
|
||||
{
|
||||
public function getDescription() : string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function up(Schema $schema) : void
|
||||
{
|
||||
// this up() migration is auto-generated, please modify it to your needs
|
||||
$this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'sqlite', 'Migration can only be executed safely on \'sqlite\'.');
|
||||
|
||||
$this->addSql('CREATE TEMPORARY TABLE __temp__track AS SELECT id, line_id, provider_id, variant, description FROM track');
|
||||
$this->addSql('DROP TABLE track');
|
||||
$this->addSql('CREATE TABLE track (id VARCHAR(255) NOT NULL COLLATE BINARY, line_id VARCHAR(255) DEFAULT NULL COLLATE BINARY, provider_id VARCHAR(255) DEFAULT NULL COLLATE BINARY, variant VARCHAR(16) DEFAULT NULL COLLATE BINARY, description VARCHAR(256) DEFAULT NULL COLLATE BINARY, final_id INTEGER DEFAULT NULL, PRIMARY KEY(id))');
|
||||
$this->addSql('INSERT INTO track (id, line_id, provider_id, variant, description) SELECT id, line_id, provider_id, variant, description FROM __temp__track');
|
||||
$this->addSql('DROP TABLE __temp__track');
|
||||
$this->addSql('CREATE UNIQUE INDEX UNIQ_D6E3F8A613D41B2D ON track (final_id)');
|
||||
$this->addSql('CREATE TEMPORARY TABLE __temp__track_stop AS SELECT stop_id, track_id, sequence FROM track_stop');
|
||||
$this->addSql('DROP TABLE track_stop');
|
||||
$this->addSql('CREATE TABLE track_stop (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, sequence INTEGER NOT NULL, stop_id VARCHAR(255) DEFAULT NULL, track_id VARCHAR(255) DEFAULT NULL)');
|
||||
$this->addSql('INSERT INTO track_stop (stop_id, track_id, sequence) SELECT stop_id, track_id, sequence FROM __temp__track_stop');
|
||||
$this->addSql('DROP TABLE __temp__track_stop');
|
||||
$this->addSql('CREATE UNIQUE INDEX stop_in_track_idx ON track_stop (stop_id, track_id, sequence)');
|
||||
}
|
||||
|
||||
public function down(Schema $schema) : void
|
||||
{
|
||||
// this down() migration is auto-generated, please modify it to your needs
|
||||
$this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'sqlite', 'Migration can only be executed safely on \'sqlite\'.');
|
||||
|
||||
$this->addSql('DROP INDEX UNIQ_D6E3F8A613D41B2D');
|
||||
$this->addSql('CREATE TEMPORARY TABLE __temp__track AS SELECT id, variant, description, line_id, provider_id FROM track');
|
||||
$this->addSql('DROP TABLE track');
|
||||
$this->addSql('CREATE TABLE track (id VARCHAR(255) NOT NULL, variant VARCHAR(16) DEFAULT NULL, description VARCHAR(256) DEFAULT NULL, line_id VARCHAR(255) DEFAULT NULL, provider_id VARCHAR(255) DEFAULT NULL, PRIMARY KEY(id))');
|
||||
$this->addSql('INSERT INTO track (id, variant, description, line_id, provider_id) SELECT id, variant, description, line_id, provider_id FROM __temp__track');
|
||||
$this->addSql('DROP TABLE __temp__track');
|
||||
$this->addSql('DROP INDEX stop_in_track_idx');
|
||||
$this->addSql('CREATE TEMPORARY TABLE __temp__track_stop AS SELECT sequence, stop_id, track_id FROM track_stop');
|
||||
$this->addSql('DROP TABLE track_stop');
|
||||
$this->addSql('CREATE TABLE track_stop (sequence INTEGER NOT NULL, stop_id VARCHAR(255) NOT NULL COLLATE BINARY, track_id VARCHAR(255) NOT NULL COLLATE BINARY, PRIMARY KEY(stop_id, track_id, sequence))');
|
||||
$this->addSql('INSERT INTO track_stop (sequence, stop_id, track_id) SELECT sequence, stop_id, track_id FROM __temp__track_stop');
|
||||
$this->addSql('DROP TABLE __temp__track_stop');
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Model;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use JMS\Serializer\Annotation as Serializer;
|
||||
|
||||
trait ReferableTrait
|
||||
@ -38,4 +39,4 @@ trait ReferableTrait
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,10 +3,8 @@
|
||||
namespace App\Provider\Database;
|
||||
|
||||
use App\Entity\StopEntity;
|
||||
use App\Entity\StopInTrack;
|
||||
use App\Entity\TrackEntity;
|
||||
use App\Model\Stop;
|
||||
use App\Model\Track;
|
||||
use App\Provider\StopRepository;
|
||||
use Tightenco\Collect\Support\Collection;
|
||||
use Kadet\Functional as f;
|
||||
@ -23,7 +21,7 @@ class GenericStopRepository extends DatabaseRepository implements StopRepository
|
||||
|
||||
public function getById($id): ?Stop
|
||||
{
|
||||
$id = $this->id->generate($this->provider, $id);
|
||||
$id = $this->id->generate($this->provider, $id);
|
||||
$stop = $this->em->getRepository(StopEntity::class)->find($id);
|
||||
|
||||
return $this->convert($stop);
|
||||
@ -31,7 +29,7 @@ class GenericStopRepository extends DatabaseRepository implements StopRepository
|
||||
|
||||
public function getManyById($ids): Collection
|
||||
{
|
||||
$ids = collect($ids)->map(f\apply(f\ref([$this->id, 'generate']), $this->provider));
|
||||
$ids = collect($ids)->map(f\apply(f\ref([$this->id, 'generate']), $this->provider));
|
||||
$stops = $this->em->getRepository(StopEntity::class)->findBy(['id' => $ids->all()]);
|
||||
|
||||
return collect($stops)->map(f\ref([$this, 'convert']));
|
||||
@ -48,12 +46,12 @@ class GenericStopRepository extends DatabaseRepository implements StopRepository
|
||||
$stops = collect($query->execute([':name' => "%$name%"]));
|
||||
|
||||
$destinations = collect($this->em->createQueryBuilder()
|
||||
->select('t', 'ts', 'ts2', 's')
|
||||
->select('t', 'f', 'fs', 'ts')
|
||||
->from(TrackEntity::class, 't')
|
||||
->join('t.stopsInTrack', 'ts')
|
||||
->join('t.stopsInTrack', 'ts2')
|
||||
->join('ts2.stop', 's')
|
||||
->where('ts.stop IN (:stops)')
|
||||
->join('t.final', 'f')
|
||||
->join('f.stop', 'fs')
|
||||
->getQuery()
|
||||
->execute(['stops' => $stops->map(t\property('id'))->all()]))
|
||||
->reduce(function ($grouped, TrackEntity $track) {
|
||||
@ -67,8 +65,7 @@ class GenericStopRepository extends DatabaseRepository implements StopRepository
|
||||
return $tracks->map(function (TrackEntity $track) {
|
||||
return $this->convert($track->getFinal()->getStop());
|
||||
})->unique()->values();
|
||||
})
|
||||
;
|
||||
});
|
||||
|
||||
return collect($stops)->map(f\ref([$this, 'convert']))->each(function (Stop $stop) use ($destinations) {
|
||||
$stop->setDestinations($destinations[$this->id->generate($this->provider, $stop->getId())]);
|
||||
|
@ -12,7 +12,6 @@ use App\Entity\TripEntity;
|
||||
use App\Entity\TripStopEntity;
|
||||
use App\Event\DataUpdateEvent;
|
||||
use App\Model\Line as LineModel;
|
||||
use App\Model\Location;
|
||||
use App\Service\DataUpdater;
|
||||
use App\Service\IdUtils;
|
||||
use Carbon\Carbon;
|
||||
@ -20,13 +19,10 @@ use Cerbero\JsonObjects\JsonObjects;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Component\Console\Helper\ProgressBar;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Console\Output\ConsoleOutputInterface;
|
||||
use Symfony\Component\Console\Output\ConsoleSectionOutput;
|
||||
use Symfony\Component\Console\Output\NullOutput;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Tightenco\Collect\Support\Collection;
|
||||
use function Cerbero\JsonObjects\JsonObjects;
|
||||
use function Kadet\Functional\ref;
|
||||
use function Kadet\Functional\Transforms\property;
|
||||
|
||||
class ZtmGdanskDataUpdateSubscriber implements EventSubscriberInterface
|
||||
{
|
||||
@ -45,6 +41,8 @@ class ZtmGdanskDataUpdateSubscriber implements EventSubscriberInterface
|
||||
private $logger;
|
||||
private $provider;
|
||||
|
||||
private $stopBlacklist = [];
|
||||
|
||||
/**
|
||||
* ZtmGdanskDataUpdateSubscriber constructor.
|
||||
*
|
||||
@ -147,6 +145,7 @@ class ZtmGdanskDataUpdateSubscriber implements EventSubscriberInterface
|
||||
|
||||
private function getStops(ProviderEntity $provider, DataUpdateEvent $event)
|
||||
{
|
||||
$this->stopBlacklist = [];
|
||||
$output = $event->getOutput();
|
||||
|
||||
$output->write('Obtaining stops from ZTM Gdańsk... ');
|
||||
@ -157,9 +156,12 @@ class ZtmGdanskDataUpdateSubscriber implements EventSubscriberInterface
|
||||
$this->logger->debug(sprintf("Saving %d stops tracks from ZTM Gdańsk.", count($stops)));
|
||||
return collect($stops)
|
||||
->filter(function ($stop) {
|
||||
return $stop['nonpassenger'] !== 1
|
||||
&& $stop['virtual'] !== 1
|
||||
&& $stop['depot'] !== 1;
|
||||
if ($stop['nonpassenger'] === 1 || $stop['virtual'] === 1 || $stop['depot'] === 1) {
|
||||
$this->stopBlacklist[] = $stop['stopId'];
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
})
|
||||
->map(function ($stop) use ($provider) {
|
||||
$name = trim($stop['stopName'] ?? $stop['stopDesc']);
|
||||
@ -178,7 +180,7 @@ class ZtmGdanskDataUpdateSubscriber implements EventSubscriberInterface
|
||||
;
|
||||
}
|
||||
|
||||
public function getTracks(ProviderEntity $provider, DataUpdateEvent $event, $stops = [])
|
||||
public function getTracks(ProviderEntity $provider, DataUpdateEvent $event, Collection $stops = null)
|
||||
{
|
||||
$output = $event->getOutput();
|
||||
|
||||
@ -209,19 +211,24 @@ class ZtmGdanskDataUpdateSubscriber implements EventSubscriberInterface
|
||||
'provider' => $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' => $entity,
|
||||
// HACK! Gdynia has 0 based sequence
|
||||
'order' => $stop['stopSequence'] + (int)($stop['stopId'] > 30000),
|
||||
]);
|
||||
});
|
||||
$stops = $stops->get($track['id'])
|
||||
->filter(function ($stop) {
|
||||
return !in_array($stop['stopId'], $this->stopBlacklist);
|
||||
})
|
||||
->map(function ($stop) use ($entity, $provider) {
|
||||
return StopInTrack::createFromArray([
|
||||
'stop' => $this->em->getReference(
|
||||
StopEntity::class,
|
||||
$this->ids->generate($provider, $stop['stopId'])
|
||||
),
|
||||
'track' => $entity,
|
||||
// HACK! Gdynia has 0 based sequence
|
||||
'order' => $stop['stopSequence'] + (int)($stop['stopId'] > 30000),
|
||||
]);
|
||||
})
|
||||
->sortBy(property("order"));
|
||||
|
||||
$entity->setStopsInTrack($stops->all());
|
||||
$entity->setStopsInTrack($stops);
|
||||
|
||||
return $entity;
|
||||
});
|
||||
|
28
src/Service/IterableUtils.php
Normal file
28
src/Service/IterableUtils.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace App\Service;
|
||||
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Tightenco\Collect\Support\Collection;
|
||||
|
||||
final class IterableUtils
|
||||
{
|
||||
public static function toArray(iterable $iterable): array
|
||||
{
|
||||
if (is_array($iterable)) {
|
||||
return $iterable;
|
||||
}
|
||||
|
||||
return iterator_to_array($iterable);
|
||||
}
|
||||
|
||||
public static function toArrayCollection(iterable $iterable): ArrayCollection
|
||||
{
|
||||
return new ArrayCollection(static::toArray($iterable));
|
||||
}
|
||||
|
||||
public static function toCollection(iterable $iterable): Collection
|
||||
{
|
||||
return collect($iterable);
|
||||
}
|
||||
}
|
@ -101,11 +101,14 @@
|
||||
|
||||
<ul class="picker__stops list-underlined">
|
||||
<li v-for="stop in stops" :key="stop.id" class="d-flex align-items-center">
|
||||
<button @click="remove(stop)" class="btn btn-action align-self-start">
|
||||
<tooltip>usuń przystanek</tooltip>
|
||||
<fa :icon="['fal', 'times']"></fa>
|
||||
</button>
|
||||
<picker-stop :stop="stop" class="flex-grow-1"></picker-stop>
|
||||
<picker-stop :stop="stop" class="flex-grow-1">
|
||||
<template v-slot:primary-action>
|
||||
<button @click="remove(stop)" class="btn btn-action align-self-start">
|
||||
<tooltip>usuń przystanek</tooltip>
|
||||
<fa :icon="['fal', 'times']"></fa>
|
||||
</button>
|
||||
</template>
|
||||
</picker-stop>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@ -143,7 +146,7 @@
|
||||
</button>
|
||||
</template>
|
||||
</header>
|
||||
<div class="transition-box" style="overflow: hidden;">
|
||||
<div class="transition-box">
|
||||
<transition name="fade">
|
||||
<stop-finder @select="add" :blacklist="stops" v-if="visibility.picker === 'search'"></stop-finder>
|
||||
<favourites v-else-if="visibility.picker === 'favourites'"></favourites>
|
||||
|
Loading…
Reference in New Issue
Block a user