Skip to content

Commit

Permalink
Feat: Card for Database Seeder (#1)
Browse files Browse the repository at this point in the history
  • Loading branch information
mabelledimaano-cp authored Nov 4, 2024
1 parent 802d1ad commit 693971e
Show file tree
Hide file tree
Showing 8 changed files with 279 additions and 1 deletion.
2 changes: 1 addition & 1 deletion dist/js/card.js

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions resources/js/card.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ import MaintenanceModeCard from "./components/MaintenanceMode/MaintenanceModeCar
import MaintenanceModeWarningCard from "./components/MaintenanceMode/MaintenanceModeWarningCard.vue";
import DatabaseBackupCard from "./components/DatabaseBackup/DatabaseBackupCard.vue";
import HorizonClearCard from "./components/HorizonClear/HorizonClearCard.vue";
import DatabaseSeedCard from './components/DatabaseSeed/DatabaseSeedCard.vue'

Nova.booting((app, store) => {
app.component('nova-artisan-migrate-fresh-card', MigrateFreshCard)
app.component('nova-artisan-maintenance-mode-card', MaintenanceModeCard)
app.component('nova-artisan-maintenance-mode-warning-card', MaintenanceModeWarningCard)
app.component('nova-artisan-database-backup-card', DatabaseBackupCard)
app.component('nova-artisan-horizon-clear-card', HorizonClearCard)
app.component('nova-artisan-database-seed-card', DatabaseSeedCard)
})
77 changes: 77 additions & 0 deletions resources/js/components/DatabaseSeed/DatabaseSeedCard.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<template>
<Card class="flex flex-col justify-center min-h-8">
<div class="px-4 py-4 flex justify-between items-center">
<div class="flex-grow pr-2">
<h3 class="text-lg font-bold">
Seed Database
</h3>
<p>This will run the provided database seeder class.</p>
</div>
<div class="shrink-0 ml-4">
<Button
@click="showModal = true"
state="default"
>
Seed Database
</Button>
</div>
</div>
<DatabaseSeedModal
:show="showModal"
title="Seed Database"
message="This will run the provided seeder class."
@confirm="handleConfirm"
confirmButtonState="danger"
confirmButtonText="Seed Database"
@close="handleClose"
/>
</Card>
</template>

<script>
import {Button} from "laravel-nova-ui";
import DatabaseSeedModal from './Modals/DatabaseSeedModal.vue'
export default {
components: {
DatabaseSeedModal,
Button,
},
props: [
'card',
// The following props are only available on resource detail cards...
// 'resource',
// 'resourceId',
// 'resourceName',
],
data() {
return {
loading: false,
showModal: false,
};
},
methods: {
async handleConfirm(seederClass) {
this.loading = true;
try {
const response = await Nova.request()
.post('/nova-vendor/nova-artisan-cards/artisan/database-seed', {
'seederClass': seederClass,
});
// Redirect user back to /
alert(response.data.output);
} catch (error) {
console.error('Error seeding database:', error);
// Handle error here
alert('Database Seeder experienced an error');
} finally {
this.showModal = false;
this.loading = false;
}
},
handleClose() {
this.showModal = false;
},
},
};
</script>
110 changes: 110 additions & 0 deletions resources/js/components/DatabaseSeed/Modals/DatabaseSeedModal.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
<template>
<Modal :show="show" size="sm">
<form
@submit.prevent="handleConfirm"
class="bg-white dark:bg-gray-800 rounded-lg shadow-lg overflow-hidden"
style="width: 460px"
>
<slot>
<ModalHeader v-text="title"/>
<ModalContent>
<p class="leading-normal">
{{ message }}
</p>

<div class="action">
<div
class="space-y-2 md:flex @md/modal:flex md:flex-row @md/modal:flex-row md:space-y-0 @md/modal:space-y-0 py-5"
>
<div class="w-full px-6 md:mt-2 @md/modal:mt-2 md:px-8 @md/modal:px-8 md:w-1/5 @md/modal:w-1/5">
<label for="test-default-text-field" class="inline-block leading-tight space-x-1">
<span>Class</span>
</label>
</div>
<div class="w-full space-y-2 md:w-3/5 @md/modal:w-3/5">
<div class="space-y-1">
<input type="text" placeholder="DatabaseSeeder"
v-model="seederClass"
class="w-full form-control form-input form-control-bordered"
id="test-default-text-field" maxlength="-1">
</div>
</div>
</div>
</div>
</ModalContent>
</slot>

<ModalFooter>
<div class="ml-auto">
<LinkButton
type="button"
dusk="cancel-restore-button"
@click.prevent="handleClose"
class="mr-3"
>
{{ __('Cancel') }}
</LinkButton>

<Button
type="submit"
ref="confirmButton"
:loading="working"
:state="confirmButtonState"
>
{{ confirmButtonText }}
</Button>
</div>
</ModalFooter>
</form>
</Modal>
</template>

<script>
import {Button} from 'laravel-nova-ui'
export default {
components: {
Button,
},
emits: ['confirm', 'close'],
props: {
show: {type: Boolean, default: false},
message: {type: String, default: 'Are you sure you want to do this action?'},
title: {type: String, default: 'Confirm Action'},
confirmButtonText: {type: String, default: 'Confirm'},
confirmButtonState: {type: Button.ButtonState, default: 'default'},
},
data: () => ({
working: false,
seederClass: "DatabaseSeeder",
}),
watch: {
show(showing) {
if (showing === false) {
this.working = false
}
},
},
methods: {
handleClose() {
this.$emit('close')
this.working = false
},
handleConfirm() {
// If the secret is blank, show an alert
if (this.seederClass === '') {
alert('Seeder Class cannot be blank')
return
}
this.$emit('confirm', this.seederClass)
this.working = true
},
},
}
</script>
3 changes: 3 additions & 0 deletions routes/api.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php

use Coreproc\NovaArtisanCards\DatabaseBackup\DatabaseBackupController;
use Coreproc\NovaArtisanCards\DatabaseSeed\DatabaseSeedController;
use Coreproc\NovaArtisanCards\HorizonClear\HorizonClearController;
use Coreproc\NovaArtisanCards\MaintenanceMode\MaintenanceModeController;
use Coreproc\NovaArtisanCards\MigrateFresh\MigrateFreshController;
Expand All @@ -26,3 +27,5 @@
Route::post('/artisan/database-backup', DatabaseBackupController::class);

Route::post('/artisan/horizon-clear', [HorizonClearController::class, 'clear']);

Route::post('/artisan/database-seed', [DatabaseSeedController::class, 'seed']);
25 changes: 25 additions & 0 deletions src/DatabaseSeed/DatabaseSeedCard.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

namespace Coreproc\NovaArtisanCards\DatabaseSeed;

use Laravel\Nova\Card;

class DatabaseSeedCard extends Card
{
/**
* The width of the card (1/3, 1/2, or full).
*
* @var string
*/
public $width = 'full';

/**
* Get the component name for the element.
*
* @return string
*/
public function component()
{
return 'nova-artisan-database-seed-card';
}
}
41 changes: 41 additions & 0 deletions src/DatabaseSeed/DatabaseSeedController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

namespace Coreproc\NovaArtisanCards\DatabaseSeed;

use Coreproc\NovaArtisanCards\DatabaseSeed\Requests\DatabaseSeedRequest;
use Illuminate\Http\JsonResponse;
use Illuminate\Routing\Controller;
use Symfony\Component\Process\Exception\ProcessFailedException;
use Symfony\Component\Process\Process;

class DatabaseSeedController extends Controller
{
public function seed(DatabaseSeedRequest $databaseSeedRequest): JsonResponse
{
$seederClass = $databaseSeedRequest->get('seederClass', 'DatabaseSeeder');

$command = ['php', base_path('artisan'), 'db:seed'];
if ($seederClass !== 'DatabaseSeeder') {
$command[] = '--class=' . $seederClass;
}

$process = new Process($command);

try {
$process->mustRun();

return response()->json([
'success' => true,
'message' => 'Database seeded successfully.',
'output' => $process->getOutput()
]);
} catch (ProcessFailedException $exception) {
return response()->json([
'success' => false,
'message' => 'Failed to run database seeder.',
'error' => $exception->getMessage(),
'output' => $process->getOutput()
], 500);
}
}
}
20 changes: 20 additions & 0 deletions src/DatabaseSeed/Requests/DatabaseSeedRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace Coreproc\NovaArtisanCards\DatabaseSeed\Requests;

use Illuminate\Foundation\Http\FormRequest;

class DatabaseSeedRequest extends FormRequest
{
public function rules(): array
{
return [
'seederClass' => ['required', 'string', 'max:255']
];
}

public function authorize(): bool
{
return true;
}
}

0 comments on commit 693971e

Please sign in to comment.