From 6589f9e0f44105f5907d4d77d0eba9b8377f6d30 Mon Sep 17 00:00:00 2001 From: Louis Jeckel Date: Thu, 30 Apr 2020 02:36:33 +0200 Subject: [PATCH] added nova metrics --- app/Nova/Actions/SendNotification.php | 55 +++++++++++++++ app/Nova/Actions/StartTrial.php | 53 +++++++++++++++ app/Nova/Actions/VerifyEmail.php | 40 +++++++++++ app/Nova/Metrics/FileAccess.php | 63 ++++++++++++++++++ app/Nova/Metrics/MailEvents.php | 78 ++++++++++++++++++++++ app/Nova/Metrics/MailEventsPartition.php | 41 ++++++++++++ app/Nova/Metrics/TotalUsers.php | 44 ++++++++++++ app/Nova/Metrics/UsersPartition.php | 48 +++++++++++++ app/Nova/User.php | 24 ++++++- app/Providers/NovaServiceProvider.php | 11 +++ app/User.php | 85 ++++++++++++++++++++---- 11 files changed, 525 insertions(+), 17 deletions(-) create mode 100644 app/Nova/Actions/SendNotification.php create mode 100644 app/Nova/Actions/StartTrial.php create mode 100644 app/Nova/Actions/VerifyEmail.php create mode 100644 app/Nova/Metrics/FileAccess.php create mode 100644 app/Nova/Metrics/MailEvents.php create mode 100644 app/Nova/Metrics/MailEventsPartition.php create mode 100644 app/Nova/Metrics/TotalUsers.php create mode 100644 app/Nova/Metrics/UsersPartition.php diff --git a/app/Nova/Actions/SendNotification.php b/app/Nova/Actions/SendNotification.php new file mode 100644 index 0000000..404616d --- /dev/null +++ b/app/Nova/Actions/SendNotification.php @@ -0,0 +1,55 @@ +map(fn(User $user) => $user->notify(new $fields->notification)); + return Action::message(sprintf('%d messages envoyés', $models->count())); + } + + /** + * Get the fields available on the action. + * + * @return array + */ + public function fields() + { + return [ + Select::make('Notification')->options([ + Notifications\Welcome::class => 'Message de bienvenue', + Notifications\RegistrationPending::class => 'Rappel', + ]) + ]; + } +} diff --git a/app/Nova/Actions/StartTrial.php b/app/Nova/Actions/StartTrial.php new file mode 100644 index 0000000..97f5c62 --- /dev/null +++ b/app/Nova/Actions/StartTrial.php @@ -0,0 +1,53 @@ +confirmText = sprintf("Etes vous sûr de vouloir activer une période d'essai de %d jours ?", User::trialDurationDays); + + } + + + + + /** + * Perform the action on the given models. + * + * @param \Laravel\Nova\Fields\ActionFields $fields + * @param \Illuminate\Support\Collection $models + * @return mixed + */ + public function handle(ActionFields $fields, Collection $models) + { + $models->map->startTrial(); + + return Action::message(sprintf("La période d'essai à bien été activée pour %d utilisteur(s)", $models->count())); + } + + /** + * Get the fields available on the action. + * + * @return array + */ + public function fields() + { + return []; + } +} diff --git a/app/Nova/Actions/VerifyEmail.php b/app/Nova/Actions/VerifyEmail.php new file mode 100644 index 0000000..894c13a --- /dev/null +++ b/app/Nova/Actions/VerifyEmail.php @@ -0,0 +1,40 @@ +map->markEmailAsVerified(); + } + + /** + * Get the fields available on the action. + * + * @return array + */ + public function fields() + { + return []; + } +} diff --git a/app/Nova/Metrics/FileAccess.php b/app/Nova/Metrics/FileAccess.php new file mode 100644 index 0000000..8486a40 --- /dev/null +++ b/app/Nova/Metrics/FileAccess.php @@ -0,0 +1,63 @@ +count($request, AccessLog::class); + } + + /** + * Get the ranges available for the metric. + * + * @return array + */ + public function ranges() + { + return [ + 30 => '30 jours', + 'TODAY' => 'Today', + 7 => '7 jours', + 60 => '60 jours', + 365 => '365 jours', + 'MTD' => 'Month To Date', + 'QTD' => 'Quarter To Date', + 'YTD' => 'Year To Date', + ]; + } + + /** + * Determine for how many minutes the metric should be cached. + * + * @return \DateTimeInterface|\DateInterval|float|int + */ + public function cacheFor() + { + // return now()->addMinutes(5); + } + + /** + * Get the URI key for the metric. + * + * @return string + */ + public function uriKey() + { + return 'file-access'; + } +} diff --git a/app/Nova/Metrics/MailEvents.php b/app/Nova/Metrics/MailEvents.php new file mode 100644 index 0000000..f655936 --- /dev/null +++ b/app/Nova/Metrics/MailEvents.php @@ -0,0 +1,78 @@ +event = $event; + $this->name = $name; + } + + /** + * Calculate the value of the metric. + * + * @param \Laravel\Nova\Http\Requests\NovaRequest $request + * @return mixed + */ + public function calculate(NovaRequest $request) + { + return $this->count($request, MailgunEvent::where('event', $this->event)); + } + + /** + * Get the ranges available for the metric. + * + * @return array + */ + public function ranges() + { + return [ + 30 => '30 Days', + 60 => '60 Days', + 365 => '365 Days', + 'TODAY' => 'Today', + 'MTD' => 'Month To Date', + 'QTD' => 'Quarter To Date', + 'YTD' => 'Year To Date', + ]; + } + + /** + * Determine for how many minutes the metric should be cached. + * + * @return \DateTimeInterface|\DateInterval|float|int + */ + public function cacheFor() + { + // return now()->addMinutes(5); + } + + /** + * Get the URI key for the metric. + * + * @return string + */ + public function uriKey() + { + return 'mail-events'; + } +} diff --git a/app/Nova/Metrics/MailEventsPartition.php b/app/Nova/Metrics/MailEventsPartition.php new file mode 100644 index 0000000..482b238 --- /dev/null +++ b/app/Nova/Metrics/MailEventsPartition.php @@ -0,0 +1,41 @@ +count($request, MailgunEvent::class, 'event'); + } + + /** + * Determine for how many minutes the metric should be cached. + * + * @return \DateTimeInterface|\DateInterval|float|int + */ + public function cacheFor() + { + // return now()->addMinutes(5); + } + + /** + * Get the URI key for the metric. + * + * @return string + */ + public function uriKey() + { + return 'mail-events-partition'; + } +} diff --git a/app/Nova/Metrics/TotalUsers.php b/app/Nova/Metrics/TotalUsers.php new file mode 100644 index 0000000..7b781c7 --- /dev/null +++ b/app/Nova/Metrics/TotalUsers.php @@ -0,0 +1,44 @@ +result(User::count()); + } + + + /** + * Determine for how many minutes the metric should be cached. + * + * @return \DateTimeInterface|\DateInterval|float|int + */ + public function cacheFor() + { +// return now()->addMinutes(5); + } + + /** + * Get the URI key for the metric. + * + * @return string + */ + public function uriKey() + { + return 'total-users'; + } +} diff --git a/app/Nova/Metrics/UsersPartition.php b/app/Nova/Metrics/UsersPartition.php new file mode 100644 index 0000000..105daa5 --- /dev/null +++ b/app/Nova/Metrics/UsersPartition.php @@ -0,0 +1,48 @@ +result([ + 'Abonnés' => $s = User::hasActiveSubscription()->count(), + "Période d'essai" => $t = User::isOnTrial()->count(), + "Reste" => User::count() - $s - $t + ]); + } + + /** + * Determine for how many minutes the metric should be cached. + * + * @return \DateTimeInterface|\DateInterval|float|int + */ + public function cacheFor() + { + // return now()->addMinutes(5); + } + + /** + * Get the URI key for the metric. + * + * @return string + */ + public function uriKey() + { + return 'users-partition'; + } +} diff --git a/app/Nova/User.php b/app/Nova/User.php index fed3cb1..28cf721 100644 --- a/app/Nova/User.php +++ b/app/Nova/User.php @@ -3,7 +3,17 @@ namespace App\Nova; use App\Nova\Actions\ImportUsers; +use App\Nova\Actions\SendNotification; +use App\Nova\Actions\StartTrial; +use App\Nova\Actions\VerifyEmail; +use App\Nova\Metrics\SubscribedUsers; +use App\Nova\Metrics\TotalUsers; +use App\Nova\Metrics\TrialUsers; +use App\Nova\Metrics\UsersPartition; +use App\User as AppUser; use Illuminate\Http\Request; +use Illuminate\Support\Arr; +use Laravel\Nova\Fields\Badge; use Laravel\Nova\Fields\BelongsTo; use Laravel\Nova\Fields\Boolean; use Laravel\Nova\Fields\Country; @@ -20,7 +30,7 @@ class User extends Resource * * @var string */ - public static $model = \App\User::class; + public static $model = AppUser::class; /** @@ -56,7 +66,9 @@ class User extends Resource BelongsTo::make('Organisation', 'organization', Organization::class)->searchable(), ]), - Boolean::make('Abonnement actif', 'isSubscribed')->readonly()->onlyOnIndex(), + Boolean::make('Compte actif', 'reg_complete'), + Badge::make('Etat', fn() => AppUser::statuses[$this->status]['label']) + ->map(Arr::pluck(AppUser::statuses, 'badge', 'label')), ]; } @@ -86,7 +98,10 @@ class User extends Resource */ public function cards(Request $request) { - return []; + return [ + new TotalUsers, + new UsersPartition, + ]; } /** @@ -121,6 +136,9 @@ class User extends Resource { return [ new ImportUsers, + new SendNotification, + new StartTrial, + new VerifyEmail, ]; } } diff --git a/app/Providers/NovaServiceProvider.php b/app/Providers/NovaServiceProvider.php index 05d973d..3b30524 100644 --- a/app/Providers/NovaServiceProvider.php +++ b/app/Providers/NovaServiceProvider.php @@ -4,6 +4,11 @@ namespace App\Providers; use A17\Twill\Models\User as TwillUser; use Anaseqal\NovaImport\NovaImport; +use App\Nova\Metrics\FileAccess; +use App\Nova\Metrics\MailEvents; +use App\Nova\Metrics\MailEventsPartition; +use App\Nova\Metrics\TotalUsers; +use App\Nova\Metrics\UsersPartition; use Illuminate\Support\Facades\Gate; use Laravel\Nova\Cards\Help; use Laravel\Nova\Nova; @@ -57,6 +62,12 @@ class NovaServiceProvider extends NovaApplicationServiceProvider protected function cards() { return [ + new TotalUsers, + new UsersPartition, + new FileAccess, + new MailEvents('opened', 'Mails ouverts'), + new MailEventsPartition, + ]; } diff --git a/app/User.php b/app/User.php index 9b9b420..cc895f7 100644 --- a/app/User.php +++ b/app/User.php @@ -3,6 +3,7 @@ namespace App; +use DemeterChain\B; use Illuminate\Contracts\Auth\MustVerifyEmail; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Relations\BelongsTo; @@ -68,7 +69,7 @@ class User extends Authenticatable 'email_verified_at' => 'datetime', 'subscription_active' => 'bool', 'reg_complete' => 'bool', - 'trial_until' => 'datetime', + 'trial_ends_at' => 'datetime', 'active_until' => 'datetime', ]; @@ -83,7 +84,7 @@ class User extends Authenticatable ]; } - public int $trialDurationDays = 14; + public const trialDurationDays = 14; /** * @return BelongsTo @@ -98,11 +99,52 @@ class User extends Authenticatable */ public function getIsSubscribedAttribute(): bool { - if($o = $this->organization){ - return $o->isSubscribed(); - } + return ($o = $this->organization) === null ? + false: + $o->isSubscribed(); + } + + /** + * Possible Statuses + */ + public const statuses = [ + 'inactive' => [ + 'badge' => 'danger', + 'label' => 'Aucun abonnement' + ], + 'subscribed' => [ + 'badge' => 'success', + 'label' => 'Abonnement actif (orga)' + ], + 'trial' => [ + 'badge' => 'warning', + 'label' => "Période d'essai" + ], + ]; + + /** + * @return string + */ + public function getStatusAttribute(): string + { + $id = 'inactive'; + + if($this->isSubscribed) + $id = 'subscribed'; + if($this->onTrial()) + $id = 'trial'; + + return $id; + + } - return false; + /** + * @return string + * Returns current status + */ + public function getStatusLabelAttribute(): string + { + return self::statuses[$this->status]['label']; } /** @@ -126,23 +168,38 @@ class User extends Authenticatable return route($route, array_merge($params, $token), $absolute); } + /** - * @param Builder $builder + * Starts trial period */ + public function startTrial(): void + { + $this->trial_ends_at = now()->addDays(self::trialDurationDays); + $this->save(); + } + + + + + + public function scopeRecievesEmails(Builder $builder): void { - $builder->whereHas('organization', fn($builder) => $builder->subscribed()) - ->orWhereDate('trial_ends_at', '>', now()); + $builder->hasActiveSubscription()->orWhere->isOnTrial(); } - /** - * Starts trial period - */ - public function startTrial(): void + public function scopeIsOnTrial(Builder $builder): void { - $this->trial_ends_at = now()->addDays($this->trialDurationDays); + $builder->whereDate('trial_ends_at', '>', now()); } + public function scopeHasActiveSubscription(Builder $builder): void + { + $builder->whereHas('organization', fn($builder) => $builder->subscribed()); + } + + + /** -- 2.39.5