diff --git a/app/Livewire/Project/Shared/ScheduledTask/Add.php b/app/Livewire/Project/Shared/ScheduledTask/Add.php new file mode 100644 index 000000000..84f790ad4 --- /dev/null +++ b/app/Livewire/Project/Shared/ScheduledTask/Add.php @@ -0,0 +1,59 @@ + 'clear']; + protected $rules = [ + 'name' => 'required|string', + 'command' => 'required|string', + 'frequency' => 'required|string', + 'container' => 'nullable|string', + ]; + protected $validationAttributes = [ + 'name' => 'name', + 'command' => 'command', + 'frequency' => 'frequency', + 'container' => 'container', + ]; + + public function mount() + { + $this->parameters = get_route_parameters(); + } + + public function submit() + { + error_log("*** IN SUBMIT"); + $this->validate(); + $isValid = validate_cron_expression($this->frequency); + if (!$isValid) { + $this->dispatch('error', 'Invalid Cron / Human expression.'); + return; + } + $this->dispatch('saveScheduledTask', [ + 'name' => $this->name, + 'command' => $this->command, + 'frequency' => $this->frequency, + 'container' => $this->container, + ]); + $this->clear(); + } + + public function clear() + { + $this->name = ''; + $this->command = ''; + $this->frequency = ''; + $this->container = ''; + } +} diff --git a/app/Livewire/Project/Shared/ScheduledTask/All.php b/app/Livewire/Project/Shared/ScheduledTask/All.php new file mode 100644 index 000000000..1562a4cae --- /dev/null +++ b/app/Livewire/Project/Shared/ScheduledTask/All.php @@ -0,0 +1,134 @@ + 'submit']; + + public function mount() + { + $resourceClass = get_class($this->resource); + $resourceWithPreviews = ['App\Models\Application']; + $simpleDockerfile = !is_null(data_get($this->resource, 'dockerfile')); + if (Str::of($resourceClass)->contains($resourceWithPreviews) && !$simpleDockerfile) { + $this->showPreview = true; + } + $this->modalId = new Cuid2(7); + $this->getDevView(); + } + public function getDevView() + { + $this->variables = $this->resource->scheduled_tasks->map(function ($item) { + error_log("** got one"); + return "$item->name=$item->command"; + })->sort(); + + error_log(print_r($this->variables,1)); + } + public function saveVariables($isPreview) + { + if ($isPreview) { + $variables = parseEnvFormatToArray($this->variablesPreview); + $this->resource->environment_variables_preview()->whereNotIn('key', array_keys($variables))->delete(); + } else { + $variables = parseEnvFormatToArray($this->variables); + $this->resource->environment_variables()->whereNotIn('key', array_keys($variables))->delete(); + } + foreach ($variables as $key => $variable) { + if ($isPreview) { + $found = $this->resource->environment_variables_preview()->where('key', $key)->first(); + } else { + $found = $this->resource->environment_variables()->where('key', $key)->first(); + } + if ($found) { + if ($found->is_shown_once) { + continue; + } + $found->value = $variable; + $found->save(); + continue; + } else { + $task = new ScheduledTask(); + $task->key = $key; + $task->value = $variable; + $task->is_build_time = false; + $task->is_preview = $isPreview ? true : false; + switch ($this->resource->type()) { + case 'application': + $task->application_id = $this->resource->id; + break; + case 'standalone-postgresql': + $task->standalone_postgresql_id = $this->resource->id; + break; + case 'standalone-redis': + $task->standalone_redis_id = $this->resource->id; + break; + case 'standalone-mongodb': + $task->standalone_mongodb_id = $this->resource->id; + break; + case 'standalone-mysql': + $task->standalone_mysql_id = $this->resource->id; + break; + case 'standalone-mariadb': + $task->standalone_mariadb_id = $this->resource->id; + break; + case 'service': + $task->service_id = $this->resource->id; + break; + } + $task->save(); + } + } + if ($isPreview) { + $this->dispatch('success', 'Preview environment variables updated successfully.'); + } else { + $this->dispatch('success', 'Environment variables updated successfully.'); + } + $this->refreshTasks(); + } + public function refreshTasks() + { + $this->resource->refresh(); + $this->getDevView(); + } + + public function submit($data) + { + error_log("** submitting the beast"); + try { + $task = new ScheduledTask(); + $task->name = $data['name']; + $task->command = $data['command']; + $task->frequency = $data['frequency']; + $task->container = $data['container']; + + switch ($this->resource->type()) { + case 'application': + $task->application_id = $this->resource->id; + break; + case 'standalone-postgresql': + $task->standalone_postgresql_id = $this->resource->id; + break; + case 'service': + $task->service_id = $this->resource->id; + break; + } + $task->save(); + $this->refreshTasks(); + $this->dispatch('success', 'Scheduled task added successfully.'); + } catch (\Throwable $e) { + return handleError($e, $this); + } + } +} diff --git a/app/Livewire/Project/Shared/ScheduledTask/Show.php b/app/Livewire/Project/Shared/ScheduledTask/Show.php new file mode 100644 index 000000000..b65c36531 --- /dev/null +++ b/app/Livewire/Project/Shared/ScheduledTask/Show.php @@ -0,0 +1,60 @@ + 'required|string', + 'task.command' => 'required|string', + ]; + protected $validationAttributes = [ + 'name' => 'Name', + 'command' => 'Command', + ]; + + public function mount() + { + $this->modalId = new Cuid2(7); + $this->parameters = get_route_parameters(); + } + + public function lock() + { + $this->task->is_shown_once = true; + $this->task->save(); + $this->dispatch('refreshTasks'); + } + public function instantSave() + { + $this->submit(); + } + public function submit() + { + $this->validate(); + $this->task->save(); + $this->dispatch('success', 'Environment variable updated successfully.'); + $this->dispatch('refreshTasks'); + } + + public function delete() + { + try { + $this->task->delete(); + $this->dispatch('refreshTasks'); + } catch (\Exception $e) { + return handleError($e); + } + } +} diff --git a/app/Models/Application.php b/app/Models/Application.php index 018d6ec91..fc1b7d500 100644 --- a/app/Models/Application.php +++ b/app/Models/Application.php @@ -315,6 +315,11 @@ class Application extends BaseModel return $this->hasMany(EnvironmentVariable::class)->where('is_preview', true)->where('key', 'like', 'NIXPACKS_%'); } + public function scheduled_tasks(): HasMany + { + return $this->hasMany(ScheduledTask::class)->orderBy('name', 'asc'); + } + public function private_key() { return $this->belongsTo(PrivateKey::class); diff --git a/app/Models/ScheduledTask.php b/app/Models/ScheduledTask.php new file mode 100644 index 000000000..79468dd2a --- /dev/null +++ b/app/Models/ScheduledTask.php @@ -0,0 +1,88 @@ + 'string', + 'command' => 'string', + 'frequency' => 'string', + 'container' => 'string', + ]; + + // protected static function booted() + // { + // static::created(function ($scheduled_task) { + // error_log("*** IN CREATED"); + // if ($scheduled_task->application_id) { + // $found = ModelsScheduledTask::where('id', $scheduled_task->id)->where('application_id', $scheduled_task->application_id)->first(); + // $application = Application::find($scheduled_task->application_id); + // if (!$found) { + // ModelsScheduledTask::create([ + // 'name' => $scheduled_task->name, + // 'command' => $scheduled_task->command, + // 'frequency' => $scheduled_task->frequency, + // 'container' => $scheduled_task->container, + // 'application_id' => $scheduled_task->application_id, + // ]); + // } + // } + // }); + // } + public function service() + { + return $this->belongsTo(Service::class); + } + // protected function value(): Attribute + // { + // return Attribute::make( + // get: fn (?string $value = null) => $this->get_scheduled_tasks($value), + // set: fn (?string $value = null) => $this->set_scheduled_tasks($value), + // ); + // } + + private function get_scheduled_tasks(?string $scheduled_task = null): string|null + { + error_log("** in get_scheduled_tasks"); + // // $team_id = currentTeam()->id; + // if (!$scheduled_task) { + // return null; + // } + // $scheduled_task = trim(decrypt($scheduled_task)); + // if (Str::startsWith($scheduled_task, '{{') && Str::endsWith($scheduled_task, '}}') && Str::contains($scheduled_task, 'global.')) { + // $variable = Str::after($scheduled_task, 'global.'); + // $variable = Str::before($variable, '}}'); + // $variable = Str::of($variable)->trim()->value; + // // $scheduled_task = GlobalScheduledTask::where('name', $scheduled_task)->where('team_id', $team_id)->first()?->value; + // ray('global env variable'); + // return $scheduled_task; + // } + // return $scheduled_task; + } + + private function set_scheduled_tasks(?string $scheduled_task = null): string|null + { + error_log("** in set_scheduled_tasks"); + // if (is_null($scheduled_task) && $scheduled_task == '') { + // return null; + // } + // $scheduled_task = trim($scheduled_task); + // return encrypt($scheduled_task); + } + + // protected function key(): Attribute + // { + // error_log("** in key()"); + + // // return Attribute::make( + // // set: fn (string $value) => Str::of($value)->trim(), + // // ); + // } +} diff --git a/database/migrations/2023_12_31_173041_create_scheduled_tasks_table.php b/database/migrations/2023_12_31_173041_create_scheduled_tasks_table.php new file mode 100644 index 000000000..b108cecf8 --- /dev/null +++ b/database/migrations/2023_12_31_173041_create_scheduled_tasks_table.php @@ -0,0 +1,36 @@ +id(); + $table->string('uuid')->unique(); + $table->boolean('enabled')->default(true); + $table->string('name'); + $table->string('command'); + $table->string('frequency'); + $table->string('container')->nullable(); + $table->timestamps(); + + $table->foreignId('application_id')->nullable(); + $table->foreignId('service_id')->nullable(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('scheduled_tasks'); + } +}; diff --git a/resources/views/livewire/project/application/configuration.blade.php b/resources/views/livewire/project/application/configuration.blade.php index 5d2936649..61fbc6c66 100644 --- a/resources/views/livewire/project/application/configuration.blade.php +++ b/resources/views/livewire/project/application/configuration.blade.php @@ -54,6 +54,9 @@ href="#">Resource Limits @endif + Scheduled Tasks + Danger Zone @@ -97,6 +100,9 @@
Are you sure you want to delete this scheduled task ({{ $task->name }})?
+