This commit is contained in:
pbao9
2026-02-03 11:07:47 +07:00
parent 0f9b6ffef2
commit 6178a76eee
18 changed files with 347 additions and 420 deletions
@@ -4,21 +4,17 @@ namespace App\Http\Controllers\admin\package;
use App\Http\Controllers\Controller;
use App\Http\Requests\Package\IPRequest;
use App\Models\ModuleDatacenter;
use App\Models\ModuleHost;
use App\Models\ModuleIpAddress;
use App\Models\ModuleNetwork;
use App\Models\vCenter;
use App\Repositories\Module\IpAddress\IpAddressRepositoryInterface;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Yajra\DataTables\Facades\DataTables;
class IPMapping extends Controller
{
public function __construct(
public IpAddressRepositoryInterface $ipAddressRepository
) {}
) {
}
public function index(Request $request)
{
$listIP = $this->ipAddressRepository->filter(
@@ -102,7 +98,7 @@ class IPMapping extends Controller
$ipaddress = $this->ipAddressRepository->findWithRelationships($id, ['host.datacenter.vCenter']);
if (! $ipaddress) {
if (!$ipaddress) {
return back()->withErrors('Can\'t find IP Address by ID #' . $id);
}
@@ -116,7 +112,7 @@ class IPMapping extends Controller
{
$ipaddress = $this->ipAddressRepository->find($id);
if (! $ipaddress) {
if (!$ipaddress) {
return back()->withErrors('Can\'t find IP Address by ID #' . $id);
}
@@ -142,9 +138,9 @@ class IPMapping extends Controller
public function destroy(int $id = 0)
{
$ipaddress = $this->ipAddressRepository->find($id);
$ipaddress = $this->ipAddressRepository->find($id);
if (! $ipaddress) {
if (!$ipaddress) {
return back()->withErrors('Can\'t find IP Address by ID #' . $id);
}
@@ -158,4 +154,28 @@ class IPMapping extends Controller
}
return back()->with('success', 'Deleted Successfully');
}
public function datatable(Request $request)
{
$query = $this->ipAddressRepository->filter(
$request->all(),
['host.datacenter.vCenter'],
[],
['*'],
true
);
return DataTables::eloquent($query)
->addColumn(
'action',
fn($d) =>
'<a href="' . route('package.ipaddress.edit', $d->id) . '" class="btn btn-primary btn-sm">Edit</a>'
)
->filterColumn('host.datacenter.v_center.host', function ($query, $keyword) {
$query->whereHas('host.datacenter.vCenter', function ($q) use ($keyword) {
$q->where('host', 'like', "%{$keyword}%");
});
})
->make(true);
}
}
@@ -122,18 +122,10 @@ class OsVersion extends Controller
return $d->getStatus();
})
->addColumn('action', function ($d) {
$editBtn = '<a href="' . route('package.version.edit', $d->id) . '"
class="btn btn-primary">
<i data-lucide="edit" class="w-12px h-12px"></i>
</a>';
$deleteBtn = '<button type="button"
class="btn btn-danger"
onclick="showDeleteModal(' . $d->id . ', \'' . addslashes($d->version) . '\')">
<i data-lucide="trash-2" class="w-12px h-12px"></i>
</button>';
return '<div class="btn-group" role="group">' . $editBtn . $deleteBtn . '</div>';
return view('administrator.pages.package.version.datatable.action', [
'id' => $d->id,
'version' => $d->version
])->render();
})
->filterColumn('host', function ($query, $keyword) {
$query->whereHas('host', function ($q) use ($keyword) {
@@ -16,19 +16,32 @@ class IpAddressCachedRepository extends BaseCachedRepository implements IpAddres
{
return $this->ipAddressRepository->getModel();
}
public function filter(array $data = [], array $relationships = [], array $withCount = [], array $select = ['*'])
{
public function filter(
array $data = [],
array $relationships = [],
array $withCount = [],
array $select = ['*'],
bool $returnQuery = false
) {
if (
$returnQuery ||
!empty($data['paginate'])
) {
return $this->ipAddressRepository
->filter($data, $relationships, $withCount, $select, $returnQuery);
}
$cacheKey = $this->getCacheKey(md5(json_encode([
'filterItem' => [
'data' => $data,
'relationships' => $relationships,
'select' => $select,
'withCount' => $withCount
]
'filter' => compact('data', 'relationships', 'withCount', 'select')
])));
return Cache::remember($cacheKey, $this->cacheTime, function () use ($data, $relationships, $select, $withCount) {
return $this->ipAddressRepository->filter($data, $relationships, $withCount, $select);
});
return Cache::remember(
$cacheKey,
$this->cacheTime,
fn() =>
$this->ipAddressRepository
->filter($data, $relationships, $withCount, $select, $returnQuery)
);
}
public function updateBy(array $condistions = [], array $data = [])
{
@@ -36,7 +49,7 @@ class IpAddressCachedRepository extends BaseCachedRepository implements IpAddres
$this->clearCache();
return $this;
}
public function findWithRelationships(int $id = 0, array $relationships = [],array $withCount = [], array $withSum = [])
public function findWithRelationships(int $id = 0, array $relationships = [], array $withCount = [], array $withSum = [])
{
$cacheKey = $this->getCacheKey(md5(json_encode([
'findWithRelationships' => [
@@ -44,8 +57,8 @@ class IpAddressCachedRepository extends BaseCachedRepository implements IpAddres
'relationships' => $relationships
]
])));
return Cache::remember($cacheKey, $this->cacheTime, function () use ($id, $relationships,$withCount,$withSum) {
return $this->ipAddressRepository->findWithRelationships($id, $relationships,$withCount,$withSum);
return Cache::remember($cacheKey, $this->cacheTime, function () use ($id, $relationships, $withCount, $withSum) {
return $this->ipAddressRepository->findWithRelationships($id, $relationships, $withCount, $withSum);
});
}
public function findBy(string $key = '', string|int|null $value = '')
@@ -11,23 +11,30 @@ class IpAddressRepository extends BaseRepository implements IpAddressRepositoryI
{
return ModuleIpAddress::class;
}
public function filter(array $data = [], array $relationships = [], array $withCount = [], array $select = ['*'])
public function filter(array $data = [], array $relationships = [], array $withCount = [], array $select = ['*'], bool $returnQuery = false)
{
$model = $this->model->with($relationships)->select($select);
$query = $this->model->with($relationships)->select($select);
if (isset($data['status'])) {
$model = $model->where("status", $data['status']);
$query = $query->where("status", $data['status']);
}
if (isset($data['module_network_id']) && $data['module_network_id']) {
$model = $model->where("module_network_id", $data['module_network_id']);
$query->where("module_network_id", $data['module_network_id']);
}
if (count($withCount) > 0) {
$model = $model->withCount($withCount);
$query->withCount($withCount);
}
if (isset($data['page'])) {
return $model->paginate(15);
if ($returnQuery) {
return $query;
}
return $model->get();
if (!empty($data['paginate'])) {
return $query->paginate(
$data['per_page'] ?? 15
);
}
return $query->get();
}
public function findWithRelationships(int $id = 0, array $relationships = [], array $withCount = [], array $withSum = [])
{
@@ -6,9 +6,15 @@ use App\Repositories\BaseRepositoryInterface;
interface IpAddressRepositoryInterface extends BaseRepositoryInterface
{
public function filter(array $data = [], array $relationships = [], array $withCount = [], array $select = ['*']);
public function filter(
array $data = [],
array $relationships = [],
array $withCount = [],
array $select = ['*'],
bool $returnQuery = false
);
public function updateBy(array $condistions = [], array $data = []);
public function findBy(string $key = '',string|int|null $value = '' );
public function findWithRelationships(int $id = 0, array $relationships = [],array $withCount = [], array $withSum = []);
public function findBy(string $key = '', string|int|null $value = '');
public function findWithRelationships(int $id = 0, array $relationships = [], array $withCount = [], array $withSum = []);
}
@@ -1,10 +1,9 @@
<a href="{{ route('package.group.create') }}" class="btn btn-outline-secondary">
<i class="fas fa-plus-circle"></i> Add New Group</a>
<form action="{{ route('package.group.import') }}" class="d-lg-inline" enctype="multipart/form-data" method="post">
<x-button-crm type="button" variant="primary" size="md" route="package.group.create" icon="plus-circle">Add
Group</x-button-crm>
<form action="{{ route('package.group.import') }}" class="d-inline" enctype="multipart/form-data" method="post">
@csrf
<input type="file" name="file" class="d-none file-selector" accept=".csv,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" onchange="form.submit()" />
<button type="button" class="btn btn-outline-secondary btn-import__from">
<i class="fas fa-plus-circle"></i> Import From Excel
</button>
<x-button-crm type="button" variant="danger" size="md" icon="cloud-download">Import From Excel</x-button-crm>
</form>
<a href="{{ url('file/vCenter.xlsx') }}" class="btn btn-outline-secondary"><i class="fas fa-download"></i> File Import Demo</a>
<x-button-crm type="button" variant="secondary" size="md" :url="url('file/vCenter.xlsx')" icon="paperclip">File Import
Demo</x-button-crm>
@@ -1,118 +1,110 @@
@extends('administrator.layout.master')
@push('plugin-styles')
<link href="{{ asset('build/plugins/select2/select2.min.css') }}" rel="stylesheet" />
@foreach (config('assets.datatable.css') as $datatable)
<link href="{{ asset($datatable) }}" rel="stylesheet" />
@endforeach
@endpush
@php
use App\Enums\Status;
@endphp
@section('breadcrumb')
@section('breadcrumb')
@php
$breadcrumbItems = [
['label' => 'Modules'],
['label' => 'Package vCenter'],
['label' => 'OS Group', 'url' => route('package.group.index')],
['label' => 'Edit', 'active' => true]
];
@endphp
<x-admin-breadcrumb :items="$breadcrumbItems" />
@endsection
@php
$breadcrumbItems = [
['label' => 'Modules'],
['label' => 'Package vCenter'],
['label' => 'OS Group'],
['label' => 'Add New', 'active' => true],
];
use App\Enums\Status;
@endphp
<x-admin-breadcrumb :items="$breadcrumbItems" />
@endsection
@section('content')
@if (auth()->guard('admins')->user()->can('add package module'))
<div class="card card-outline card-primary">
<form action="{{ route('package.group.store') }}" method="post">
@csrf
<div class="card-body">
<div class="row">
<div class="col">
{{-- Name --}}
<div class="row form-group align-items-center mb-0">
<label for="name" class="col-md-3 text-right">Group Name</label>
<div class="col-md-9 bg-customer p-1">
<input type="text" id="name" name="name" placeholder="" value=""
class="form-control">
@section('content')
@if (auth()->guard('admins')->user()->can('add package module'))
<div class="card card-outline card-primary">
<form action="{{ route('package.group.store') }}" method="post">
@csrf
<div class="card-body">
<div class="row">
<div class="col">
{{-- Name --}}
<div class="row form-group align-items-center mb-0">
<label for="name" class="col-md-3 text-right">Group Name</label>
<div class="col-md-9 bg-customer p-1">
<input type="text" id="name" name="name" placeholder="" value="" class="form-control">
</div>
</div>
</div>
{{-- Thumbnail --}}
<div class="row form-group align-items-center mb-0">
<label for="thumbnail" class="col-md-3 text-right">Thumbnail</label>
<div class="col-md-9 p-1">
<div class="row">
<div class="col-md-8 bg-customer">
<input type="text" data-choise="upload-images" name="thumbnail"
value="{{ old('thumbnail') }}" class="form-control" placeholder="Chọn File">
</div>
<div class="col-md-4">
<button type="button" class="btn btn-outline-secondary btn-open-thumb">
<i class="fas fa-folder-open"></i> Chọn hình ảnh
</button>
{{-- Thumbnail --}}
<div class="row form-group align-items-center mb-0">
<label for="thumbnail" class="col-md-3 text-right">Thumbnail</label>
<div class="col-md-9 p-1">
<div class="row">
<div class="col-md-8 bg-customer">
<input type="text" data-choise="upload-images" name="thumbnail"
value="{{ old('thumbnail') }}" class="form-control" placeholder="Chọn File">
</div>
<div class="col-md-4">
<button type="button" class="btn btn-outline-secondary btn-open-thumb">
<i class="fas fa-folder-open"></i> Chọn hình ảnh
</button>
</div>
</div>
</div>
</div>
</div>
<x-module.v-center :model="null" />
<x-module.datacenter :model="null" />
<x-module.host :model="null" />
{{-- Status --}}
<div class="row form-group align-items-center mb-0">
<label for="status" class="col-md-3 text-right">Status</label>
<div class="col-md-9 p-1 bg-customer">
<select class="custom-select select2" id="status" name="status">
@foreach (Status::getOptions() as $value => $label)
<option value="{{ $value }}">
{{ $label }}
</option>
@endforeach
</select>
<x-module.v-center :model="null" />
<x-module.datacenter :model="null" />
<x-module.host :model="null" />
{{-- Status --}}
<div class="row form-group align-items-center mb-0">
<label for="status" class="col-md-3 text-right">Status</label>
<div class="col-md-9 p-1 bg-customer">
<select class="custom-select select2" id="status" name="status">
@foreach (Status::getOptions() as $value => $label)
<option value="{{ $value }}">
{{ $label }}
</option>
@endforeach
</select>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="card-footer">
<a href="{{ route('package.group.index') }}" class="btn btn-outline-secondary">Trở về</a>
<button type="submit" class="btn btn-outline-primary">Lưu dữ liệu</button>
</div>
</form>
</div>
@else
<div class="alert alert-danger alert-dismissible">
<h5 class="mb-0"><i class="icon fas fa-ban"></i> Access Denied - You are not assigned to any Module Package
management department</h5>
</div>
@endif
@endsection
@push('scripts')
<script type="text/javascript">
$('.btn-open-thumb').click(function() {
CKFinder.popup({
chooseFiles: true,
onInit: function(finder) {
finder.on('files:choose', function(evt) {
let img = $('input[name="thumbnail"]');
if (img.length) {
img.val(evt.data.files.first().getUrl())
img.trigger('input')
}
});
}
<div class="card-footer">
<a href="{{ route('package.group.index') }}" class="btn btn-outline-secondary">Trở về</a>
<button type="submit" class="btn btn-outline-primary">Lưu dữ liệu</button>
</div>
</form>
</div>
@else
<div class="alert alert-danger alert-dismissible">
<h5 class="mb-0"><i class="icon fas fa-ban"></i> Access Denied - You are not assigned to any Module Package
management department</h5>
</div>
@endif
@endsection
@push('scripts')
<script type="text/javascript">
$('.btn-open-thumb').click(function () {
CKFinder.popup({
chooseFiles: true,
onInit: function (finder) {
finder.on('files:choose', function (evt) {
let img = $('input[name="thumbnail"]');
if (img.length) {
img.val(evt.data.files.first().getUrl())
img.trigger('input')
}
});
}
});
});
});
// Initialize Select2
$(document).ready(function() {
$('.select2').select2({
theme: 'bootstrap4',
width: '100%'
});
});
</script>
@endpush
@push('plugin-scripts')
<script src="{{ asset('build/plugins/jquery/jquery.min.js') }}"></script>
<script src="{{ asset('build/plugins/select2/select2.min.js') }}"></script>
<script src="{{ asset('build/plugins/datatables.net/dataTables.min.js') }}"></script>
<script src="{{ asset('build/plugins/datatables.net-bs5/dataTables.bootstrap5.min.js') }}"></script>
@endpush
</script>
@endpush
@push('plugin-scripts')
@foreach (config('assets.datatable.js') as $datatable)
<script src="{{ asset($datatable) }}"></script>
@endforeach
@endpush
@@ -1,22 +1,24 @@
@extends('administrator.layout.master')
@push('plugin-styles')
<link href="{{ asset('build/plugins/select2/select2.min.css') }}" rel="stylesheet" />
@foreach (config('assets.datatable.css') as $datatable)
<link href="{{ asset($datatable) }}" rel="stylesheet" />
@endforeach
@endpush
@php
use App\Enums\Status;
@endphp
@section('breadcrumb')
@php
$breadcrumbItems = [
['label' => 'Modules'],
['label' => 'Package vCenter'],
['label' => 'OS Group', 'active' => true],
['label' => 'OS Group', 'url' => route('package.group.index')],
['label' => 'Edit', 'active' => true]
];
@endphp
<x-admin-breadcrumb :items="$breadcrumbItems" />
@endsection
@php
use App\Enums\Status;
@endphp
@section('content')
@if (auth()->guard('admins')->user()->can('add package module'))
<div class="card card-outline card-primary">
@@ -30,8 +32,8 @@
<div class="row form-group align-items-center mb-0">
<label for="name" class="col-md-3 text-right">Group Name</label>
<div class="col-md-9 bg-customer p-1">
<input type="text" id="name" name="name" placeholder=""
value="{{ $group->name }}" class="form-control">
<input type="text" id="name" name="name" placeholder="" value="{{ $group->name }}"
class="form-control">
</div>
</div>
{{-- Thumbnail --}}
@@ -87,11 +89,11 @@
@endsection
@push('scripts')
<script type="text/javascript">
$('.btn-open-thumb').click(function() {
$('.btn-open-thumb').click(function () {
CKFinder.popup({
chooseFiles: true,
onInit: function(finder) {
finder.on('files:choose', function(evt) {
onInit: function (finder) {
finder.on('files:choose', function (evt) {
let img = $('input[name="thumbnail"]');
if (img.length) {
img.val(evt.data.files.first().getUrl())
@@ -102,18 +104,10 @@
});
});
// Initialize Select2
$(document).ready(function() {
$('.select2').select2({
theme: 'bootstrap4',
width: '100%'
});
});
</script>
@endpush
@push('plugin-scripts')
<script src="{{ asset('build/plugins/jquery/jquery.min.js') }}"></script>
<script src="{{ asset('build/plugins/select2/select2.min.js') }}"></script>
<script src="{{ asset('build/plugins/datatables.net/dataTables.min.js') }}"></script>
<script src="{{ asset('build/plugins/datatables.net-bs5/dataTables.bootstrap5.min.js') }}"></script>
@foreach (config('assets.datatable.js') as $datatable)
<script src="{{ asset($datatable) }}"></script>
@endforeach
@endpush
@@ -1,32 +1,33 @@
@extends('administrator.layout.master')
@push('plugin-styles')
<link href="{{ asset('build/plugins/select2/select2.min.css') }}" rel="stylesheet" />
@foreach (config('assets.datatable.css') as $datatable)
<link href="{{ asset($datatable) }}" rel="stylesheet" />
@endforeach
@endpush
@section('breadcrumb')
@php
$breadcrumbItems = [
['label' => 'Modules'],
['label' => 'Package vCenter'],
['label' => 'OS Group', 'active' => true],
];
$breadcrumbItems = [
['label' => 'Modules'],
['label' => 'Package vCenter'],
['label' => 'OS Group', 'active' => true],
];
@endphp
<x-admin-breadcrumb :items="$breadcrumbItems" />
@endsection
@section('content')
@if (auth()->guard('admins')->user()->can('manager package module'))
<div class="card card-primary card-outline">
<div class="card-header">
<div class="card-header d-flex justify-content-end gap-2">
@include('administrator.pages.block.Group')
</div>
<div class="card-body">
<x-datatable id="groupTable" ajax="{{ route('package.group.datatable') }}" :columns="[
['key' => 'name', 'label' => 'Name'],
['key' => 'thumbnail', 'label' => 'Thumbnail'],
['key' => 'module_host_id', 'label' => 'Host'],
['key' => 'status', 'label' => 'Status'],
['key' => 'action', 'label' => 'Action'],
]" />
['key' => 'name', 'label' => 'Name'],
['key' => 'thumbnail', 'label' => 'Thumbnail'],
['key' => 'module_host_id', 'label' => 'Host'],
['key' => 'status', 'label' => 'Status'],
['key' => 'action', 'label' => 'Action'],
]" />
</div>
</div>
@else
@@ -41,4 +42,4 @@
<script src="{{ asset('build/plugins/select2/select2.min.js') }}"></script>
<script src="{{ asset('build/plugins/datatables.net/dataTables.min.js') }}"></script>
<script src="{{ asset('build/plugins/datatables.net-bs5/dataTables.bootstrap5.min.js') }}"></script>
@endpush
@endpush
@@ -1,18 +1,15 @@
@extends('administrator.layout.master')
@push('plugin-styles')
<link href="{{ asset('build/plugins/select2/select2.min.css') }}" rel="stylesheet" />
@foreach (config('assets.datatable.css') as $datatable)
<link href="{{ asset($datatable) }}" rel="stylesheet" />
@endforeach
@endpush
@php
use App\Enums\Status;
@endphp
@section('breadcrumb')
@php
$breadcrumbItems = [
['label' => 'Modules'],
['label' => 'Package vCenter'],
['label' => 'Datacenter', 'active' => true],
['label' => 'IP Address', 'active' => true],
];
@endphp
<x-admin-breadcrumb :items="$breadcrumbItems" />
@@ -20,74 +17,16 @@
@section('content')
@if(auth()->guard('admins')->user()->can("manager package module"))
<div class="card card-primary card-outline">
<div class="card-header">
<a href="{{ route('package.ipaddress.create') }}" class="btn btn-outline-secondary">
<i class="fas fa-plus"></i> Add New IP Address
</a>
<div class="card-header d-flex justify-content-end">
<x-button-crm type="button" variant="primary" size="md" route="package.ipaddress.create" icon="plus-circle">Add
IP Address</x-button-crm>
</div>
<div class="card-body">
<table class="table table-invoice table-bordered">
<thead>
<tr>
<th>
<label>
<input type="checkbox" name="check" class="check-all">
</label>
</th>
<th>VMWare Name</th>
<th>IP Address</th>
<th>Host Name</th>
<th>Status</th>
<th style="width: 40px"></th>
<th style="width: 40px"></th>
</tr>
</thead>
<tbody>
@if($listIP->count())
@foreach($listIP->all() as $item)
<tr>
<td class="text-center">
<label for=""></label><input type="checkbox" name="id[]" value="{{ $item->id }}"
id="">
</td>
<td class="text-center">
{{ $item->vm_name }}
</td>
<td class="text-center">
{{ $item->ip }}
</td>
<td class="text-center">
{{ $item->Host->name }}
</td>
<td class="text-center">
{!! $item->getStatus() !!}
</td>
<td class="text-center">
<a class="btn btn-warning btn-sm"
href="{{ route('package.ipaddress.edit',['id' => $item->id]) }}">
<i class="fas fa-user-edit"></i>
</a>
</td>
<td class="text-center">
<form method="post"
class="d-inline"
action="{{ route('package.ipaddress.destroy',['id' => $item->id]) }}">
@method('delete')
@csrf
<button type="submit" data-toggle="tooltip" data-placement="top" title=""
class="btn btn-sm btn-danger" data-original-title="Xoá">
<i class="fas fa-trash"></i>
</button>
</form>
</td>
</tr>
@endforeach
@endif
</tbody>
</table>
</div>
<div class="card-footer">
{{ $listIP->withQueryString()->links() }}
<x-datatable id="ipAddressTable" ajax="{{ route('package.ipaddress.datatable') }}" :columns="[
['key' => 'vm_name', 'label' => 'Name'],
['key' => 'host.name', 'label' => 'Host'],
['key' => 'action', 'label' => 'Action']
]" />
</div>
</div>
@else
@@ -99,9 +38,7 @@
@endsection
@push('plugin-scripts')
<script src="{{ asset('build/plugins/jquery/jquery.min.js') }}"></script>
<script src="{{ asset('build/plugins/select2/select2.min.js') }}"></script>
<script src="{{ asset('build/plugins/datatables.net/dataTables.min.js') }}"></script>
<script src="{{ asset('build/plugins/datatables.net-bs5/dataTables.bootstrap5.min.js') }}"></script>
@endpush
@foreach (config('assets.datatable.js') as $datatable)
<script src="{{ asset($datatable) }}"></script>
@endforeach
@endpush
@@ -1,22 +1,25 @@
@extends('administrator.layout.master')
@push('plugin-styles')
<link href="{{ asset('build/plugins/select2/select2.min.css') }}" rel="stylesheet" />
@foreach (config('assets.datatable.css') as $datatable)
<link href="{{ asset($datatable) }}" rel="stylesheet" />
@endforeach
@endpush
@php
use App\Enums\Status;
@endphp
@section('breadcrumb')
@php
$breadcrumbItems = [
['label' => 'Modules'],
['label' => 'Package vCenter'],
['label' => 'Os Version', 'active' => true],
['label' => 'Version', 'url' => route('package.version.index')],
['label' => 'Add Version', 'active' => true],
];
@endphp
<x-admin-breadcrumb :items="$breadcrumbItems" />
@endsection
@php
use App\Enums\Status;
@endphp
@section('content')
@if (auth()->guard('admins')->user()->can('add package module'))
<div class="card card-outline card-primary">
@@ -49,7 +52,7 @@
<div class="row form-group align-items-center mb-0">
<label for="status" class="col-md-3 text-right">Status</label>
<div class="col-md-9 p-1 bg-customer">
<select class="custom-select select2" id="status" name="status">
<select class="custom-select select2 single__select" id="status" name="status">
@foreach(Status::getOptions() as $value => $label)
<option value="{{ $value }}" @selected(old('status') == $value)>
{{ $label }}
@@ -76,25 +79,10 @@
@endsection
@push('scripts')
<script type="text/javascript">
$(document).ready(function() {
// Initialize Select2 using global function
if (typeof window.initSelect2 === 'function') {
window.initSelect2();
}
// Initialize other Select2 elements
$('.select2').select2({
theme: 'bootstrap4',
width: '100%'
});
});
</script>
@endpush
@push('plugin-scripts')
<script src="{{ asset('build/plugins/jquery/jquery.min.js') }}"></script>
<script src="{{ asset('build/plugins/select2/select2.min.js') }}"></script>
<script src="{{ asset('build/plugins/datatables.net/dataTables.min.js') }}"></script>
<script src="{{ asset('build/plugins/datatables.net-bs5/dataTables.bootstrap5.min.js') }}"></script>
@foreach (config('assets.datatable.js') as $datatable)
<script src="{{ asset($datatable) }}"></script>
@endforeach
@endpush
@@ -0,0 +1,6 @@
<div class="d-flex gap-2">
<x-button-crm route="package.version.edit" :params="['id' => $id]" variant="primary" size="sm" class="p-1"
icon="edit">Edit</x-button-crm>
<x-button-crm type="button" variant="danger" size="sm" icon="trash-2" class="p-1"
onclick="showDeleteModal({{ $id }}, '{{ addslashes($version) }}')">Delete</x-button-crm>
</div>
@@ -21,17 +21,11 @@
</div>
</main>
<footer class="modal__footer">
<button type="button" class="btn btn-outline-secondary btn-sm me-2" data-micromodal-close>
<i data-lucide="x" class="me-1"></i>
Cancel
</button>
<x-button-crm type="button" variant="secondary" size="sm" icon="x" data-micromodal-close>Cancel</x-button-crm>
<form id="deleteForm" method="POST" class="d-inline">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-primary btn-sm">
<i data-lucide="trash-2" class="me-1"></i>
Delete
</button>
<x-button-crm type="submit" variant="danger" size="sm" icon="trash-2">Confirm Delete</x-button-crm>
</form>
</footer>
</div>
@@ -40,10 +34,10 @@
@push('custom-scripts')
<script>
document.addEventListener('DOMContentLoaded', function() {
document.addEventListener('DOMContentLoaded', function () {
function initializeModal() {
if (typeof ModalManager !== 'undefined') {
window.showDeleteModal = function(id, name) {
window.showDeleteModal = function (id, name) {
// Update modal content
const nameElement = document.getElementById('deleteItemName');
const formElement = document.getElementById('deleteForm');
@@ -66,4 +60,4 @@
setTimeout(initializeModal, 50);
});
</script>
@endpush
@endpush
@@ -1,6 +1,8 @@
@extends('administrator.layout.master')
@push('plugin-styles')
<link href="{{ asset('build/plugins/select2/select2.min.css') }}" rel="stylesheet" />
@foreach (config('assets.datatable.css') as $datatable)
<link href="{{ asset($datatable) }}" rel="stylesheet" />
@endforeach
@endpush
@php
@@ -12,7 +14,8 @@
$breadcrumbItems = [
['label' => 'Modules'],
['label' => 'Package vCenter'],
['label' => 'Datacenter', 'active' => true],
['label' => 'Version', 'url' => route('package.version.index')],
['label' => 'Edit Version', 'active' => true],
];
@endphp
<x-admin-breadcrumb :items="$breadcrumbItems" />
@@ -78,12 +81,12 @@
@push('scripts')
<script type="text/javascript">
$(document).ready(function() {
$(document).ready(function () {
// Initialize Select2 using global function
if (typeof window.initSelect2 === 'function') {
window.initSelect2();
}
// Initialize other Select2 elements
$('.select2').select2({
theme: 'bootstrap4',
@@ -94,8 +97,7 @@
@endpush
@push('plugin-scripts')
<script src="{{ asset('build/plugins/jquery/jquery.min.js') }}"></script>
<script src="{{ asset('build/plugins/select2/select2.min.js') }}"></script>
<script src="{{ asset('build/plugins/datatables.net/dataTables.min.js') }}"></script>
<script src="{{ asset('build/plugins/datatables.net-bs5/dataTables.bootstrap5.min.js') }}"></script>
@endpush
@foreach (config('assets.datatable.js') as $datatable)
<script src="{{ asset($datatable) }}"></script>
@endforeach
@endpush
@@ -1,6 +1,8 @@
@extends('administrator.layout.master')
@push('plugin-styles')
<link href="{{ asset('build/plugins/select2/select2.min.css') }}" rel="stylesheet" />
@foreach (config('assets.datatable.css') as $datatable)
<link href="{{ asset($datatable) }}" rel="stylesheet" />
@endforeach
@endpush
@section('breadcrumb')
@@ -8,7 +10,7 @@
$breadcrumbItems = [
['label' => 'Modules'],
['label' => 'Package vCenter'],
['label' => 'Datacenter', 'active' => true],
['label' => 'Version', 'active' => true],
];
@endphp
<x-admin-breadcrumb :items="$breadcrumbItems" />
@@ -16,10 +18,9 @@
@section('content')
@if (auth()->guard('admins')->user()->can('manager package module'))
<div class="card card-primary card-outline">
<div class="card-header">
<a href="{{ route('package.version.create') }}" class="btn btn-outline-primary">
<i data-lucide="plus" class="mr-2"></i> Add New Version OS
</a>
<div class="card-header d-flex justify-content-end gap-2">
<x-button-crm type="button" variant="primary" size="md" route="package.version.create" icon="plus-circle">Add
Version OS</x-button-crm>
</div>
<div class="card-body">
<x-datatable id="osVerisionTable" ajax="{{ route('package.version.datatable') }}" :columns="[
@@ -34,7 +35,8 @@
</div>
@else
<div class="alert alert-danger alert-dismissible">
<h5 class="mb-0"><i data-lucide="ban" class="icon mr-2"></i> Access Denied - You are not assigned to any Module Package
<h5 class="mb-0"><i data-lucide="ban" class="icon mr-2"></i> Access Denied - You are not assigned to any Module
Package
management department</h5>
</div>
@endif
@@ -43,27 +45,9 @@
@include('administrator.pages.package.version.datatable.modal')
@endsection
@push('scripts')
<script type="text/javascript">
$(document).ready(function() {
// Initialize Lucide icons
if (typeof lucide !== 'undefined') {
lucide.createIcons();
}
// Re-initialize icons when DataTable draws
$('#osVerisionTable').on('draw.dt', function() {
if (typeof lucide !== 'undefined') {
lucide.createIcons();
}
});
});
</script>
@endpush
@push('plugin-scripts')
<script src="{{ asset('build/plugins/jquery/jquery.min.js') }}"></script>
<script src="{{ asset('build/plugins/select2/select2.min.js') }}"></script>
<script src="{{ asset('build/plugins/datatables.net/dataTables.min.js') }}"></script>
<script src="{{ asset('build/plugins/datatables.net-bs5/dataTables.bootstrap5.min.js') }}"></script>
@endpush
@foreach (config('assets.datatable.js') as $datatable)
<script src="{{ asset($datatable) }}"></script>
@endforeach
@endpush
@@ -1,41 +1,41 @@
@php
$tag = 'button';
$href = null;
$tag = 'button';
$href = null;
if ($route) {
$href = route($route, $params);
$tag = 'a';
} elseif ($url) {
$href = $url;
$tag = 'a';
} elseif ($attributes->has('href')) {
$href = $attributes->get('href');
$tag = 'a';
}
if ($route) {
$href = route($route, $params);
$tag = 'a';
} elseif ($url) {
$href = $url;
$tag = 'a';
} elseif ($attributes->has('href')) {
$href = $attributes->get('href');
$tag = 'a';
}
$baseClasses = 'd-inline-flex gap-2 align-items-center justify-content-center text-white border-0 shadow-md px-2 py-1 rounded-2';
$baseClasses = 'd-inline-flex gap-2 align-items-center justify-content-center text-white border-0 shadow-md px-2 py-1 rounded-2';
$variants = [
'primary' => 'bg-primary',
'secondary' => 'bg-secondary',
'outline' => 'bg-outline',
'ghost' => 'bg-ghost',
'link' => 'bg-link',
'danger' => 'bg-danger',
'destructive' => 'bg-destructive',
];
$variants = [
'primary' => 'bg-primary',
'secondary' => 'bg-secondary',
'outline' => 'bg-outline',
'ghost' => 'bg-ghost',
'link' => 'bg-link',
'danger' => 'bg-danger',
'destructive' => 'bg-destructive',
];
$sizes = [
'default' => 'h-10',
'sm' => 'h-6',
'lg' => 'h-12',
'icon' => 'h-10',
];
$sizes = [
'default' => 'h-10',
'sm' => 'h-6',
'lg' => 'h-12',
'icon' => 'h-10',
];
$variantClass = $variants[$variant] ?? $variants['primary'];
$sizeClass = $sizes[$size] ?? $sizes['default'];
$variantClass = $variants[$variant] ?? $variants['primary'];
$sizeClass = $sizes[$size] ?? $sizes['default'];
$classes = "{$baseClasses} {$variantClass} {$sizeClass}";
$classes = "{$baseClasses} {$variantClass} {$sizeClass}";
@endphp
@if($tag === 'a')
@@ -48,7 +48,7 @@
@else
<button type="{{ $type }}" {{ $attributes->merge(['class' => $classes]) }}>
@if($icon)
<i data-lucide="{{ $icon }}" class="w-1 h-1 mr-2"></i>
<i data-lucide="{{ $icon }}" class="mr-2" style="height: 15px; width: 15px"></i>
@endif
{{ $slot }}
</button>
@@ -24,54 +24,45 @@
@push('custom-scripts')
<script>
$(document).ready(function () {
// Prevent multiple initializations using namespace
if (window.vcenterComponentInitialized) {
return;
}
window.vcenterComponentInitialized = true;
// Prevent multiple initializations using namespace
if (window.vcenterComponentInitialized) {
return;
}
window.vcenterComponentInitialized = true;
$('.select2').select2({
width: '100%'
});
$('.select2').select2({
width: '100%'
});
const $vcenter = $('.vcenter_id');
const $datacenter = $('.datacenter_id');
const $host = $('.host_id');
const $vcenter = $('.vcenter_id');
const $datacenter = $('.datacenter_id');
const $host = $('.host_id');
// Disable datacenter and host initially
// Note: In edit view these might be inputs not selects, so this logic might need adjustment if intended for cascading selects.
// For now, keeping logic but ensuring it doesn't break if elements aren't selects.
if ($datacenter.is('select')) {
$datacenter.prop('disabled', true);
}
if ($host.is('select')) {
$host.prop('disabled', true);
}
// Remove existing event handlers and bind new ones with namespace
$vcenter.off('change.vcenterComponent').on('change.vcenterComponent', function () {
const vcenterId = $(this).val();
// Reset and disable datacenter and host if they are selects
if ($datacenter.is('select')) {
$datacenter.html('<option value="">--- Chọn Datacenter ---</option>').prop('disabled', true);
$datacenter.prop('disabled', true);
}
if ($host.is('select')) {
$host.html('<option value="">--- Chọn Host ---</option>').prop('disabled', true);
$host.prop('disabled', true);
}
// Enable datacenter if vcenter is selected
if (vcenterId) {
$vcenter.off('change.vcenterComponent').on('change.vcenterComponent', function () {
const vcenterId = $(this).val();
if ($datacenter.is('select')) {
$datacenter.html('<option value="">--- Chọn Datacenter ---</option>').prop('disabled', true);
}
if ($host.is('select')) {
$host.html('<option value="">--- Chọn Host ---</option>').prop('disabled', true);
}
if (vcenterId) {
if ($datacenter.is('select')) $datacenter.prop('disabled', false);
}
});
if ($vcenter.val()) {
if ($datacenter.is('select')) $datacenter.prop('disabled', false);
}
});
// Trigger initial state
if ($vcenter.val()) {
if ($datacenter.is('select')) $datacenter.prop('disabled', false);
}
});
</script>
@endpush
@endpush
+1
View File
@@ -318,6 +318,7 @@ Route::prefix('administrator')->group(function () {
Route::get('edit/{id}', 'edit')->name('edit');
Route::put('edit/{id}', 'update')->name('update');
Route::delete('remove-ip-address/{id}', 'destroy')->name('destroy');
Route::get('datatable', 'datatable')->name('datatable');
});