From 5ba878903ae3acda5092d8e64bd0ec8dcc05623f Mon Sep 17 00:00:00 2001 From: Levin Herr Date: Tue, 8 Jun 2021 21:56:13 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Set=20the=20visibility=20for=20stat?= =?UTF-8?q?uses=20individually=20(#410)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * added migration * Visibility-logic implemented. * Now like creation is only possible with a visibleToMe-Status! * icons to show the visibility of a status * Translations!!!1 Also visibility in events * Yay, the visibility-dropdown does now exist * check in with visibility * updates work now too (not in the api) * codacy, etc. * fixed tests. * fixed dropdown to btn-group * fixes * fixes * enum! * format * user Co-authored-by: Kris --- app/Enum/StatusVisibility.php | 12 +++ app/Http/Controllers/API/StatusController.php | 3 +- .../Controllers/API/TransportController.php | 2 + .../Controllers/API/v1/StatusController.php | 2 +- .../Controllers/FrontendStatusController.php | 12 ++- .../FrontendTransportController.php | 17 +++-- app/Http/Controllers/StatusController.php | 50 ++++++++---- app/Http/Controllers/TransportController.php | 8 +- app/Http/Controllers/UserController.php | 14 +++- app/Models/Status.php | 27 ++++++- ...6_07_145349_add_visibility_to_statuses.php | 22 ++++++ database/seeders/TrainCheckinSeeder.php | 2 + resources/js/components/business-check-in.js | 50 +++++++----- resources/lang/de.json | 8 ++ resources/lang/en.json | 8 ++ resources/sass/components/status.scss | 4 + .../includes/business-dropdown.blade.php | 50 ++++++------ resources/views/includes/edit-modal.blade.php | 4 +- resources/views/includes/status.blade.php | 6 +- .../includes/visibility-dropdown.blade.php | 33 ++++++++ resources/views/trip.blade.php | 29 ++++--- tests/Feature/CheckinTest.php | 44 ++++++----- tests/TestCase.php | 2 + tests/Unit/HelperMethodTest.php | 76 +++++++++---------- 24 files changed, 336 insertions(+), 149 deletions(-) create mode 100644 app/Enum/StatusVisibility.php create mode 100644 database/migrations/2021_06_07_145349_add_visibility_to_statuses.php create mode 100644 resources/views/includes/visibility-dropdown.blade.php diff --git a/app/Enum/StatusVisibility.php b/app/Enum/StatusVisibility.php new file mode 100644 index 000000000..7d9b51ccc --- /dev/null +++ b/app/Enum/StatusVisibility.php @@ -0,0 +1,12 @@ +sendError('Not found'); diff --git a/app/Http/Controllers/API/TransportController.php b/app/Http/Controllers/API/TransportController.php index 32ede57a2..56e391937 100644 --- a/app/Http/Controllers/API/TransportController.php +++ b/app/Http/Controllers/API/TransportController.php @@ -2,6 +2,7 @@ namespace App\Http\Controllers\API; +use App\Enum\StatusVisibility; use App\Enum\TravelType; use App\Exceptions\CheckInCollisionException; use App\Exceptions\HafasException; @@ -127,6 +128,7 @@ public function TrainCheckin(Request $request) { 0, $request->input('tweet'), $request->input('toot'), + StatusVisibility::PUBLIC, 0, isset($request->departure) ? Carbon::parse($request->input('departure')) : null, isset($request->arrival) ? Carbon::parse($request->input('arrival')) : null, diff --git a/app/Http/Controllers/API/v1/StatusController.php b/app/Http/Controllers/API/v1/StatusController.php index 41fe0136b..811f2d288 100644 --- a/app/Http/Controllers/API/v1/StatusController.php +++ b/app/Http/Controllers/API/v1/StatusController.php @@ -44,7 +44,7 @@ public function getPolyline(string $parameters): JsonResponse { ->with('trainCheckin.HafasTrip.getPolyLine') ->get() ->reject(function($status) { - return $status->user->userInvisibleToMe; + return ($status->user->userInvisibleToMe || $status->statusInvisibleToMe); }) ->mapWithKeys(function($status) { return [ $status->id => $status->trainCheckin->getMapLines() ]; diff --git a/app/Http/Controllers/FrontendStatusController.php b/app/Http/Controllers/FrontendStatusController.php index 509c0336b..aa1df8200 100644 --- a/app/Http/Controllers/FrontendStatusController.php +++ b/app/Http/Controllers/FrontendStatusController.php @@ -2,6 +2,7 @@ namespace App\Http\Controllers; +use App\Enum\StatusVisibility; use App\Exceptions\PermissionException; use App\Exceptions\StatusAlreadyLikedException; use App\Http\Controllers\Backend\EventController as EventBackend; @@ -67,14 +68,17 @@ public function DeleteStatus(Request $request): JsonResponse|RedirectResponse { public function EditStatus(Request $request): JsonResponse|RedirectResponse { $this->validate($request, [ - 'body' => ['max:280'], - 'business_check' => ['required', 'digits_between:0,2'], + 'body' => ['max:280'], + 'business_check' => ['required', 'digits_between:0,2'], + 'checkinVisibility' => ['required', Rule::in(StatusVisibility::getList())], ]); + $editStatusResponse = StatusBackend::EditStatus( Auth::user(), $request['statusId'], $request['body'], - $request['business_check'] + $request['business_check'], + $request['checkinVisibility'] ); if ($editStatusResponse === false) { return redirect()->back(); @@ -93,7 +97,7 @@ public function createLike(Request $request) { return response(__('controller.status.like-ok'), 201); } catch (StatusAlreadyLikedException $e) { return response(__('controller.status.like-already'), 409); - } catch (PermissionException $e) { + } catch (PermissionException) { abort(403); } } diff --git a/app/Http/Controllers/FrontendTransportController.php b/app/Http/Controllers/FrontendTransportController.php index b2a6ff0a9..f4f4ac8fc 100644 --- a/app/Http/Controllers/FrontendTransportController.php +++ b/app/Http/Controllers/FrontendTransportController.php @@ -2,6 +2,7 @@ namespace App\Http\Controllers; +use App\Enum\StatusVisibility; use App\Enum\TravelType; use App\Exceptions\CheckInCollisionException; use App\Exceptions\HafasException; @@ -126,13 +127,14 @@ public function TrainTrip(Request $request): Renderable|RedirectResponse { public function TrainCheckin(Request $request): RedirectResponse { $this->validate($request, [ - 'body' => 'max:280', - 'business_check' => 'digits_between:0,2', - 'tweet_check' => 'max:2', - 'toot_check' => 'max:2', - 'event' => 'integer', - 'departure' => ['required', 'date'], - 'arrival' => ['required', 'date'], + 'body' => 'max:280', + 'business_check' => 'digits_between:0,2', + 'checkinVisibility' => Rule::in(StatusVisibility::getList()), + 'tweet_check' => 'max:2', + 'toot_check' => 'max:2', + 'event' => 'integer', + 'departure' => ['required', 'date'], + 'arrival' => ['required', 'date'], ]); try { $trainCheckin = TransportBackend::TrainCheckin( @@ -144,6 +146,7 @@ public function TrainCheckin(Request $request): RedirectResponse { $request->business_check, $request->tweet_check, $request->toot_check, + $request->checkinVisibility, $request->event, Carbon::parse($request->departure), Carbon::parse($request->arrival), diff --git a/app/Http/Controllers/StatusController.php b/app/Http/Controllers/StatusController.php index 491a910e1..a26f32eba 100644 --- a/app/Http/Controllers/StatusController.php +++ b/app/Http/Controllers/StatusController.php @@ -2,6 +2,7 @@ namespace App\Http\Controllers; +use App\Enum\StatusVisibility; use App\Exceptions\PermissionException; use App\Exceptions\StatusAlreadyLikedException; use App\Models\Event; @@ -24,12 +25,12 @@ class StatusController extends Controller { /** - * @api v1 - * @frontend * @param int $statusId * @return Status * @throws HttpException * @throws ModelNotFoundException + * @api v1 + * @frontend */ public static function getStatus(int $statusId): Status { $status = Status::where('id', $statusId)->with('user', @@ -38,7 +39,7 @@ public static function getStatus(int $statusId): Status { 'trainCheckin.Destination', 'trainCheckin.HafasTrip', 'event')->withCount('likes')->firstOrFail(); - if (!$status->user->userInvisibleToMe) { + if (!$status->user->userInvisibleToMe && (!$status->statusInvisibleToMe || $status->visibility == StatusVisibility::UNLISTED)) { return $status; } @@ -48,11 +49,11 @@ public static function getStatus(int $statusId): Status { /** * This Method returns the current active status(es) for all users or a specific user. * - * @api v1 - * @frontend * @param null $userId UserId to get the current active status for a user. Defaults to null. * @param bool $array This parameter is a temporary solution until the frontend is no more dependend on blade. * @return Status|array|Builder|Model|object|null + * @api v1 + * @frontend */ public static function getActiveStatuses($userId = null, bool $array = true) { if ($userId === null) { @@ -71,7 +72,7 @@ public static function getActiveStatuses($userId = null, bool $array = true) { }) ->get() ->filter(function($status) { - return !$status->user->userInvisibleToMe; + return (!$status->user->userInvisibleToMe && !$status->statusInvisibleToMe); }) ->sortByDesc(function($status) { return $status->trainCheckin->departure; @@ -90,7 +91,7 @@ public static function getActiveStatuses($userId = null, bool $array = true) { }) ->where('user_id', $userId) ->first(); - if ($status?->user?->userInvisibleToMe) { + if ($status?->user?->userInvisibleToMe || $status?->statusInvisibleToMe) { return null; } return $status; @@ -126,6 +127,8 @@ public static function getDashboard(User $user): Paginator { ->select('statuses.*') ->orderBy('train_checkins.departure', 'desc') ->whereIn('user_id', $followingIDs) + ->whereIn('visibility', [StatusVisibility::PUBLIC, StatusVisibility::FOLLOWERS]) + ->orWhere('user_id', $user->id) ->withCount('likes') ->latest() ->simplePaginate(15); @@ -141,9 +144,16 @@ public static function getGlobalDashboard(): Paginator { ->join('train_checkins', 'train_checkins.status_id', '=', 'statuses.id') ->join('users', 'statuses.user_id', '=', 'users.id') ->where(function($query) { + $user = Auth::check() ? auth()->user() : null; $query->where('users.private_profile', 0) - ->orWhere('users.id', auth()->user()->id) - ->orWhereIn('users.id', auth()->user()->follows()->select('follow_id')); + ->where('visibility', StatusVisibility::PUBLIC) + ->orWhere('users.id', $user->id) + ->orWhere(function($query) { + $followings = Auth::check() ? auth()->user()->follows()->select('follow_id') : []; + $query->where('visibility', StatusVisibility::FOLLOWERS) + ->whereIn('users.id', $followings) + ->orWhere('visibility', StatusVisibility::PUBLIC); + }); }) ->whereHas('trainCheckin', function($query) { $query->where('departure', '<', date('Y-m-d H:i:s', strtotime("+20min"))); @@ -168,7 +178,7 @@ public static function DeleteStatus($user, $statusId): ?bool { return true; } - public static function EditStatus($user, $statusId, $body, $businessCheck): bool|string|null { + public static function EditStatus($user, $statusId, $body, $businessCheck, $visibility): bool|string|null { $status = Status::find($statusId); if ($status === null) { return null; @@ -179,6 +189,9 @@ public static function EditStatus($user, $statusId, $body, $businessCheck): bool $status->body = $body; $status->business = $businessCheck; + if ($visibility != null) { + $status->visibility = $visibility; + } $status->update(); return $status->body; } @@ -192,7 +205,7 @@ public static function EditStatus($user, $statusId, $body, $businessCheck): bool */ public static function createLike(User $user, Status $status): Like { - if ($status->user->UserInvisibleToMe) { + if (($status->StatusInvisibleToMe && $status->visibility != StatusVisibility::UNLISTED) || $status->user->UserInvisibleToMe) { throw new PermissionException(); } @@ -362,11 +375,16 @@ public static function getStatusesByEvent(?string $slug, ?int $id): array { ->select('statuses.*') ->join('users', 'statuses.user_id', '=', 'users.id') ->where(function($query) { - $query->where('users.private_profile', 0); - if (auth()->check()) { - $query->orWhere('users.id', auth()->user()->id) - ->orWhereIn('users.id', auth()->user()->follows()->select('follow_id')); - } + $query->where('users.private_profile', 0) + ->where('visibility', StatusVisibility::PUBLIC); + if (auth()->check()) { + $query->orWhere('users.id', auth()->user()->id) + ->orWhere(function($query) { + $query->where('visibility', StatusVisibility::FOLLOWERS) + ->whereIn('users.id', auth()->user()->follows()->select('follow_id')) + ->orWhere('visibility', StatusVisibility::PUBLIC); + }); + } }); if (auth()->check()) { diff --git a/app/Http/Controllers/TransportController.php b/app/Http/Controllers/TransportController.php index 377c8c58c..10485d8d7 100644 --- a/app/Http/Controllers/TransportController.php +++ b/app/Http/Controllers/TransportController.php @@ -294,6 +294,7 @@ public static function TrainCheckin($tripId, $businessCheck, $tweetCheck, $tootCheck, + $visibility, $eventId = 0, Carbon $departure = null, Carbon $arrival = null): array { @@ -367,9 +368,10 @@ public static function TrainCheckin($tripId, } $status = Status::create([ - 'user_id' => $user->id, - 'body' => $body, - 'business' => $businessCheck + 'user_id' => $user->id, + 'body' => $body, + 'business' => $businessCheck, + 'visibility' => $visibility ]); $plannedDeparture = Carbon::parse( diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index da163393f..7638db44e 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -2,10 +2,12 @@ namespace App\Http\Controllers; +use App\Enum\StatusVisibility; use App\Exceptions\AlreadyFollowingException; use App\Exceptions\PermissionException; use App\Models\Follow; use App\Models\FollowRequest; +use App\Models\Status; use App\Models\User; use App\Notifications\FollowRequestApproved; use App\Notifications\FollowRequestIssued; @@ -156,8 +158,16 @@ public static function statusesForUser(User $user): ?LengthAwarePaginator { 'user', 'likes', 'trainCheckin.Origin', 'trainCheckin.Destination', 'trainCheckin.HafasTrip.stopoversNEW', 'event' ]) - ->orderByDesc('created_at') - ->paginate(15); + ->where(function($query) { + $user = Auth::check() ? auth()->user() : null; + $query->whereIn('visibility', [StatusVisibility::PUBLIC, StatusVisibility::UNLISTED]) + ->orWhere('user_id', $user->id) + ->orWhere(function($query) { + $followings = Auth::check() ? auth()->user()->follows()->select('follow_id') : []; + $query->where('visibility', StatusVisibility::FOLLOWERS) + ->whereIn('user_id', $followings); + }); + })->orderByDesc('created_at')->paginate(15); } public static function getProfilePage($username): ?array { diff --git a/app/Models/Status.php b/app/Models/Status.php index e9ff47ba2..c3c12b5de 100644 --- a/app/Models/Status.php +++ b/app/Models/Status.php @@ -2,6 +2,7 @@ namespace App\Models; +use App\Enum\StatusVisibility; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; @@ -9,14 +10,20 @@ use Illuminate\Database\Eloquent\Relations\HasOne; use Illuminate\Support\Facades\Auth; +/** + * @property int user_id + * @property string body + * @property int business + * @property int visibility + */ class Status extends Model { use HasFactory; - protected $fillable = ['user_id', 'body', 'business', 'event_id']; + protected $fillable = ['user_id', 'body', 'business', 'event_id', 'visibility']; protected $hidden = ['user_id', 'business']; - protected $appends = ['favorited', 'socialText']; + protected $appends = ['favorited', 'socialText', 'statusInvisibleToMe']; public function user(): BelongsTo { return $this->belongsTo(User::class); @@ -83,4 +90,20 @@ public function getSocialTextAttribute(): string { return $postText; } + + /** + * When is a status invisible? + * 0=public, 1=unlisted, 2=Followers, 3=Private + * @return bool + */ + public function getStatusInvisibleToMeAttribute(): bool { + if (Auth::check() && Auth::id() == $this->user_id || $this->visibility == StatusVisibility::PUBLIC) { + return false; + } + $visible = false; + if ($this->visibility == StatusVisibility::FOLLOWERS) { + $visible = (Auth::check() && Auth::user()->follows->contains('id', $this->user_id)); + } + return !$visible; + } } diff --git a/database/migrations/2021_06_07_145349_add_visibility_to_statuses.php b/database/migrations/2021_06_07_145349_add_visibility_to_statuses.php new file mode 100644 index 000000000..ba729b270 --- /dev/null +++ b/database/migrations/2021_06_07_145349_add_visibility_to_statuses.php @@ -0,0 +1,22 @@ +unsignedTinyInteger('visibility') + ->default(0) + ->after('business'); + }); + } + + public function down(): void { + Schema::table('statuses', function(Blueprint $table) { + $table->dropColumn('visibility'); + }); + } +} diff --git a/database/seeders/TrainCheckinSeeder.php b/database/seeders/TrainCheckinSeeder.php index d2c77da2f..be26e5224 100644 --- a/database/seeders/TrainCheckinSeeder.php +++ b/database/seeders/TrainCheckinSeeder.php @@ -2,6 +2,7 @@ namespace Database\Seeders; +use App\Enum\StatusVisibility; use App\Exceptions\CheckInCollisionException; use App\Http\Controllers\TransportController; use App\Models\HafasTrip; @@ -28,6 +29,7 @@ public function run() { 0, 0, 0, + StatusVisibility::PUBLIC, rand(0, 1) ); } catch (CheckInCollisionException $e) { diff --git a/resources/js/components/business-check-in.js b/resources/js/components/business-check-in.js index b9b541b50..efa732fde 100644 --- a/resources/js/components/business-check-in.js +++ b/resources/js/components/business-check-in.js @@ -1,35 +1,46 @@ let statusBusiness; +let statusVisibility; let statusBody; -let statusId = 0; +let statusId = 0; +let statusBodyElement = $("#status-body"); -let businessCheckInput = $("#business_check"); -let dropDownButton = $("#businessDropdownButton"); -let dropDown = $("#businessDropdown"); -const businessIcons = ["fa-user", "fa-briefcase", "fa-building"]; +let businessCheckInput = $("#business_check"); +let businessButton = $("#businessDropdownButton"); +const businessIcons = ["fa-user", "fa-briefcase", "fa-building"]; +let visibilityFormInput = $("#checkinVisibility"); +let visibilityButton = $("#visibilityDropdownButton"); +const visibilityIcons = ["fa-globe-americas", "fa-lock-open", "fa-user-friends", "fa-lock"]; -function setIconsForCheckIn(value) { +function setIconForDropdown(value, button, inputFieldValue, icons) { let number = parseInt(value, 10); - let classes = dropDownButton.children()[0].classList; - businessIcons.forEach((value) => { + let classes = button.children()[0].classList; + icons.forEach((value) => { classes.remove(value); }); - classes.add(businessIcons[number]); - businessCheckInput.val(number); + classes.add(icons[number]); + inputFieldValue.val(number); } $(".trwl-business-item").on("click", function (event) { - setIconsForCheckIn(event.currentTarget.dataset.trwlBusiness); + setIconForDropdown(event.currentTarget.dataset.trwlBusiness, businessButton, businessCheckInput, businessIcons); +}); + +$(".trwl-visibility-item").on("click", function (event) { + setIconForDropdown(event.currentTarget.dataset.trwlVisibility, visibilityButton, visibilityFormInput, visibilityIcons); }); $(document).on("click", ".edit", function (event) { event.preventDefault(); - statusId = event.currentTarget.dataset.trwlStatusId; - statusBody = document.getElementById("status-" + statusId).dataset.trwlStatusBody; - statusBusiness = document.getElementById("status-" + statusId).dataset.trwlBusinessId; - $("#status-body").val(statusBody); - $("#business_check").val(statusBusiness); - setIconsForCheckIn(statusBusiness); + statusId = event.currentTarget.dataset.trwlStatusId; + statusBody = document.getElementById("status-" + statusId).dataset.trwlStatusBody; + statusBusiness = document.getElementById("status-" + statusId).dataset.trwlBusinessId; + statusVisibility = document.getElementById("status-" + statusId).dataset.trwlVisibility; + statusBodyElement.val(statusBody); + businessCheckInput.val(statusBusiness); + visibilityFormInput.val(statusVisibility); + setIconForDropdown(statusBusiness, businessButton, businessCheckInput, businessIcons); + setIconForDropdown(statusVisibility, visibilityButton, visibilityFormInput, visibilityIcons); $("#edit-modal").modal("show"); }); @@ -38,9 +49,10 @@ $(document).on("click", "#modal-trwl-edit-save", function () { method: "POST", url: urlEdit, data: { - body: $("#status-body").val(), + body: statusBodyElement.val(), statusId: statusId, - business_check: $("#business_check").val(), + business_check: businessCheckInput.val(), + checkinVisibility: visibilityFormInput.val(), _token: token } }).done(function (msg) { diff --git a/resources/lang/de.json b/resources/lang/de.json index 7ec6b3a84..74aaf8f37 100644 --- a/resources/lang/de.json +++ b/resources/lang/de.json @@ -369,6 +369,14 @@ "stationboard.business.commute.detail": "Weg zwischen Wohnort und Arbeitsplatz", "status.ogp-title": ":name's Reise mit Träwelling", "status.ogp-description": ":distancekm von :origin nach :destination in :linename.|:distancekm von :origin nach :destination in Linie :linename.", + "status.visibility.0": "Öffentlich", + "status.visibility.0.detail": "Sichtbar für alle, angezeigt im Dashboard, bei Events, etc.", + "status.visibility.1": "Ungelistet", + "status.visibility.1.detail": "Sichtbar für alle, nur im Profil aufrufbar", + "status.visibility.2": "Nur für Follower", + "status.visibility.2.detail": "Nur für (akzeptierte) Follower sichtbar", + "status.visibility.3": "Privat", + "status.visibility.3.detail": "Nur für dich sichtbar", "time-format": "HH:mm", "time-format.with-day": "HH:mm (DD.MM.YYYY)", "datetime-format": "DD.MM.YYYY HH:mm", diff --git a/resources/lang/en.json b/resources/lang/en.json index aaad9e1b8..808d4c0f3 100644 --- a/resources/lang/en.json +++ b/resources/lang/en.json @@ -356,6 +356,14 @@ "stationboard.business.commute.detail": "Between home and work place", "status.ogp-title": ":name's journey with Träwelling", "status.ogp-description": ":distancekm from :origin to :destination in :linename.|:distancekm from :origin to :destination in line :linename.", + "status.visibility.0": "Public", + "status.visibility.0.detail": "Visible for all, shown in dashboard, events, etc.", + "status.visibility.1": "Unlisted", + "status.visibility.1.detail": "Visible for all, only accessible in profile", + "status.visibility.2": "Followers-only", + "status.visibility.2.detail": "Only visible for (approved) followers", + "status.visibility.3": "Private", + "status.visibility.3.detail": "Only visible for you", "transport_types.bus": "bus", "transport_types.business": "Business Trip", "transport_types.businessPlural": "Business Trips", diff --git a/resources/sass/components/status.scss b/resources/sass/components/status.scss index 1c90e864c..465fffaad 100644 --- a/resources/sass/components/status.scss +++ b/resources/sass/components/status.scss @@ -52,4 +52,8 @@ .like-text { line-height: 2em; } + + .visibility-icon { + color: #b3b3b3 !important; + } } diff --git a/resources/views/includes/business-dropdown.blade.php b/resources/views/includes/business-dropdown.blade.php index 1a324988e..3890dbf92 100644 --- a/resources/views/includes/business-dropdown.blade.php +++ b/resources/views/includes/business-dropdown.blade.php @@ -1,24 +1,26 @@ - - - +
+ + + +
diff --git a/resources/views/includes/edit-modal.blade.php b/resources/views/includes/edit-modal.blade.php index 9fc29d90c..67844e3a4 100644 --- a/resources/views/includes/edit-modal.blade.php +++ b/resources/views/includes/edit-modal.blade.php @@ -14,12 +14,14 @@
@include('includes.business-dropdown') + @include('includes.visibility-dropdown')
diff --git a/resources/views/includes/status.blade.php b/resources/views/includes/status.blade.php index 2a47e93f1..5929b6458 100644 --- a/resources/views/includes/status.blade.php +++ b/resources/views/includes/status.blade.php @@ -1,6 +1,6 @@
@if (Route::current()->uri == "status/{id}") @if($status->trainCheckin->HafasTrip->polyline) @@ -118,6 +118,10 @@ class="progress-bar progress-time"