Add admin job list and manual exec to admin
This commit is contained in:
parent
3a4c475488
commit
fc04e2dace
|
@ -5,9 +5,9 @@ namespace App\Console;
|
||||||
use Illuminate\Console\Scheduling\Schedule;
|
use Illuminate\Console\Scheduling\Schedule;
|
||||||
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
|
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
|
||||||
|
|
||||||
use App\Jobs\NotifyUsersManualModeOn;
|
use App\Jobs\NotifyUsersManualModeOnJob;
|
||||||
use App\Jobs\RemoveOldIpAddressesFromLogs;
|
use App\Jobs\RemoveOldIpAddressesFromLogsJob;
|
||||||
use App\Jobs\ResetAvailabilityMinutes;
|
use App\Jobs\ResetAvailabilityMinutesJob;
|
||||||
use App\Jobs\UpdateAvailabilityWithSchedulesJob;
|
use App\Jobs\UpdateAvailabilityWithSchedulesJob;
|
||||||
|
|
||||||
class Kernel extends ConsoleKernel
|
class Kernel extends ConsoleKernel
|
||||||
|
@ -17,13 +17,13 @@ class Kernel extends ConsoleKernel
|
||||||
*/
|
*/
|
||||||
protected function schedule(Schedule $schedule): void
|
protected function schedule(Schedule $schedule): void
|
||||||
{
|
{
|
||||||
$schedule->job(new NotifyUsersManualModeOn)
|
$schedule->job(new NotifyUsersManualModeOnJob)
|
||||||
->dailyAt('7:00');
|
->dailyAt('7:00');
|
||||||
//->sentryMonitor();
|
//->sentryMonitor();
|
||||||
$schedule->job(new RemoveOldIpAddressesFromLogs)
|
$schedule->job(new RemoveOldIpAddressesFromLogsJob)
|
||||||
->dailyAt('0:30');
|
->dailyAt('0:30');
|
||||||
//->sentryMonitor();
|
//->sentryMonitor();
|
||||||
$schedule->job(new ResetAvailabilityMinutes)
|
$schedule->job(new ResetAvailabilityMinutesJob)
|
||||||
->monthlyOn(1, '0:00');
|
->monthlyOn(1, '0:00');
|
||||||
//->sentryMonitor();
|
//->sentryMonitor();
|
||||||
$schedule->job(new UpdateAvailabilityWithSchedulesJob)
|
$schedule->job(new UpdateAvailabilityWithSchedulesJob)
|
||||||
|
|
|
@ -94,6 +94,43 @@ class AdminController extends Controller
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getJobsList() {
|
||||||
|
if(!request()->user()->hasPermission("admin-maintenance-read")) abort(401);
|
||||||
|
|
||||||
|
$jobPath = app_path('Jobs');
|
||||||
|
$jobs = [];
|
||||||
|
|
||||||
|
$files = scandir($jobPath);
|
||||||
|
foreach ($files as $file) {
|
||||||
|
if (pathinfo($file, PATHINFO_EXTENSION) == 'php') {
|
||||||
|
$jobs[] = pathinfo($file, PATHINFO_FILENAME);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json($jobs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function runJob(Request $request) {
|
||||||
|
if(!request()->user()->hasPermission("admin-maintenance-update")) abort(401);
|
||||||
|
|
||||||
|
$request->validate([
|
||||||
|
'job' => 'required|string'
|
||||||
|
]);
|
||||||
|
|
||||||
|
Artisan::call('schedule:test', ['--name' => "App\\Jobs\\".$request->input('job')]);
|
||||||
|
$output = Artisan::output();
|
||||||
|
|
||||||
|
if(str_contains($output, 'No matching scheduled command found.')) {
|
||||||
|
return response()->json([
|
||||||
|
'message' => 'Job not found'
|
||||||
|
], 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'message' => 'Job ran successfully'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
public function getMaintenanceMode() {
|
public function getMaintenanceMode() {
|
||||||
if(!request()->user()->hasPermission("admin-maintenance-read")) abort(401);
|
if(!request()->user()->hasPermission("admin-maintenance-read")) abort(401);
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ use DefStudio\Telegraph\Keyboard\Button;
|
||||||
use DefStudio\Telegraph\Keyboard\Keyboard;
|
use DefStudio\Telegraph\Keyboard\Keyboard;
|
||||||
use DefStudio\Telegraph\Facades\Telegraph;
|
use DefStudio\Telegraph\Facades\Telegraph;
|
||||||
|
|
||||||
class NotifyUsersManualModeOn implements ShouldQueue
|
class NotifyUsersManualModeOnJob implements ShouldQueue
|
||||||
{
|
{
|
||||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||||
|
|
|
@ -10,7 +10,7 @@ use Illuminate\Queue\SerializesModels;
|
||||||
use App\Models\Log;
|
use App\Models\Log;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
|
|
||||||
class RemoveOldIpAddressesFromLogs implements ShouldQueue
|
class RemoveOldIpAddressesFromLogsJob implements ShouldQueue
|
||||||
{
|
{
|
||||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||||
|
|
|
@ -11,7 +11,7 @@ use Illuminate\Queue\SerializesModels;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use App\Models\AvailabilityMinutesArchive;
|
use App\Models\AvailabilityMinutesArchive;
|
||||||
|
|
||||||
class ResetAvailabilityMinutes implements ShouldQueue
|
class ResetAvailabilityMinutesJob implements ShouldQueue
|
||||||
{
|
{
|
||||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||||
|
|
|
@ -99,6 +99,9 @@ Route::middleware('auth:sanctum')->group( function () {
|
||||||
Route::post('/admin/runMigrations', [AdminController::class, 'runMigrations']);
|
Route::post('/admin/runMigrations', [AdminController::class, 'runMigrations']);
|
||||||
Route::post('/admin/runSeeding', [AdminController::class, 'runSeeding']);
|
Route::post('/admin/runSeeding', [AdminController::class, 'runSeeding']);
|
||||||
|
|
||||||
|
Route::get('/admin/jobs', [AdminController::class, 'getJobsList']);
|
||||||
|
Route::post('/admin/runJob', [AdminController::class, 'runJob']);
|
||||||
|
|
||||||
Route::get('/admin/maintenanceMode', [AdminController::class, 'getMaintenanceMode']);
|
Route::get('/admin/maintenanceMode', [AdminController::class, 'getMaintenanceMode']);
|
||||||
Route::post('/admin/maintenanceMode', [AdminController::class, 'updateMaintenanceMode']);
|
Route::post('/admin/maintenanceMode', [AdminController::class, 'updateMaintenanceMode']);
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-6 right-border">
|
<div class="col-md-6 right-border">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<h4>Database:</h4>
|
<h4>{{ 'admin.database'|translate|ftitlecase }}:</h4>
|
||||||
|
|
||||||
<div class="table-responsive ms-3 pe-5">
|
<div class="table-responsive ms-3 pe-5">
|
||||||
<table class="table table-striped table-bordered">
|
<table class="table table-striped table-bordered">
|
||||||
|
@ -66,8 +66,6 @@
|
||||||
<button type="button" class="btn btn-lg btn-danger" (click)="runSeeding()">{{ 'admin.run_seeding'|translate|ftitlecase }}</button>
|
<button type="button" class="btn btn-lg btn-danger" (click)="runSeeding()">{{ 'admin.run_seeding'|translate|ftitlecase }}</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
<div class="mb-2 ms-3 ps-5 pe-5" *ngIf="db && db.tables">
|
<div class="mb-2 ms-3 ps-5 pe-5" *ngIf="db && db.tables">
|
||||||
<button type="button" class="btn btn-primary" (click)="isTableListCollaped = !isTableListCollaped"
|
<button type="button" class="btn btn-primary" (click)="isTableListCollaped = !isTableListCollaped"
|
||||||
[attr.aria-expanded]="!isTableListCollaped" aria-controls="collapseBasic">
|
[attr.aria-expanded]="!isTableListCollaped" aria-controls="collapseBasic">
|
||||||
|
@ -94,6 +92,30 @@
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<hr>
|
||||||
|
<div class="row">
|
||||||
|
<h4>{{ 'admin.operations'|translate|ftitlecase }}:</h4>
|
||||||
|
|
||||||
|
<div class="table-responsive ms-3 pe-5">
|
||||||
|
<table class="table table-striped table-bordered">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>{{ 'name'|translate|ftitlecase }}</th>
|
||||||
|
<th>{{ 'admin.manual_execution'|translate|ftitlecase }}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr *ngFor="let job of jobs">
|
||||||
|
<td>{{ job }}</td>
|
||||||
|
<td (click)="runJob(job)" class="pointer text-center"
|
||||||
|
[ngClass]="{'text-bg-danger': ultraDangerousJobs.includes(job), 'text-bg-warning': dangerousJobs.includes(job)}">
|
||||||
|
<i class="fas fa-play"></i> {{ 'admin.run'|translate|ftitlecase }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|
|
@ -12,6 +12,10 @@
|
||||||
animation: blink 2s linear infinite;
|
animation: blink 2s linear infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.pointer {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
.right-border {
|
.right-border {
|
||||||
border-right: #0000004a 1px solid
|
border-right: #0000004a 1px solid
|
||||||
}
|
}
|
|
@ -12,6 +12,15 @@ export class AdminMaintenanceComponent implements OnInit {
|
||||||
public db: any | undefined = undefined;
|
public db: any | undefined = undefined;
|
||||||
public isTableListCollaped = true;
|
public isTableListCollaped = true;
|
||||||
|
|
||||||
|
public jobs: string[] = [];
|
||||||
|
//Hard-coded list of jobs that should not be run manually
|
||||||
|
public dangerousJobs: string[] = [
|
||||||
|
"NotifyUsersManualModeOnJob"
|
||||||
|
];
|
||||||
|
public ultraDangerousJobs: string[] = [
|
||||||
|
"ResetAvailabilityMinutesJob"
|
||||||
|
];
|
||||||
|
|
||||||
public isMaintenanceModeActive = false;
|
public isMaintenanceModeActive = false;
|
||||||
|
|
||||||
public telegramBotInfo: any | undefined = undefined;
|
public telegramBotInfo: any | undefined = undefined;
|
||||||
|
@ -40,6 +49,19 @@ export class AdminMaintenanceComponent implements OnInit {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getJobs() {
|
||||||
|
this.api.get('admin/jobs').then((res: any) => {
|
||||||
|
this.jobs = res;
|
||||||
|
console.log(this.jobs);
|
||||||
|
}).catch((err: any) => {
|
||||||
|
Swal.fire({
|
||||||
|
icon: 'error',
|
||||||
|
title: this.translateService.instant('error_title'),
|
||||||
|
text: err.message
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
getMaintenanceMode() {
|
getMaintenanceMode() {
|
||||||
this.api.get('admin/maintenanceMode').then((res: any) => {
|
this.api.get('admin/maintenanceMode').then((res: any) => {
|
||||||
this.isMaintenanceModeActive = res.enabled;
|
this.isMaintenanceModeActive = res.enabled;
|
||||||
|
@ -68,6 +90,7 @@ export class AdminMaintenanceComponent implements OnInit {
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.getDB();
|
this.getDB();
|
||||||
|
this.getJobs();
|
||||||
this.getMaintenanceMode();
|
this.getMaintenanceMode();
|
||||||
this.getTelegramBotDebugInfo();
|
this.getTelegramBotDebugInfo();
|
||||||
}
|
}
|
||||||
|
@ -118,6 +141,35 @@ export class AdminMaintenanceComponent implements OnInit {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
runJob(job: string) {
|
||||||
|
//Require confirmation before proceeding
|
||||||
|
Swal.fire({
|
||||||
|
title: this.translateService.instant('admin.run_confirm_title'),
|
||||||
|
text: this.translateService.instant('admin.run_confirm_text'),
|
||||||
|
icon: 'warning',
|
||||||
|
showCancelButton: true,
|
||||||
|
confirmButtonText: this.translateService.instant('yes'),
|
||||||
|
cancelButtonText: this.translateService.instant('no')
|
||||||
|
}).then((result) => {
|
||||||
|
if (result.isConfirmed) {
|
||||||
|
this.api.post('admin/runJob', { job }).then((res: any) => {
|
||||||
|
Swal.fire({
|
||||||
|
icon: 'success',
|
||||||
|
title: this.translateService.instant('success_title'),
|
||||||
|
text: this.translateService.instant('admin.run_success')
|
||||||
|
});
|
||||||
|
this.getJobs();
|
||||||
|
}).catch((err: any) => {
|
||||||
|
Swal.fire({
|
||||||
|
icon: 'error',
|
||||||
|
title: this.translateService.instant('error_title'),
|
||||||
|
text: err.error.message
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
updateMaintenanceMode(enabled: boolean) {
|
updateMaintenanceMode(enabled: boolean) {
|
||||||
this.api.post('admin/maintenanceMode', { enabled }).then((res: any) => {
|
this.api.post('admin/maintenanceMode', { enabled }).then((res: any) => {
|
||||||
this.isMaintenanceModeActive = enabled;
|
this.isMaintenanceModeActive = enabled;
|
||||||
|
|
|
@ -46,7 +46,12 @@
|
||||||
"telegram_webhook_set": "Set Telegram Webhook",
|
"telegram_webhook_set": "Set Telegram Webhook",
|
||||||
"telegram_webhook_set_success": "Telegram Webhook set successfully",
|
"telegram_webhook_set_success": "Telegram Webhook set successfully",
|
||||||
"telegram_webhook_unset": "Unset Telegram Webhook",
|
"telegram_webhook_unset": "Unset Telegram Webhook",
|
||||||
"telegram_webhook_unset_success": "Telegram Webhook unset successfully"
|
"telegram_webhook_unset_success": "Telegram Webhook unset successfully",
|
||||||
|
"manual_execution": "manual execution",
|
||||||
|
"run": "run",
|
||||||
|
"run_confirm_title": "Are you sure you want to run this command?",
|
||||||
|
"run_confirm_text": "This action cannot be undone.",
|
||||||
|
"run_success": "Command executed successfully"
|
||||||
},
|
},
|
||||||
"table": {
|
"table": {
|
||||||
"yes_remove": "Yes, remove",
|
"yes_remove": "Yes, remove",
|
||||||
|
|
|
@ -46,7 +46,12 @@
|
||||||
"telegram_webhook_set": "Imposta Webhook Telegram",
|
"telegram_webhook_set": "Imposta Webhook Telegram",
|
||||||
"telegram_webhook_set_success": "Webhook Telegram impostato con successo",
|
"telegram_webhook_set_success": "Webhook Telegram impostato con successo",
|
||||||
"telegram_webhook_unset": "Rimuovi Webhook Telegram",
|
"telegram_webhook_unset": "Rimuovi Webhook Telegram",
|
||||||
"telegram_webhook_unset_success": "Webhook Telegram rimosso con successo"
|
"telegram_webhook_unset_success": "Webhook Telegram rimosso con successo",
|
||||||
|
"manual_execution": "esecuzione manuale",
|
||||||
|
"run": "esegui",
|
||||||
|
"run_confirm_title": "Sei sicuro di voler eseguire questo comando?",
|
||||||
|
"run_confirm_text": "Questa operazione non potrà essere annullata.",
|
||||||
|
"run_success": "Comando eseguito con successo"
|
||||||
},
|
},
|
||||||
"table": {
|
"table": {
|
||||||
"yes_remove": "Si, rimuovi",
|
"yes_remove": "Si, rimuovi",
|
||||||
|
|
Loading…
Reference in New Issue