feat(custom-field): tambahkan kolom label dan urutan prioritas
- Menambahkan kolom 'label' pada tabel custom_fields. - Menambahkan kolom 'urutan_prioritas' pada tabel custom_fields. - Memperbarui model CustomField untuk menyertakan kolom baru. - Memperbarui form input untuk label dan urutan prioritas di tampilan create dan index. - Menambahkan validasi untuk label dan urutan prioritas di CustomFieldRequest.
This commit is contained in:
@@ -1,150 +1,153 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Modules\Lpj\Http\Controllers;
|
namespace Modules\Lpj\Http\Controllers;
|
||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use Exception;
|
use Exception;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Maatwebsite\Excel\Facades\Excel;
|
use Maatwebsite\Excel\Facades\Excel;
|
||||||
use Modules\Lpj\Exports\CustomFieldExport;
|
use Modules\Lpj\Exports\CustomFieldExport;
|
||||||
use Modules\Lpj\Http\Requests\CustomFieldRequest;
|
use Modules\Lpj\Http\Requests\CustomFieldRequest;
|
||||||
use Modules\Lpj\Models\CustomField;
|
use Modules\Lpj\Models\CustomField;
|
||||||
|
|
||||||
class CustomFieldController extends Controller
|
class CustomFieldController extends Controller
|
||||||
{
|
|
||||||
public $user;
|
|
||||||
|
|
||||||
public function index()
|
|
||||||
{
|
{
|
||||||
return view('lpj::custom_fields.index');
|
public $user;
|
||||||
}
|
|
||||||
|
|
||||||
public function store(CustomFieldRequest $request)
|
public function index()
|
||||||
{
|
{
|
||||||
$validate = $request->validated();
|
return view('lpj::custom_fields.index');
|
||||||
|
}
|
||||||
|
|
||||||
if ($validate) {
|
public function store(CustomFieldRequest $request)
|
||||||
try {
|
{
|
||||||
// Save to database
|
$validate = $request->validated();
|
||||||
CustomField::create($validate);
|
|
||||||
return redirect()
|
if ($validate) {
|
||||||
->route('basicdata.custom-field.index')
|
try {
|
||||||
->with('success', 'Custom Field created successfully');
|
// Save to database
|
||||||
} catch (Exception $e) {
|
CustomField::create($validate);
|
||||||
return redirect()
|
return redirect()
|
||||||
->route('basicdata.custom-field.create')
|
->route('basicdata.custom-field.index')
|
||||||
->with('error', $e->getMessage());
|
->with('success', 'Custom Field created successfully');
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return redirect()
|
||||||
|
->route('basicdata.custom-field.create')
|
||||||
|
->with('error', $e->getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public function create()
|
public function create()
|
||||||
{
|
{
|
||||||
return view('lpj::custom_fields.create');
|
$urutan_prioritas = CustomField::max('urutan_prioritas')+1;
|
||||||
}
|
return view('lpj::custom_fields.create', compact('urutan_prioritas'));
|
||||||
|
|
||||||
public function edit($id)
|
|
||||||
{
|
|
||||||
$customField = CustomField::find($id);
|
|
||||||
return view('lpj::custom_fields.create', compact('customField'));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function update(CustomFieldRequest $request, $id)
|
|
||||||
{
|
|
||||||
$validate = $request->validated();
|
|
||||||
|
|
||||||
if ($validate) {
|
|
||||||
try {
|
|
||||||
// Update in database
|
|
||||||
$customField = CustomField::find($id);
|
|
||||||
$customField->update($validate);
|
|
||||||
return redirect()
|
|
||||||
->route('basicdata.custom-field.index')
|
|
||||||
->with('success', 'Custom Field updated successfully');
|
|
||||||
} catch (Exception $e) {
|
|
||||||
return redirect()
|
|
||||||
->route('basicdata.custom-field.edit', $id)
|
|
||||||
->with('error', 'Failed to update custom field');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public function destroy($id)
|
public function edit($id)
|
||||||
{
|
{
|
||||||
try {
|
|
||||||
// Delete from database
|
|
||||||
$customField = CustomField::find($id);
|
$customField = CustomField::find($id);
|
||||||
$customField->delete();
|
$urutan_prioritas = $customField->urutan_prioritas ?? CustomField::max('urutan_prioritas')+1;
|
||||||
|
return view('lpj::custom_fields.create', compact('customField', 'urutan_prioritas' ));
|
||||||
|
}
|
||||||
|
|
||||||
echo json_encode(['success' => true, 'message' => 'Custom Field deleted successfully']);
|
public function update(CustomFieldRequest $request, $id)
|
||||||
} catch (Exception $e) {
|
{
|
||||||
echo json_encode(['success' => false, 'message' => 'Failed to delete custom field']);
|
$validate = $request->validated();
|
||||||
|
|
||||||
|
if ($validate) {
|
||||||
|
try {
|
||||||
|
// Update in database
|
||||||
|
$customField = CustomField::find($id);
|
||||||
|
$customField->update($validate);
|
||||||
|
return redirect()
|
||||||
|
->route('basicdata.custom-field.index')
|
||||||
|
->with('success', 'Custom Field updated successfully');
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return redirect()
|
||||||
|
->route('basicdata.custom-field.edit', $id)
|
||||||
|
->with('error', 'Failed to update custom field');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function destroy($id)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
// Delete from database
|
||||||
|
$customField = CustomField::find($id);
|
||||||
|
$customField->delete();
|
||||||
|
|
||||||
|
echo json_encode(['success' => true, 'message' => 'Custom Field deleted successfully']);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
echo json_encode(['success' => false, 'message' => 'Failed to delete custom field']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function dataForDatatables(Request $request)
|
||||||
|
{
|
||||||
|
if (is_null($this->user) || !$this->user->can('custom_fields.view')) {
|
||||||
|
//abort(403, 'Sorry! You are not allowed to view custom fields.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieve data from the database
|
||||||
|
$query = CustomField::query();
|
||||||
|
|
||||||
|
// Apply search filter if provided
|
||||||
|
if ($request->has('search') && !empty($request->get('search'))) {
|
||||||
|
$search = $request->get('search');
|
||||||
|
$query->where(function ($q) use ($search) {
|
||||||
|
$q->where('name', 'LIKE', "%$search%");
|
||||||
|
$q->orWhere('label', 'LIKE', "%$search%");
|
||||||
|
$q->orWhere('type', 'LIKE', "%$search%");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply sorting if provided
|
||||||
|
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
|
||||||
|
$order = $request->get('sortOrder');
|
||||||
|
$column = $request->get('sortField');
|
||||||
|
$query->orderBy($column, $order);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the total count of records
|
||||||
|
$totalRecords = $query->count();
|
||||||
|
|
||||||
|
// Apply pagination if provided
|
||||||
|
if ($request->has('page') && $request->has('size')) {
|
||||||
|
$page = $request->get('page');
|
||||||
|
$size = $request->get('size');
|
||||||
|
$offset = ($page - 1) * $size; // Calculate the offset
|
||||||
|
|
||||||
|
$query->skip($offset)->take($size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the filtered count of records
|
||||||
|
$filteredRecords = $query->count();
|
||||||
|
|
||||||
|
// Get the data for the current page
|
||||||
|
$data = $query->get();
|
||||||
|
|
||||||
|
// Calculate the page count
|
||||||
|
$pageCount = ceil($totalRecords / $request->get('size'));
|
||||||
|
|
||||||
|
// Calculate the current page number
|
||||||
|
$currentPage = 0 + 1;
|
||||||
|
|
||||||
|
// Return the response data as a JSON object
|
||||||
|
return response()->json([
|
||||||
|
'draw' => $request->get('draw'),
|
||||||
|
'recordsTotal' => $totalRecords,
|
||||||
|
'recordsFiltered' => $filteredRecords,
|
||||||
|
'pageCount' => $pageCount,
|
||||||
|
'page' => $currentPage,
|
||||||
|
'totalCount' => $totalRecords,
|
||||||
|
'data' => $data,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function export()
|
||||||
|
{
|
||||||
|
return Excel::download(new CustomFieldExport, 'custom_fields.xlsx');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function dataForDatatables(Request $request)
|
|
||||||
{
|
|
||||||
if (is_null($this->user) || !$this->user->can('custom_fields.view')) {
|
|
||||||
//abort(403, 'Sorry! You are not allowed to view custom fields.');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Retrieve data from the database
|
|
||||||
$query = CustomField::query();
|
|
||||||
|
|
||||||
// Apply search filter if provided
|
|
||||||
if ($request->has('search') && !empty($request->get('search'))) {
|
|
||||||
$search = $request->get('search');
|
|
||||||
$query->where(function ($q) use ($search) {
|
|
||||||
$q->where('name', 'LIKE', "%$search%");
|
|
||||||
$q->orWhere('type', 'LIKE', "%$search%");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply sorting if provided
|
|
||||||
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
|
|
||||||
$order = $request->get('sortOrder');
|
|
||||||
$column = $request->get('sortField');
|
|
||||||
$query->orderBy($column, $order);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the total count of records
|
|
||||||
$totalRecords = $query->count();
|
|
||||||
|
|
||||||
// Apply pagination if provided
|
|
||||||
if ($request->has('page') && $request->has('size')) {
|
|
||||||
$page = $request->get('page');
|
|
||||||
$size = $request->get('size');
|
|
||||||
$offset = ($page - 1) * $size; // Calculate the offset
|
|
||||||
|
|
||||||
$query->skip($offset)->take($size);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the filtered count of records
|
|
||||||
$filteredRecords = $query->count();
|
|
||||||
|
|
||||||
// Get the data for the current page
|
|
||||||
$data = $query->get();
|
|
||||||
|
|
||||||
// Calculate the page count
|
|
||||||
$pageCount = ceil($totalRecords / $request->get('size'));
|
|
||||||
|
|
||||||
// Calculate the current page number
|
|
||||||
$currentPage = 0 + 1;
|
|
||||||
|
|
||||||
// Return the response data as a JSON object
|
|
||||||
return response()->json([
|
|
||||||
'draw' => $request->get('draw'),
|
|
||||||
'recordsTotal' => $totalRecords,
|
|
||||||
'recordsFiltered' => $filteredRecords,
|
|
||||||
'pageCount' => $pageCount,
|
|
||||||
'page' => $currentPage,
|
|
||||||
'totalCount' => $totalRecords,
|
|
||||||
'data' => $data,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function export()
|
|
||||||
{
|
|
||||||
return Excel::download(new CustomFieldExport, 'custom_fields.xlsx');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
namespace Modules\Lpj\Http\Requests;
|
namespace Modules\Lpj\Http\Requests;
|
||||||
|
|
||||||
use Illuminate\Foundation\Http\FormRequest;
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
use Modules\Lpj\Models\customField;
|
||||||
|
use Illuminate\Validation\Rule;
|
||||||
|
|
||||||
class CustomFieldRequest extends FormRequest
|
class CustomFieldRequest extends FormRequest
|
||||||
{
|
{
|
||||||
@@ -14,6 +16,12 @@ class CustomFieldRequest extends FormRequest
|
|||||||
return [
|
return [
|
||||||
'name' => 'required|max:255',
|
'name' => 'required|max:255',
|
||||||
'type' => 'required|in:text,select,radio,checkbox',
|
'type' => 'required|in:text,select,radio,checkbox',
|
||||||
|
'label' => 'nullable|max:255',
|
||||||
|
'urutan_prioritas' => [
|
||||||
|
'nullable',
|
||||||
|
'integer',
|
||||||
|
Rule::unique('custom_fields')->ignore($this->route('custom_field')),
|
||||||
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,5 +37,22 @@ class CustomFieldRequest extends FormRequest
|
|||||||
if(!$this->type){
|
if(!$this->type){
|
||||||
$this->merge(['type' => 'text']);
|
$this->merge(['type' => 'text']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!$this->urutan_prioritas) {
|
||||||
|
$maxPrioritas = CustomField::max('urutan_prioritas') ?? 0;
|
||||||
|
$this->merge(['urutan_prioritas' => $maxPrioritas + 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get custom messages for validator errors.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function messages()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'urutan_prioritas.unique' => 'Urutan prioritas sudah digunakan. Silakan pilih nomor lain.',
|
||||||
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,9 @@ class customField extends Base
|
|||||||
*/
|
*/
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'name',
|
'name',
|
||||||
'type'
|
'type',
|
||||||
|
'urutan_prioritas',
|
||||||
|
'label'
|
||||||
];
|
];
|
||||||
|
|
||||||
// protected static function newFactory(): CustomFieldFactory
|
// protected static function newFactory(): CustomFieldFactory
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('custom_fields', function (Blueprint $table) {
|
||||||
|
$table->integer('urutan_prioritas')->nullable()->after('type');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('custom_fields', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('urutan_prioritas');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('custom_fields', function (Blueprint $table) {
|
||||||
|
$table->string('label')->nullable()->after('name');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('custom_fields', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('label');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -39,6 +39,17 @@
|
|||||||
@enderror
|
@enderror
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
||||||
|
<label class="form-label max-w-56">
|
||||||
|
Label
|
||||||
|
</label>
|
||||||
|
<div class="flex flex-wrap items-baseline w-full">
|
||||||
|
<input class="input @error('label') border-danger bg-danger-light @enderror" type="text" name="label" value="{{ $customField->label ?? '' }}">
|
||||||
|
@error('label')
|
||||||
|
<em class="alert text-danger text-sm">{{ $message }}</em>
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
||||||
<label class="form-label max-w-56">
|
<label class="form-label max-w-56">
|
||||||
Type
|
Type
|
||||||
@@ -55,6 +66,17 @@
|
|||||||
@enderror
|
@enderror
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
||||||
|
<label class="form-label max-w-56">
|
||||||
|
Urutan Prioritas
|
||||||
|
</label>
|
||||||
|
<div class="flex flex-wrap items-baseline w-full">
|
||||||
|
<input class="input @error('urutan_prioritas') border-danger bg-danger-light @enderror" type="number" name="urutan_prioritas" value="{{ $customField->urutan_prioritas ?? $urutan_prioritas }}">
|
||||||
|
@error('urutan_prioritas')
|
||||||
|
<em class="alert text-danger text-sm">{{ $message }}</em>
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="flex justify-end">
|
<div class="flex justify-end">
|
||||||
<button type="submit" class="btn btn-primary">
|
<button type="submit" class="btn btn-primary">
|
||||||
Save
|
Save
|
||||||
|
|||||||
@@ -40,6 +40,10 @@
|
|||||||
<span class="sort"> <span class="sort-label"> Type </span>
|
<span class="sort"> <span class="sort-label"> Type </span>
|
||||||
<span class="sort-icon"> </span> </span>
|
<span class="sort-icon"> </span> </span>
|
||||||
</th>
|
</th>
|
||||||
|
<th class="min-w-[250px]" data-datatable-column="urutan_prioritas">
|
||||||
|
<span class="sort"> <span class="sort-label"> Urutan Prioritas </span>
|
||||||
|
<span class="sort-icon"> </span> </span>
|
||||||
|
</th>
|
||||||
<th class="min-w-[50px] text-center" data-datatable-column="actions">Action</th>
|
<th class="min-w-[50px] text-center" data-datatable-column="actions">Action</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
@@ -113,12 +117,15 @@
|
|||||||
return checkbox.outerHTML.trim();
|
return checkbox.outerHTML.trim();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
name: {
|
label: {
|
||||||
title: 'Custom Field',
|
title: 'Custom Field',
|
||||||
},
|
},
|
||||||
type: {
|
type: {
|
||||||
title: 'Type',
|
title: 'Type',
|
||||||
},
|
},
|
||||||
|
urutan_prioritas: {
|
||||||
|
title: 'Urutan Prioritas',
|
||||||
|
},
|
||||||
actions: {
|
actions: {
|
||||||
title: 'Status',
|
title: 'Status',
|
||||||
render: (item, data) => {
|
render: (item, data) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user