Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#270 - refresh indicator #410

Merged
merged 8 commits into from
Mar 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,6 @@ SANCTUM_STATEFUL_DOMAINS=toby.blumilk.localhost

SOPS_AGE_BETA_SECRET_KEY=
SOPS_AGE_PROD_SECRET_KEY=

# 5 minutes (in miliseconds)
VITE_LAST_UPDATE_TIMEOUT=300000
2 changes: 2 additions & 0 deletions app/Architecture/Providers/EventServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use Toby\Domain\Events\VacationRequestChanged;
use Toby\Domain\Listeners\UpdateDailySummaries;
use Toby\Domain\Listeners\UpdateLastUpdateCache;

class EventServiceProvider extends ServiceProvider
{
protected $listen = [
VacationRequestChanged::class => [
UpdateDailySummaries::class,
UpdateLastUpdateCache::class,
],
];
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ protected function notifyAuthorizedUsers(VacationRequest $vacationRequest): void
{
$users = Permission::findByName("receiveVacationRequestWaitsForApprovalNotification")
->users()
->with("permissions")
->get();

$users = $users->filter(fn(User $user): bool => $user->can("acceptAsAdminApprover", $vacationRequest));
Expand Down
21 changes: 21 additions & 0 deletions app/Domain/Listeners/UpdateLastUpdateCache.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

declare(strict_types=1);

namespace Toby\Domain\Listeners;

use Carbon\Carbon;
use Illuminate\Cache\CacheManager;
use Toby\Domain\Events\VacationRequestChanged;

class UpdateLastUpdateCache
{
public function __construct(
protected CacheManager $cacheManager,
) {}

public function handle(VacationRequestChanged $event): void
{
$this->cacheManager->set("last_update", Carbon::now()->toIso8601String());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

declare(strict_types=1);

namespace Toby\Infrastructure\Http\Controllers\Api;

use Carbon\Carbon;
use Illuminate\Cache\CacheManager;
use Symfony\Component\HttpFoundation\JsonResponse;

class LastUpdateController
{
public function __invoke(CacheManager $cache): JsonResponse
{
return new JsonResponse([
"lastUpdate" => $cache->get("last_update", Carbon::now()->toIso8601String()),
]);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@

namespace Toby\Infrastructure\Http\Middleware;

use Carbon\Carbon;
use Closure;
use Illuminate\Cache\CacheManager;
use Illuminate\Http\Request;
use Inertia\Middleware;
use Spatie\Permission\Models\Permission;
Expand All @@ -17,6 +19,7 @@ class HandleInertiaRequests extends Middleware
{
public function __construct(
protected YearPeriodRetriever $yearPeriodRetriever,
protected CacheManager $cache,
) {}

public function share(Request $request): array
Expand All @@ -27,6 +30,7 @@ public function share(Request $request): array
"years" => $this->getYearsData($request),
"vacationRequestsCount" => $this->getVacationRequestsCount($request),
"deployInformation" => $this->getDeployInformation(),
"lastUpdate" => $this->cache->rememberForever("last_update", fn(): string => Carbon::now()->toIso8601String()),
]);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public function toArray($request): array
return [
"id" => $this->id,
"name" => $this->name,
"user" => new SimpleUserResource($user),
"user" => new SimpleUserResource($this->user),
"type" => $this->type,
"isVacation" => $this->configRetriever->isVacation($this->type),
"state" => $this->state,
Expand Down
2 changes: 0 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
version: "3.8"

services:
app:
build:
Expand Down
1 change: 1 addition & 0 deletions environment/prod/app/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ FROM node:21.6.2-bullseye-slim as frontend
WORKDIR /app_frontend_dependencies

COPY package.json package-lock.json postcss.config.js tailwind.config.js vite.config.js ./
COPY ./environment/prod/app/vite.env .env

RUN npm clean-install

Expand Down
1 change: 1 addition & 0 deletions environment/prod/app/vite.env
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
VITE_LAST_UPDATE_TIMEOUT=300000
Binary file added public/images/icon-alert.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
28 changes: 28 additions & 0 deletions resources/js/Shared/LastUpdate.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<script setup>
import { onMounted } from 'vue'
import axios from 'axios'
import { updateFavicon } from '@/Shared/updateFavicon'

const props = defineProps({
lastUpdate: String,
})

const emit = defineEmits(['lastUpdateUpdated'])

const fetchLastUpdate = async () => {
try {
const response = await axios.get('/api/last-update')
if (response.data.lastUpdate !== props.lastUpdate) {
emit('lastUpdateUpdated')
updateFavicon('/images/icon-alert.png')
}
} catch (error) {
console.error('Failed to fetch last update.')
}
}

onMounted(() => {
fetchLastUpdate()
setInterval(fetchLastUpdate, import.meta.env.VITE_LAST_UPDATE_TIMEOUT)
})
</script>
22 changes: 20 additions & 2 deletions resources/js/Shared/Layout/AppLayout.vue
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
<script setup>
import MainMenu from '@/Shared/MainMenu.vue'
import LastUpdate from '@/Shared/LastUpdate.vue'
import { useToast } from 'vue-toastification'
import { watch } from 'vue'
import { ref, watch } from 'vue'
import DeployInfo from '@/Shared/DeployInfo.vue'
import { updateFavicon } from '@/Shared/updateFavicon'

const props = defineProps({
flash: Object,
auth: Object,
years: Object,
vacationRequestsCount: Number,
deployInformation: Object,
lastUpdate: String,
})

const toast = useToast()
Expand All @@ -27,14 +30,29 @@ watch(() => props.flash, flash => {
toast.error(flash.error)
}
}, { immediate: true })

const isUpdated = ref(false)

function vacationPageOpened() {
isUpdated.value = false
updateFavicon('/images/icon.png')
}
</script>

<template>
<LastUpdate
v-if="props.auth.can.listAllRequests"
:is-updated="isUpdated"
:last-update="lastUpdate"
@last-update-updated="isUpdated = true"
/>
<div class="relative min-h-screen">
<MainMenu
:auth="auth"
:years="years"
:show-refresh-button="isUpdated"
:vacation-requests-count="vacationRequestsCount"
:years="years"
@open="vacationPageOpened"
/>
<main class="flex flex-col flex-1 py-8 lg:ml-60">
<div class="lg:px-4">
Expand Down
Loading
Loading