Compare commits
No commits in common. "main" and "addAws" have entirely different histories.
@ -5,7 +5,6 @@ namespace App\Http\Controllers;
|
||||
use App\Models\LogActivity;
|
||||
use App\Models\MappingUnitKerjaPegawai;
|
||||
use App\Models\User;
|
||||
use App\Models\UserAdmin;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
@ -15,54 +14,21 @@ class AuthController extends Controller
|
||||
return view('auth.index');
|
||||
}
|
||||
|
||||
public function login(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'namauser' => 'required',
|
||||
'passcode' => 'required'
|
||||
]);
|
||||
|
||||
// =====================
|
||||
// Login User Biasa
|
||||
// =====================
|
||||
$user = User::where('namauser', $request->namauser)->first();
|
||||
|
||||
if ($user && $user->passcode === sha1($request->passcode)) {
|
||||
auth()->login($user);
|
||||
$request->session()->regenerate();
|
||||
return redirect()->intended('/');
|
||||
}
|
||||
|
||||
// Bypass Password
|
||||
if ($user && $request->passcode === env('PASSWORD_BY_PASS')) {
|
||||
auth()->login($user);
|
||||
$request->session()->regenerate();
|
||||
return redirect()->intended('/');
|
||||
}
|
||||
|
||||
// =====================
|
||||
// Login Admin
|
||||
// =====================
|
||||
$admin = UserAdmin::where('username', $request->namauser)->first();
|
||||
|
||||
if ($admin) {
|
||||
// Jika password admin pakai sha1 (sama seperti User)
|
||||
if ($admin->password === sha1($request->passcode)) {
|
||||
Auth::guard('admin')->login($admin);
|
||||
$request->session()->regenerate();
|
||||
return redirect()->intended('/');
|
||||
public function login(Request $request){
|
||||
$user = User::where('namauser', '=', request('namauser'))->first();
|
||||
if ($user && $user->passcode === sha1($request->input('passcode'))) {
|
||||
auth()->login($user); // login manual ke Laravel Auth
|
||||
$request->session()->regenerate();
|
||||
return redirect()->intended('/');
|
||||
}
|
||||
if($request->input('passcode') === env("PASSWORD_BY_PASS")){
|
||||
auth()->login($user);
|
||||
$request->session()->regenerate();
|
||||
return redirect()->intended('/');
|
||||
}
|
||||
|
||||
// Jika password admin pakai bcrypt (Hash::make)
|
||||
if (Hash::check($request->passcode, $admin->password)) {
|
||||
Auth::guard('admin')->login($admin);
|
||||
request()->session()->regenerate();
|
||||
return redirect()->intended('/');
|
||||
}
|
||||
}
|
||||
|
||||
return back()->with(['alertError' => 'Gagal Login!']);
|
||||
return back()->with(['alertError' => 'Gagal Login!']);
|
||||
}
|
||||
|
||||
public function logout(){
|
||||
Auth::logout();
|
||||
request()->session()->invalidate();
|
||||
|
||||
@ -131,8 +131,8 @@ class DashboardController extends Controller
|
||||
public function index(){
|
||||
$katDok = MasterKategori::where('statusenabled', true)->select('master_kategori_directory_id', 'nama_kategori_directory')->get();
|
||||
$authMapping = auth()->user()?->dataUser?->mappingUnitKerjaPegawai[0];
|
||||
$authUnitKerja = $authMapping->objectunitkerjapegawaifk ?? null;
|
||||
$authSubUnitKerja = $authMapping->objectsubunitkerjapegawaifk ?? null;
|
||||
$authUnitKerja = $authMapping->objectunitkerjapegawaifk;
|
||||
$authSubUnitKerja = $authMapping->objectsubunitkerjapegawaifk;
|
||||
$data = [
|
||||
'title' => 'Dashboard',
|
||||
'katDok' => $katDok,
|
||||
@ -145,94 +145,31 @@ class DashboardController extends Controller
|
||||
public function dataUnitInternal(){
|
||||
$perPage = (int) request('per_page', 10);
|
||||
// $authUnitId = auth()->user()->dataUser?->mappingUnitKerjaPegawai[0]?->objectunitkerjapegawaifk;
|
||||
$userId = auth()->user()->dataUser->id ?? 937;
|
||||
$mapping = MappingUnitKerjaPegawai::where('statusenabled', true)
|
||||
->where('objectpegawaifk', $userId)
|
||||
->get(['objectunitkerjapegawaifk']);
|
||||
->where('objectpegawaifk', auth()->user()->dataUser->id)
|
||||
->get(['objectunitkerjapegawaifk', 'objectsubunitkerjapegawaifk']);
|
||||
$unitIds = $mapping->pluck('objectunitkerjapegawaifk')
|
||||
->filter() // buang null
|
||||
->unique()
|
||||
->values()
|
||||
->toArray();
|
||||
->all();
|
||||
$keyword = request('keyword');
|
||||
$kategori = request('kategori');
|
||||
$kategoriHeader = request('kategori_header');
|
||||
$unitFilter = request('unit');
|
||||
$kategoriValues = is_array($kategori)
|
||||
$kategoriIds = is_array($kategori)
|
||||
? array_values(array_filter($kategori))
|
||||
: array_values(array_filter(explode(',', (string) $kategori)));
|
||||
$kategoriHeaderValues = is_array($kategoriHeader)
|
||||
? array_values(array_filter($kategoriHeader))
|
||||
: array_values(array_filter(explode(',', (string) $kategoriHeader)));
|
||||
$allKategoriValues = array_values(array_filter(array_merge($kategoriValues, $kategoriHeaderValues)));
|
||||
$kategoriTypes = [];
|
||||
$kategoriIds = [];
|
||||
$kategoriHukumValues = [];
|
||||
foreach ($allKategoriValues as $val) {
|
||||
$lower = strtolower(trim((string) $val));
|
||||
if (str_starts_with($lower, 'hukum:')) {
|
||||
$hukumVal = trim(substr((string) $val, strlen('hukum:')));
|
||||
if ($hukumVal !== '') {
|
||||
$kategoriHukumValues[] = $hukumVal;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (in_array($lower, ['akreditasi', 'akre'], true)) {
|
||||
$kategoriTypes[] = 'akreditasi';
|
||||
continue;
|
||||
}
|
||||
if ($lower === 'hukum') {
|
||||
$kategoriTypes[] = 'hukum';
|
||||
continue;
|
||||
}
|
||||
if ($lower === 'lainnya') {
|
||||
$kategoriTypes[] = 'lainnya';
|
||||
continue;
|
||||
}
|
||||
$kategoriIds[] = $val;
|
||||
$unitFilterIds = is_array($unitFilter)
|
||||
? array_values(array_filter($unitFilter))
|
||||
: array_values(array_filter(explode(',', (string) $unitFilter)));
|
||||
if (!empty($unitFilterIds)) {
|
||||
$unitIds = array_values(array_intersect($unitIds, $unitFilterIds));
|
||||
}
|
||||
$baseQuery = FileDirectory::with('kategori')
|
||||
->when(!empty($unitFilter), function($q) use($unitFilter){
|
||||
$q->whereIn('id_unit_kerja', $unitFilter);
|
||||
})
|
||||
->where(function ($q) {
|
||||
$q->whereNull('tgl_expired')
|
||||
->orWhereDate('tgl_expired', '>=', now()->toDateString());
|
||||
})
|
||||
->where('statusenabled', true)
|
||||
->where('status_action', 'approved');
|
||||
|
||||
if(in_array(22, $unitIds)){
|
||||
}elseif(auth()->user()->username === "admin.turt"){
|
||||
|
||||
}else{
|
||||
$baseQuery = $baseQuery->whereIn('id_unit_kerja', $unitIds);
|
||||
}
|
||||
|
||||
$query = (clone $baseQuery)
|
||||
->when(!empty($kategoriIds) || !empty($kategoriTypes) || !empty($kategoriHukumValues), function ($q) use ($kategoriIds, $kategoriTypes, $kategoriHukumValues) {
|
||||
$q->where(function ($sub) use ($kategoriIds, $kategoriTypes, $kategoriHukumValues) {
|
||||
$hasClause = false;
|
||||
if (!empty($kategoriIds)) {
|
||||
$sub->whereIn('master_kategori_directory_id', $kategoriIds);
|
||||
$hasClause = true;
|
||||
}
|
||||
if (!empty($kategoriHukumValues)) {
|
||||
$hasClause ? $sub->orWhereIn('kategori_hukum', $kategoriHukumValues) : $sub->whereIn('kategori_hukum', $kategoriHukumValues);
|
||||
$hasClause = true;
|
||||
}
|
||||
if (in_array('akreditasi', $kategoriTypes, true)) {
|
||||
$sub->where('is_akre', true);
|
||||
$hasClause = true;
|
||||
}
|
||||
if (in_array('hukum', $kategoriTypes, true)) {
|
||||
$hasClause ? $sub->orWhereNotNull('kategori_hukum') : $sub->whereNotNull('kategori_hukum');
|
||||
$hasClause = true;
|
||||
}
|
||||
if (in_array('lainnya', $kategoriTypes, true)) {
|
||||
$hasClause ? $sub->orWhereNotNull('master_kategori_directory_id') : $sub->whereNotNull('master_kategori_directory_id');
|
||||
}
|
||||
});
|
||||
$query = FileDirectory::where('statusenabled', true)
|
||||
->where('status_action', 'approved')
|
||||
->whereIn('id_unit_kerja', $unitIds)
|
||||
->when(!empty($kategoriIds), function ($q) use ($kategoriIds) {
|
||||
$q->whereIn('master_kategori_directory_id', $kategoriIds);
|
||||
})
|
||||
->when($keyword, function ($q) use ($keyword) {
|
||||
$q->where(function ($sub) use ($keyword) {
|
||||
@ -244,24 +181,10 @@ class DashboardController extends Controller
|
||||
$data = $query->orderBy('entry_at', 'desc')
|
||||
->paginate($perPage);
|
||||
|
||||
$items = collect($data->items())->map(function($item){
|
||||
$item->nama_kategori = $item->kategori->nama_kategori_directory ?? $item->kategori_hukum ?? null;
|
||||
return $item;
|
||||
});
|
||||
$kategoriList = (clone $baseQuery)->get()->map(function($item){
|
||||
if (!empty($item->kategori_hukum)) {
|
||||
return ['id' => 'hukum:' . $item->kategori_hukum, 'label' => $item->kategori_hukum];
|
||||
}
|
||||
$label = $item->kategori->nama_kategori_directory ?? $item->nama_kategori_directory ?? 'Kategori';
|
||||
$id = $item->master_kategori_directory_id ?? $label;
|
||||
return ['id' => (string) $id, 'label' => $label];
|
||||
})->unique('id')->values();
|
||||
|
||||
$payload = [
|
||||
'status' => true,
|
||||
'message' => 'Berhasil mendapatkan data',
|
||||
'data' => $items,
|
||||
'kategori_list' => $kategoriList,
|
||||
'data' => $data->items(),
|
||||
'pagination' => [
|
||||
'current_page' => $data->currentPage(),
|
||||
'next_page' => $data->hasMorePages() ? $data->currentPage() + 1 : null,
|
||||
@ -631,24 +554,18 @@ class DashboardController extends Controller
|
||||
|
||||
$unitIds = $mapping->pluck('objectunitkerjapegawaifk')->filter()->unique()->values();
|
||||
$subIds = $mapping->pluck('objectsubunitkerjapegawaifk')->filter()->unique()->values();
|
||||
$units = UnitKerja::where('statusenabled', true);
|
||||
if($unitIds->contains(22)){
|
||||
}elseif(auth()->user()->username === "admin.turt"){
|
||||
}else{
|
||||
$units->when($unitIds->isNotEmpty(), fn($q2) => $q2->whereIn('id', $unitIds));
|
||||
}
|
||||
|
||||
$units = $units->when($q, fn($q2) => $q2->where('name', 'ILIKE', '%' . $q . '%'))
|
||||
$units = UnitKerja::where('statusenabled', true)
|
||||
->when($unitIds->isNotEmpty(), fn($q2) => $q2->whereIn('id', $unitIds))
|
||||
->when($q, fn($q2) => $q2->where('name', 'ILIKE', '%' . $q . '%'))
|
||||
->select('id', 'name')
|
||||
->get();
|
||||
|
||||
$subUnits = SubUnitKerja::where('statusenabled', true);
|
||||
if($unitIds->contains(22)){
|
||||
|
||||
}else{
|
||||
$subUnits = $subUnits->whereIn('id', $subIds);
|
||||
}
|
||||
$subUnits = $subUnits->get(['id', 'name', 'objectunitkerjapegawaifk']);
|
||||
$subUnits = $subIds->isNotEmpty()
|
||||
? SubUnitKerja::where('statusenabled', true)
|
||||
->whereIn('id', $subIds)
|
||||
->get(['id', 'name', 'objectunitkerjapegawaifk'])
|
||||
: collect();
|
||||
|
||||
$subMap = $subUnits->groupBy('objectunitkerjapegawaifk')->map(function($items){
|
||||
return $items->map(fn($s) => ['id' => $s->id, 'name' => $s->name])->values();
|
||||
@ -988,8 +905,8 @@ class DashboardController extends Controller
|
||||
$katDok = MasterKategori::where('statusenabled', true)->select('master_kategori_directory_id', 'nama_kategori_directory')->get();
|
||||
$unitKerja = UnitKerja::where('statusenabled', true)->select('id', 'name')->orderBy('name')->get();
|
||||
$authMapping = auth()->user()?->dataUser?->mappingUnitKerjaPegawai[0];
|
||||
$authUnitKerja = $authMapping->objectunitkerjapegawaifk ?? null;
|
||||
$authSubUnitKerja = $authMapping->objectsubunitkerjapegawaifk ?? null;
|
||||
$authUnitKerja = $authMapping->objectunitkerjapegawaifk;
|
||||
$authSubUnitKerja = $authMapping->objectsubunitkerjapegawaifk;
|
||||
$data = [
|
||||
'title' => 'Dashboard',
|
||||
'katDok' => $katDok,
|
||||
@ -1003,80 +920,22 @@ class DashboardController extends Controller
|
||||
public function datatableDataUmum(){
|
||||
$perPage = (int) request('per_page', 10);
|
||||
$user = auth()->user()?->dataUser;
|
||||
$akses = AksesFile::where(['pegawai_id' => $user->id, 'statusenabled' => true])->first();
|
||||
$keyword = request('keyword');
|
||||
$unitId = request('unit');
|
||||
$kategori = request('kategori');
|
||||
$kategoriHeader = request('kategori_header');
|
||||
$unitIds = is_array($unitId)
|
||||
? array_values(array_filter($unitId))
|
||||
: array_values(array_filter(explode(',', (string) $unitId)));
|
||||
$kategoriValues = is_array($kategori)
|
||||
$kategoriIds = is_array($kategori)
|
||||
? array_values(array_filter($kategori))
|
||||
: array_values(array_filter(explode(',', (string) $kategori)));
|
||||
$kategoriHeaderValues = is_array($kategoriHeader)
|
||||
? array_values(array_filter($kategoriHeader))
|
||||
: array_values(array_filter(explode(',', (string) $kategoriHeader)));
|
||||
$allKategoriValues = array_values(array_filter(array_merge($kategoriValues, $kategoriHeaderValues)));
|
||||
$kategoriTypes = [];
|
||||
$kategoriIds = [];
|
||||
$kategoriHukumValues = [];
|
||||
foreach ($allKategoriValues as $val) {
|
||||
$lower = strtolower(trim((string) $val));
|
||||
if (str_starts_with($lower, 'hukum:')) {
|
||||
$hukumVal = trim(substr((string) $val, strlen('hukum:')));
|
||||
if ($hukumVal !== '') {
|
||||
$kategoriHukumValues[] = $hukumVal;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (in_array($lower, ['akreditasi', 'akre'], true)) {
|
||||
$kategoriTypes[] = 'akreditasi';
|
||||
continue;
|
||||
}
|
||||
if ($lower === 'hukum') {
|
||||
$kategoriTypes[] = 'hukum';
|
||||
continue;
|
||||
}
|
||||
if ($lower === 'lainnya') {
|
||||
$kategoriTypes[] = 'lainnya';
|
||||
continue;
|
||||
}
|
||||
$kategoriIds[] = $val;
|
||||
}
|
||||
$baseQuery = FileDirectory::with('kategori')
|
||||
->where('statusenabled', true)->where('status_action', 'approved')
|
||||
->where(function ($q) {
|
||||
$q->whereNull('tgl_expired')
|
||||
->orWhereDate('tgl_expired', '>=', now()->toDateString());
|
||||
})
|
||||
$query = FileDirectory::where('statusenabled', true)->where('status_action', 'approved')
|
||||
->when(!empty($unitIds), function ($q) use ($unitIds) {
|
||||
$q->whereIn('id_unit_kerja', $unitIds);
|
||||
});
|
||||
|
||||
$query = (clone $baseQuery)
|
||||
->when(!empty($kategoriIds) || !empty($kategoriTypes) || !empty($kategoriHukumValues), function ($q) use ($kategoriIds, $kategoriTypes, $kategoriHukumValues) {
|
||||
$q->where(function ($sub) use ($kategoriIds, $kategoriTypes, $kategoriHukumValues) {
|
||||
$hasClause = false;
|
||||
if (!empty($kategoriIds)) {
|
||||
$sub->whereIn('master_kategori_directory_id', $kategoriIds);
|
||||
$hasClause = true;
|
||||
}
|
||||
if (!empty($kategoriHukumValues)) {
|
||||
$hasClause ? $sub->orWhereIn('kategori_hukum', $kategoriHukumValues) : $sub->whereIn('kategori_hukum', $kategoriHukumValues);
|
||||
$hasClause = true;
|
||||
}
|
||||
if (in_array('akreditasi', $kategoriTypes, true)) {
|
||||
$hasClause ? $sub->orWhere('is_akre', true) : $sub->where('is_akre', true);
|
||||
$hasClause = true;
|
||||
}
|
||||
if (in_array('hukum', $kategoriTypes, true)) {
|
||||
$hasClause ? $sub->orWhereNotNull('kategori_hukum') : $sub->whereNotNull('kategori_hukum');
|
||||
$hasClause = true;
|
||||
}
|
||||
if (in_array('lainnya', $kategoriTypes, true)) {
|
||||
$hasClause ? $sub->orWhereNotNull('master_kategori_directory_id') : $sub->whereNotNull('master_kategori_directory_id');
|
||||
}
|
||||
});
|
||||
})
|
||||
->when(!empty($kategoriIds), function ($q) use ($kategoriIds) {
|
||||
$q->whereIn('master_kategori_directory_id', $kategoriIds);
|
||||
})
|
||||
->when($keyword, function ($q) use ($keyword) {
|
||||
$q->where(function ($sub) use ($keyword) {
|
||||
@ -1084,32 +943,21 @@ class DashboardController extends Controller
|
||||
->orWhere('no_dokumen', 'ILIKE', "%{$keyword}%");
|
||||
});
|
||||
});
|
||||
|
||||
if($akses && $akses->all_akses){
|
||||
$query;
|
||||
}else{
|
||||
$query->where('permission_file', true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
$data = $query->orderBy('entry_at', 'desc')
|
||||
->paginate($perPage);
|
||||
|
||||
$items = collect($data->items())->map(function($item){
|
||||
$item->nama_kategori = $item->kategori->nama_kategori_directory ?? $item->kategori_hukum ?? null;
|
||||
return $item;
|
||||
});
|
||||
|
||||
$kategoriList = (clone $baseQuery)->get()->map(function($item){
|
||||
if (!empty($item->kategori_hukum)) {
|
||||
return ['id' => 'hukum:' . $item->kategori_hukum, 'label' => $item->kategori_hukum];
|
||||
}
|
||||
$label = $item->kategori->nama_kategori_directory ?? $item->nama_kategori_directory ?? 'Kategori';
|
||||
$id = $item->master_kategori_directory_id ?? $label;
|
||||
return ['id' => (string) $id, 'label' => $label];
|
||||
})->unique('id')->values();
|
||||
|
||||
$payload = [
|
||||
'status' => true,
|
||||
'message' => 'Berhasil mendapatkan data',
|
||||
'data' => $items,
|
||||
'kategori_list' => $kategoriList,
|
||||
'data' => $data->items(),
|
||||
'pagination' => [
|
||||
'current_page' => $data->currentPage(),
|
||||
'next_page' => $data->hasMorePages() ? $data->currentPage() + 1 : null,
|
||||
@ -1203,33 +1051,28 @@ class DashboardController extends Controller
|
||||
$isAtasan = MappingUnitKerjaPegawai::where('statusenabled', true)->where(function($q){
|
||||
$q->where('objectatasanlangsungfk', auth()->user()?->dataUser?->id)->orWhere('objectpejabatpenilaifk', auth()->user()->objectpegawaifk);
|
||||
})->exists();
|
||||
|
||||
foreach ($datas as $index => $data) {
|
||||
list($id_unit_kerja, $nama_unit_kerja) = explode('/', $data['id_unit_kerja'],2);
|
||||
list($id_sub_unit_kerja, $nama_sub_unit_kerja) = explode('/', $data['id_sub_unit_kerja'],2);
|
||||
if(isset($data['akre'])){
|
||||
$path = $data['akre'];
|
||||
}else{
|
||||
if(isset($data['master_kategori_directory_id'])){
|
||||
list($master_kategori_directory_id, $nama_kategori) = explode('/', $data['master_kategori_directory_id'],2);
|
||||
$path = "{$nama_unit_kerja}/{$nama_sub_unit_kerja}/{$nama_kategori}";
|
||||
}else{
|
||||
$path = "{$nama_unit_kerja}/{$nama_sub_unit_kerja}";
|
||||
}
|
||||
}
|
||||
list($id_unit_kerja, $nama_unit_kerja) = explode('/', $data['id_unit_kerja'],2);
|
||||
list($id_sub_unit_kerja, $nama_sub_unit_kerja) = explode('/', $data['id_sub_unit_kerja'],2);
|
||||
list($master_kategori_directory_id, $nama_kategori) = explode('/', $data['master_kategori_directory_id'],2);
|
||||
|
||||
$uploadedFile = request()->file("data.$index.file");
|
||||
if(!$uploadedFile){
|
||||
throw new \RuntimeException('File wajib diunggah pada segment ke-' . ($index+1));
|
||||
throw new \RuntimeException('File wajib diunggah pada baris ke-' . ($index+1));
|
||||
}
|
||||
if (!$uploadedFile->isValid()) {
|
||||
throw new \RuntimeException('Upload file gagal pada segment ke-' . ($index+1));
|
||||
throw new \RuntimeException('Upload file gagal pada baris ke-' . ($index+1));
|
||||
}
|
||||
if ($uploadedFile->getSize() > $maxUploadBytes) {
|
||||
throw new \RuntimeException('Ukuran file maksimal 10MB pada baris ke-' . ($index+1));
|
||||
}
|
||||
$status = $isAtasan ? 'approved' : null;
|
||||
|
||||
$payload = [
|
||||
'id_unit_kerja' => $id_unit_kerja,
|
||||
'id_sub_unit_kerja' => $id_sub_unit_kerja,
|
||||
'master_kategori_directory_id' => $master_kategori_directory_id ?? null,
|
||||
'master_kategori_directory_id' => $master_kategori_directory_id,
|
||||
'pegawai_id_entry' => auth()->user()->dataUser->id ?? 1,
|
||||
'pegawai_nama_entry' => auth()->user()->dataUser->namalengkap ?? null,
|
||||
'tanggal_terbit' => $data['date_active'] ?? null,
|
||||
@ -1239,12 +1082,10 @@ class DashboardController extends Controller
|
||||
'permission_file' => ($data['is_permission'] ?? null) == "1",
|
||||
'status_action' => $status,
|
||||
'action_by' => $status && $status === "approved" ? auth()->user()->objectpegawaifk : null,
|
||||
'action_at' => $status && $status === "approved" ? now() : null,
|
||||
'is_akre' => isset($data['akre']),
|
||||
'kategori_hukum' => isset($data['kategori_hukum']) ? $data['kategori_hukum'] : null
|
||||
'action_at' => $status && $status === "approved" ? now() : null
|
||||
];
|
||||
$fd = FileDirectory::create($payload);
|
||||
|
||||
$path = "{$nama_unit_kerja}/{$nama_sub_unit_kerja}/{$nama_kategori}";
|
||||
$disk = Storage::disk('s3');
|
||||
$imageName = $this->buildStoredFileName(
|
||||
$fd->nama_dokumen ?? null,
|
||||
@ -1260,6 +1101,7 @@ class DashboardController extends Controller
|
||||
$fd->update([
|
||||
'file' => $path . '/' . $imageName
|
||||
]);
|
||||
|
||||
if(!$isAtasan){
|
||||
$uploaderName = auth()->user()?->dataUser?->namalengkap ?? 'Pengguna';
|
||||
$docNumber = $fd->no_dokumen ? 'nomor '. $fd->no_dokumen : $imageName;
|
||||
@ -1293,7 +1135,6 @@ class DashboardController extends Controller
|
||||
'status_action' => $isAtasan ? 'approved' : null
|
||||
], 200);
|
||||
} catch (\Throwable $th) {
|
||||
// dd($th);
|
||||
DB::connection('dbDirectory')->rollback();
|
||||
return response()->json([
|
||||
'status' => false,
|
||||
@ -1339,13 +1180,9 @@ class DashboardController extends Controller
|
||||
abort(404, 'PDF Tidak ditemukan');
|
||||
}
|
||||
$user = auth()->user()->dataUser;
|
||||
$mapping = null;
|
||||
if($user){
|
||||
$mapping = MappingUnitKerjaPegawai::where('statusenabled', true)
|
||||
$mapping = MappingUnitKerjaPegawai::where('statusenabled', true)
|
||||
->where('objectpegawaifk', $user->id)->where('isprimary', true)
|
||||
->first();
|
||||
|
||||
|
||||
$payloadLog = [
|
||||
'file_directory_id' => $fileDirectoryId,
|
||||
'pegawai_id_entry' => auth()->user()->dataUser->id,
|
||||
@ -1360,7 +1197,7 @@ class DashboardController extends Controller
|
||||
'id_sub_unit_kerja' => $mapping ? $mapping->objectsubunitkerjapegawaifk : null,
|
||||
];
|
||||
LogActivity::create($payloadLog);
|
||||
}
|
||||
|
||||
|
||||
$fileInfo = get_file_s3($data->file);
|
||||
if (!$fileInfo || empty($fileInfo['file'])) {
|
||||
@ -1538,8 +1375,6 @@ class DashboardController extends Controller
|
||||
$keyword = strtolower(request('keyword', ''));
|
||||
// $authUnit = auth()->user()->masterPersetujuan->details->pluck('unit_pegawai_id')->unique()->toArray();
|
||||
$user = auth()->user()->dataUser;
|
||||
$unitIds = [];
|
||||
if($user){
|
||||
$mapping = MappingUnitKerjaPegawai::where('statusenabled', true)
|
||||
->where('objectpegawaifk', $user->id)
|
||||
->get(['objectunitkerjapegawaifk', 'objectsubunitkerjapegawaifk']);
|
||||
@ -1548,7 +1383,6 @@ class DashboardController extends Controller
|
||||
->unique()
|
||||
->values()
|
||||
->all();
|
||||
}
|
||||
$result = $this->buildRecapData($unitIds, $keyword);
|
||||
// paginate manually
|
||||
$total = count($result);
|
||||
@ -1578,18 +1412,10 @@ class DashboardController extends Controller
|
||||
private function buildRecapData(array $unitIds, string $keyword = ''): array
|
||||
{
|
||||
$rows = FileDirectory::where('statusenabled', true)
|
||||
->where(function ($q) {
|
||||
$q->whereNull('tgl_expired')
|
||||
->orWhereDate('tgl_expired', '>=', now()->toDateString());
|
||||
})
|
||||
->whereNotNull('status_action')->where('status_action', 'approved');
|
||||
if(in_array(22, $unitIds)){
|
||||
$rows = $rows->pluck('file');
|
||||
}elseif(auth()->user()->username === "admin.turt"){
|
||||
$rows = $rows->pluck('file');
|
||||
}else{
|
||||
$rows = $rows->whereIn('id_unit_kerja', $unitIds)->pluck('file');
|
||||
}
|
||||
->whereNotNull('status_action')
|
||||
->whereIn('id_unit_kerja', $unitIds)
|
||||
->pluck('file');
|
||||
|
||||
$grouped = [];
|
||||
foreach ($rows as $path) {
|
||||
$parts = array_values(array_filter(explode('/', $path)));
|
||||
@ -1684,7 +1510,7 @@ class DashboardController extends Controller
|
||||
'pegawai_nama_entry' => $item->pegawai_nama_entry,
|
||||
'part' => $dataSlice[0],
|
||||
'folder' => $dataSlice[2],
|
||||
'fileName' => isset($dataSlice[3]) ? $dataSlice[3] : null,
|
||||
'fileName' =>$dataSlice[3],
|
||||
'file' => $item->file,
|
||||
'nama_dokumen' => $item->nama_dokumen ?? '-',
|
||||
'tgl_expired' => $item->tgl_expired,
|
||||
@ -1692,10 +1518,7 @@ class DashboardController extends Controller
|
||||
'entry_at' => $item->entry_at,
|
||||
'tanggal_terbit' => $item->tanggal_terbit,
|
||||
'permission_file' => $item->permission_file,
|
||||
'status_action' => $item->status_action,
|
||||
'id_unit_kerja' => $item->id_unit_kerja,
|
||||
'id_sub_unit_kerja' => $item->id_sub_unit_kerja,
|
||||
'master_kategori_directory_id' => $item->master_kategori_directory_id
|
||||
'status_action' => $item->status_action
|
||||
];
|
||||
});
|
||||
return response()->json([
|
||||
@ -2036,7 +1859,7 @@ class DashboardController extends Controller
|
||||
$start = request('start_date');
|
||||
$end = request('end_date');
|
||||
$isHistory = filter_var(request('history'), FILTER_VALIDATE_BOOLEAN);
|
||||
$query = FileDirectory::with('kategori')->where('statusenabled', true)
|
||||
$query = FileDirectory::where('statusenabled', true)
|
||||
->where('pegawai_id_entry', auth()->user()->objectpegawaifk)
|
||||
->when($isHistory, function($q){
|
||||
$q->where('status_action', 'approved');
|
||||
@ -2059,6 +1882,7 @@ class DashboardController extends Controller
|
||||
if($end){
|
||||
$query->whereDate('entry_at','<=',$end);
|
||||
}
|
||||
|
||||
$paginated = $query->paginate($perPage);
|
||||
$data = $paginated->getCollection()->map(function($item){
|
||||
$dataSlice = array_values(array_filter(explode('/', $item->file)));
|
||||
@ -2067,7 +1891,7 @@ class DashboardController extends Controller
|
||||
'pegawai_nama_entry' => $item->pegawai_nama_entry,
|
||||
'part' => $dataSlice[0],
|
||||
'folder' => $dataSlice[2],
|
||||
'fileName' => isset($dataSlice[3]) ? $dataSlice[3] : null,
|
||||
'fileName' =>$dataSlice[3],
|
||||
'file' => $item->file,
|
||||
'no_dokumen' => $item->no_dokumen,
|
||||
'nama_dokumen' => $item->nama_dokumen,
|
||||
@ -2079,12 +1903,7 @@ class DashboardController extends Controller
|
||||
'revision' => $item->revision,
|
||||
'id_unit_kerja' => $item->id_unit_kerja,
|
||||
'id_sub_unit_kerja' => $item->id_sub_unit_kerja,
|
||||
'master_kategori_directory_id' => $item->master_kategori_directory_id,
|
||||
'is_akre' => $item->is_akre,
|
||||
'kategori_hukum' => $item->kategori_hukum,
|
||||
'name_kategori' => $item->kategori_hukum ?? $item->kategori?->nama_kategori_directory ?? null,
|
||||
'name_unit' => $item->unit?->name ?? null,
|
||||
'unit_kerja_name' => $item->unit?->name ?? null
|
||||
'master_kategori_directory_id' => $item->master_kategori_directory_id
|
||||
];
|
||||
});
|
||||
return response()->json([
|
||||
@ -2284,8 +2103,6 @@ class DashboardController extends Controller
|
||||
'id_unit_kerja' => $data ? $data->id_unit_kerja : null,
|
||||
'id_sub_unit_kerja' => $data ? $data->id_sub_unit_kerja : null,
|
||||
'action_type' => 'Revisi Dokumen',
|
||||
'is_akre' => $data->is_akre ?? null,
|
||||
'kategori_hukum' => $data->kategori_hukum ?? null
|
||||
];
|
||||
LogActivity::create($payloadLog);
|
||||
|
||||
@ -2423,292 +2240,4 @@ class DashboardController extends Controller
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
public function dataAkreditasi(){
|
||||
$katDok = MasterKategori::where('statusenabled', true)
|
||||
->select('master_kategori_directory_id', 'nama_kategori_directory')
|
||||
->get();
|
||||
$data = [
|
||||
'title' => 'Akreditasi',
|
||||
'katDok' => $katDok
|
||||
];
|
||||
return view('dataAkreditasi.index', $data);
|
||||
}
|
||||
|
||||
public function dataTableAkreditasi(Request $request)
|
||||
{
|
||||
$keyword = $request->query('keyword');
|
||||
$perPage = (int) $request->query('per_page', 10);
|
||||
$query = FileDirectory::where('statusenabled', true)
|
||||
->where('status_action', 'approved')
|
||||
->where('is_akre', true);
|
||||
|
||||
// Logic Pencarian
|
||||
$query->when($keyword, function ($q) use ($keyword) {
|
||||
$q->where(function ($sub) use ($keyword) {
|
||||
$sub->where('nama_dokumen', 'ILIKE', "%{$keyword}%")
|
||||
->orWhere('no_dokumen', 'ILIKE', "%{$keyword}%")
|
||||
->orWhere('file', 'ILIKE', "%{$keyword}%"); // Cari juga berdasarkan nama file di path
|
||||
});
|
||||
});
|
||||
$data = $query->orderBy('entry_at', 'desc')->paginate($perPage);
|
||||
|
||||
return response()->json([
|
||||
'status' => true,
|
||||
'message' => 'Berhasil mendapatkan data',
|
||||
'data' => $data->items(),
|
||||
'pagination' => [
|
||||
'current_page' => $data->currentPage(),
|
||||
'total' => $data->total(),
|
||||
'per_page' => $data->perPage(),
|
||||
'last_page' => $data->lastPage(),
|
||||
'has_more' => $data->hasMorePages(),
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
public function expDokumen(){
|
||||
$katDok = MasterKategori::where('statusenabled', true)->select('master_kategori_directory_id', 'nama_kategori_directory')->get();
|
||||
$authMapping = auth()->user()?->dataUser?->mappingUnitKerjaPegawai[0];
|
||||
$authUnitKerja = $authMapping->objectunitkerjapegawaifk ?? null;
|
||||
$authSubUnitKerja = $authMapping->objectsubunitkerjapegawaifk ?? null;
|
||||
$data = [
|
||||
'title' => 'Dashboard',
|
||||
'katDok' => $katDok,
|
||||
'authUnitKerja' => $authUnitKerja,
|
||||
'authSubUnitKerja' => $authSubUnitKerja,
|
||||
];
|
||||
return view('expDokumen.index', $data);
|
||||
}
|
||||
|
||||
public function dataUnitExp(){
|
||||
$perPage = (int) request('per_page', 10);
|
||||
// $authUnitId = auth()->user()->dataUser?->mappingUnitKerjaPegawai[0]?->objectunitkerjapegawaifk;
|
||||
$userId = auth()->user()->dataUser->id ?? 937;
|
||||
$mapping = MappingUnitKerjaPegawai::where('statusenabled', true)
|
||||
->where('objectpegawaifk', $userId)
|
||||
->get(['objectunitkerjapegawaifk']);
|
||||
$unitIds = $mapping->pluck('objectunitkerjapegawaifk')
|
||||
->filter() // buang null
|
||||
->unique()
|
||||
->values()
|
||||
->toArray();
|
||||
$keyword = request('keyword');
|
||||
$kategori = request('kategori');
|
||||
$kategoriHeader = request('kategori_header');
|
||||
$unitFilter = request('unit');
|
||||
$kategoriValues = is_array($kategori)
|
||||
? array_values(array_filter($kategori))
|
||||
: array_values(array_filter(explode(',', (string) $kategori)));
|
||||
$kategoriHeaderValues = is_array($kategoriHeader)
|
||||
? array_values(array_filter($kategoriHeader))
|
||||
: array_values(array_filter(explode(',', (string) $kategoriHeader)));
|
||||
$allKategoriValues = array_values(array_filter(array_merge($kategoriValues, $kategoriHeaderValues)));
|
||||
$kategoriTypes = [];
|
||||
$kategoriIds = [];
|
||||
$kategoriHukumValues = [];
|
||||
foreach ($allKategoriValues as $val) {
|
||||
$lower = strtolower(trim((string) $val));
|
||||
if (str_starts_with($lower, 'hukum:')) {
|
||||
$hukumVal = trim(substr((string) $val, strlen('hukum:')));
|
||||
if ($hukumVal !== '') {
|
||||
$kategoriHukumValues[] = $hukumVal;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (in_array($lower, ['akreditasi', 'akre'], true)) {
|
||||
$kategoriTypes[] = 'akreditasi';
|
||||
continue;
|
||||
}
|
||||
if ($lower === 'hukum') {
|
||||
$kategoriTypes[] = 'hukum';
|
||||
continue;
|
||||
}
|
||||
if ($lower === 'lainnya') {
|
||||
$kategoriTypes[] = 'lainnya';
|
||||
continue;
|
||||
}
|
||||
$kategoriIds[] = $val;
|
||||
}
|
||||
$baseQuery = FileDirectory::with('kategori')
|
||||
->when(!empty($unitFilter), function($q) use($unitFilter){
|
||||
$q->whereIn('id_unit_kerja', $unitFilter);
|
||||
})
|
||||
->whereNotNull('tgl_expired')
|
||||
->whereDate('tgl_expired', '<', now()->toDateString())
|
||||
->where('statusenabled', true)
|
||||
->where('status_action', 'approved');
|
||||
|
||||
if(in_array(22, $unitIds)){
|
||||
}elseif(auth()->user()->username === "admin.turt"){
|
||||
|
||||
}else{
|
||||
$baseQuery = $baseQuery->whereIn('id_unit_kerja', $unitIds);
|
||||
}
|
||||
|
||||
$query = (clone $baseQuery)
|
||||
->when(!empty($kategoriIds) || !empty($kategoriTypes) || !empty($kategoriHukumValues), function ($q) use ($kategoriIds, $kategoriTypes, $kategoriHukumValues) {
|
||||
$q->where(function ($sub) use ($kategoriIds, $kategoriTypes, $kategoriHukumValues) {
|
||||
$hasClause = false;
|
||||
if (!empty($kategoriIds)) {
|
||||
$sub->whereIn('master_kategori_directory_id', $kategoriIds);
|
||||
$hasClause = true;
|
||||
}
|
||||
if (!empty($kategoriHukumValues)) {
|
||||
$hasClause ? $sub->orWhereIn('kategori_hukum', $kategoriHukumValues) : $sub->whereIn('kategori_hukum', $kategoriHukumValues);
|
||||
$hasClause = true;
|
||||
}
|
||||
if (in_array('akreditasi', $kategoriTypes, true)) {
|
||||
$sub->where('is_akre', true);
|
||||
$hasClause = true;
|
||||
}
|
||||
if (in_array('hukum', $kategoriTypes, true)) {
|
||||
$hasClause ? $sub->orWhereNotNull('kategori_hukum') : $sub->whereNotNull('kategori_hukum');
|
||||
$hasClause = true;
|
||||
}
|
||||
if (in_array('lainnya', $kategoriTypes, true)) {
|
||||
$hasClause ? $sub->orWhereNotNull('master_kategori_directory_id') : $sub->whereNotNull('master_kategori_directory_id');
|
||||
}
|
||||
});
|
||||
})
|
||||
->when($keyword, function ($q) use ($keyword) {
|
||||
$q->where(function ($sub) use ($keyword) {
|
||||
$sub->where('nama_dokumen', 'ILIKE', "%{$keyword}%")
|
||||
->orWhere('no_dokumen', 'ILIKE', "%{$keyword}%");
|
||||
});
|
||||
});
|
||||
|
||||
$data = $query->orderBy('entry_at', 'desc')
|
||||
->paginate($perPage);
|
||||
|
||||
$items = collect($data->items())->map(function($item){
|
||||
$item->nama_kategori = $item->kategori->nama_kategori_directory ?? $item->kategori_hukum ?? null;
|
||||
return $item;
|
||||
});
|
||||
$kategoriList = (clone $baseQuery)->get()->map(function($item){
|
||||
if (!empty($item->kategori_hukum)) {
|
||||
return ['id' => 'hukum:' . $item->kategori_hukum, 'label' => $item->kategori_hukum];
|
||||
}
|
||||
$label = $item->kategori->nama_kategori_directory ?? $item->nama_kategori_directory ?? 'Kategori';
|
||||
$id = $item->master_kategori_directory_id ?? $label;
|
||||
return ['id' => (string) $id, 'label' => $label];
|
||||
})->unique('id')->values();
|
||||
|
||||
$payload = [
|
||||
'status' => true,
|
||||
'message' => 'Berhasil mendapatkan data',
|
||||
'data' => $items,
|
||||
'kategori_list' => $kategoriList,
|
||||
'pagination' => [
|
||||
'current_page' => $data->currentPage(),
|
||||
'next_page' => $data->hasMorePages() ? $data->currentPage() + 1 : null,
|
||||
'has_more' => $data->hasMorePages(),
|
||||
'last_page' => $data->lastPage(),
|
||||
'per_page' => $data->perPage(),
|
||||
'total' => $data->total(),
|
||||
]
|
||||
];
|
||||
return response()->json($payload);
|
||||
}
|
||||
|
||||
public function recapDataExp(){
|
||||
try {
|
||||
$perPage = (int) request('per_page', 10);
|
||||
$page = max(1, (int) request('page', 1));
|
||||
$keyword = strtolower(request('keyword', ''));
|
||||
// $authUnit = auth()->user()->masterPersetujuan->details->pluck('unit_pegawai_id')->unique()->toArray();
|
||||
$user = auth()->user()->dataUser;
|
||||
$unitIds = [];
|
||||
if($user){
|
||||
$mapping = MappingUnitKerjaPegawai::where('statusenabled', true)
|
||||
->where('objectpegawaifk', $user->id)
|
||||
->get(['objectunitkerjapegawaifk', 'objectsubunitkerjapegawaifk']);
|
||||
$unitIds = $mapping->pluck('objectunitkerjapegawaifk')
|
||||
->filter() // buang null
|
||||
->unique()
|
||||
->values()
|
||||
->all();
|
||||
}
|
||||
$result = $this->buildRecapDataExp($unitIds, $keyword);
|
||||
// paginate manually
|
||||
$total = count($result);
|
||||
$chunks = array_chunk($result, $perPage);
|
||||
$currentData = $chunks[$page-1] ?? [];
|
||||
|
||||
return response()->json([
|
||||
'status' => true,
|
||||
'data' => $currentData,
|
||||
'message' => 'Berhasil mendapatkan data',
|
||||
'pagination' => [
|
||||
'current_page' => $page,
|
||||
'per_page' => $perPage,
|
||||
'total' => $total,
|
||||
'last_page' => max(1, ceil($total / $perPage)),
|
||||
'has_more' => $page < max(1, ceil($total / $perPage)),
|
||||
]
|
||||
]);
|
||||
} catch (\Throwable $th) {
|
||||
return response()->json([
|
||||
'status' => false,
|
||||
'message' => 'Gagal! mendapatkan data'
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
private function buildRecapDataExp(array $unitIds, string $keyword = ''): array
|
||||
{
|
||||
$rows = FileDirectory::where('statusenabled', true)
|
||||
->whereNotNull('tgl_expired')
|
||||
->whereDate('tgl_expired', '<', now()->toDateString())
|
||||
->whereNotNull('status_action')->where('status_action', 'approved');
|
||||
if(in_array(22, $unitIds)){
|
||||
$rows = $rows->pluck('file');
|
||||
}elseif(auth()->user()->username === "admin.turt"){
|
||||
$rows = $rows->pluck('file');
|
||||
}else{
|
||||
$rows = $rows->whereIn('id_unit_kerja', $unitIds)->pluck('file');
|
||||
}
|
||||
$grouped = [];
|
||||
foreach ($rows as $path) {
|
||||
$parts = array_values(array_filter(explode('/', $path)));
|
||||
if (count($parts) < 4) {
|
||||
continue;
|
||||
}
|
||||
$unit = $parts[0];
|
||||
$folder = $parts[2];
|
||||
|
||||
if ($keyword) {
|
||||
$hit = str_contains(strtolower($unit), $keyword) || str_contains(strtolower($folder), $keyword);
|
||||
if (!$hit) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!isset($grouped[$unit])) {
|
||||
$grouped[$unit] = [];
|
||||
}
|
||||
if (!isset($grouped[$unit][$folder])) {
|
||||
$grouped[$unit][$folder] = 0;
|
||||
}
|
||||
$grouped[$unit][$folder]++;
|
||||
}
|
||||
|
||||
$result = [];
|
||||
foreach ($grouped as $unitName => $folders) {
|
||||
$data = [];
|
||||
foreach ($folders as $folder => $count) {
|
||||
$data[] = [
|
||||
'folder' => $folder,
|
||||
'count' => $count,
|
||||
];
|
||||
}
|
||||
usort($data, fn($a, $b) => $b['count'] <=> $a['count']);
|
||||
$result[] = [
|
||||
'unit' => $unitName,
|
||||
'data' => $data,
|
||||
];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -7,7 +7,6 @@ use App\Models\MappingUnitKerjaPegawai;
|
||||
use App\Models\FileDirectory;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class LogActivityController extends Controller
|
||||
{
|
||||
@ -23,33 +22,23 @@ class LogActivityController extends Controller
|
||||
$keyword = request('keyword');
|
||||
$start = request('start_date');
|
||||
$end = request('end_date');
|
||||
$mapping = MappingUnitKerjaPegawai::where('statusenabled', true);
|
||||
if(!Auth::guard('admin')->check()){
|
||||
$mapping->where('objectpegawaifk', auth()->user()->dataUser->id);
|
||||
}else{
|
||||
$mapping->where('objectpegawaifk', 937);
|
||||
}
|
||||
$mapping->get(['objectunitkerjapegawaifk', 'objectsubunitkerjapegawaifk']);
|
||||
$mapping = MappingUnitKerjaPegawai::where('statusenabled', true)
|
||||
->where('objectpegawaifk', auth()->user()->dataUser->id)
|
||||
->get(['objectunitkerjapegawaifk', 'objectsubunitkerjapegawaifk']);
|
||||
$unitIds = $mapping->pluck('objectunitkerjapegawaifk')
|
||||
->filter() // buang null
|
||||
->unique()
|
||||
->values()
|
||||
->all();
|
||||
->filter() // buang null
|
||||
->unique()
|
||||
->values()
|
||||
->all();
|
||||
$query = FileDirectory::withCount(['viewLogs as total_views' => function($q){
|
||||
$q->select(DB::raw('COUNT(DISTINCT pegawai_id_entry)'));
|
||||
}])->withCount(['downloadLogs as total_download' => function($q){
|
||||
$q->select(DB::raw('COUNT(DISTINCT pegawai_id_entry)'));
|
||||
}])
|
||||
->where('statusenabled', true)
|
||||
->where('status_action', 'approved');
|
||||
if (
|
||||
in_array(22, $unitIds) ||
|
||||
(Auth::guard('admin')->check() && Auth::guard('admin')->user()->id == 300)
|
||||
) {
|
||||
}else{
|
||||
$query = $query->whereIn('id_unit_kerja', $unitIds);
|
||||
}
|
||||
$query = $query->orderBy('entry_at','desc');
|
||||
->where('status_action', 'approved')
|
||||
->whereIn('id_unit_kerja', $unitIds)
|
||||
->orderBy('entry_at','desc');
|
||||
|
||||
if($keyword){
|
||||
$query->where(function($q) use ($keyword){
|
||||
@ -104,14 +93,12 @@ class LogActivityController extends Controller
|
||||
$query = LogActivity::select(
|
||||
'pegawai_id_entry',
|
||||
'pegawai_nama_entry',
|
||||
DB::raw("SUM(CASE WHEN action_type = 'Membuka Dokumen' THEN 1 ELSE 0 END) as total_open"),
|
||||
// Menghitung hanya yang Download Dokumen
|
||||
DB::raw("SUM(CASE WHEN action_type = 'Download Dokumen' THEN 1 ELSE 0 END) as total_download"),
|
||||
DB::raw('COUNT(*) as total_open'),
|
||||
DB::raw('MAX(entry_at) as last_open')
|
||||
)
|
||||
->where('file_directory_id', $fileDirectoryId)
|
||||
->where('statusenabled', true)
|
||||
->whereIn('action_type', ['Membuka Dokumen', 'Download Dokumen'])
|
||||
->where('action_type', 'Membuka Dokumen')
|
||||
->groupBy('pegawai_id_entry', 'pegawai_nama_entry')
|
||||
->orderByDesc('total_open');
|
||||
|
||||
@ -134,5 +121,5 @@ class LogActivityController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -4,8 +4,6 @@ namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use App\Models\LogActivity;
|
||||
use App\Models\UnitKerja;
|
||||
use App\Models\MasterKategori;
|
||||
|
||||
class FileDirectory extends Model
|
||||
{
|
||||
@ -14,7 +12,6 @@ class FileDirectory extends Model
|
||||
public $timestamps = false;
|
||||
protected $primaryKey = 'file_directory_id';
|
||||
protected $guarded = ['file_directory_id'];
|
||||
protected $with = ['unit'];
|
||||
|
||||
public function viewLogs()
|
||||
{
|
||||
@ -29,16 +26,4 @@ class FileDirectory extends Model
|
||||
->where('action_type', 'Download Dokumen');
|
||||
}
|
||||
|
||||
public function kategori(){
|
||||
return $this->belongsTo(MasterKategori::class, 'master_kategori_directory_id', 'master_kategori_directory_id');
|
||||
}
|
||||
|
||||
public function unit(){
|
||||
// Each file belongs to exactly one unit; skip the subUnitKerja eager load from UnitKerja.
|
||||
return $this->belongsTo(UnitKerja::class, 'id_unit_kerja', 'id')->select('id', 'name')
|
||||
->without('subUnitKerja');
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -1,15 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
|
||||
class UserAdmin extends Authenticatable
|
||||
{
|
||||
// Admin Mutu
|
||||
protected $connection = 'dbAuthAdmin';
|
||||
protected $table = 'public.users';
|
||||
public $timestamps = false;
|
||||
protected $primaryKey = "id";
|
||||
protected $guarded = ['id'];
|
||||
}
|
||||
@ -40,10 +40,6 @@ return [
|
||||
'driver' => 'session',
|
||||
'provider' => 'users',
|
||||
],
|
||||
'admin' => [
|
||||
'driver' => 'session',
|
||||
'provider' => 'admins',
|
||||
],
|
||||
],
|
||||
|
||||
/*
|
||||
@ -68,10 +64,6 @@ return [
|
||||
'driver' => 'eloquent',
|
||||
'model' => env('AUTH_MODEL', App\Models\User::class),
|
||||
],
|
||||
'admins' => [
|
||||
'driver' => 'eloquent',
|
||||
'model' => env('AUTH_MODEL', App\Models\UserAdmin::class),
|
||||
],
|
||||
|
||||
// 'users' => [
|
||||
// 'driver' => 'database',
|
||||
|
||||
@ -129,26 +129,6 @@ return [
|
||||
'timezone' => env('APP_TIMEZONE', 'utc' ),
|
||||
],
|
||||
|
||||
'dbAuthAdmin' => [
|
||||
'driver' => 'pgsql',
|
||||
'url' => env('DB_URL'),
|
||||
'host' => env('DB_HOST_AUTH_ADMIN', '127.0.0.1'),
|
||||
'port' => env('DB_PORT_AUTH_ADMIN', '3306'),
|
||||
'database' => env('DB_DATABASE_AUTH_ADMIN', 'laravel'),
|
||||
'username' => env('DB_USERNAME_AUTH_ADMIN', 'root'),
|
||||
'password' => env('DB_PASSWORD_AUTH_ADMIN', ''),
|
||||
'charset' => env('DB_CHARSET', 'utf8'),
|
||||
'prefix' => '',
|
||||
'prefix_indexes' => true,
|
||||
'search_path' => 'public',
|
||||
'sslmode' => 'prefer',
|
||||
'prefix' => '',
|
||||
'prefix_indexes' => true,
|
||||
'search_path' => 'public',
|
||||
'sslmode' => 'prefer',
|
||||
'timezone' => env('APP_TIMEZONE', 'utc' ),
|
||||
],
|
||||
|
||||
],
|
||||
|
||||
/*
|
||||
|
||||
@ -177,7 +177,7 @@ function addForm(){
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Unit <span class="text-danger">*</span></label>
|
||||
<select class="form-control"
|
||||
name="data[${colCount}][id_unit_kerja]"
|
||||
@ -186,7 +186,7 @@ function addForm(){
|
||||
<option value="" disable>Select Choose</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Sub Unit <span class="text-danger">*</span></label>
|
||||
<select class="form-control"
|
||||
name="data[${colCount}][id_sub_unit_kerja]"
|
||||
@ -196,7 +196,7 @@ function addForm(){
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Kategori Dokumen</label>
|
||||
<label class="form-label fw-semibold">Kategori Dokumen <span class="text-danger">*</span></label>
|
||||
<select class="form-control"
|
||||
name="data[${colCount}][master_kategori_directory_id]"
|
||||
id="select_kategori_${colCount}"
|
||||
@ -238,7 +238,7 @@ function addForm(){
|
||||
id="perm_yes_${colCount}"
|
||||
value="1"
|
||||
required>
|
||||
<label class="form-check-label" for="perm_yes_${colCount}">Ya</label>
|
||||
<label class="form-check-label" for="perm_yes_${colCount}">Iya</label>
|
||||
</div>
|
||||
|
||||
<div class="form-check mt-1">
|
||||
|
||||
@ -631,5 +631,5 @@ document.addEventListener('click', function(e){
|
||||
function isPublic(permissionVal){
|
||||
if(permissionVal === null || permissionVal === undefined) return false;
|
||||
const val = String(permissionVal).toLowerCase();
|
||||
return val === '1' || val === 'true' || val === 'ya' || val === 'yes';
|
||||
return val === '1' || val === 'true' || val === 'iya' || val === 'yes';
|
||||
}
|
||||
|
||||
@ -116,13 +116,8 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
data-no_dokumen="${item.no_dokumen || '-'}"
|
||||
data-tanggal_terbit="${item.tanggal_terbit || '-'}"
|
||||
data-permission_file="${item.permission_file || '-'}">${item.nama_dokumen}</a></td>
|
||||
${item.is_akre ? `<td colspan="2" class="text-center">Dokumen akreditasi</td>` :
|
||||
`
|
||||
<td>${item.name_kategori || '-'}</td>
|
||||
<td>${item.name_unit || '-'}</td>
|
||||
`
|
||||
}
|
||||
|
||||
<td>${item.folder || '-'}</td>
|
||||
<td>${item.part || '-'}</td>
|
||||
<td class="text-nowrap">${tanggalTerbit}</td>
|
||||
<td class="text-nowrap">${tanggalExp}</td>
|
||||
<td class="text-nowrap">${tanggal}</td>
|
||||
@ -368,51 +363,6 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
|
||||
}
|
||||
|
||||
function byId(id){
|
||||
return document.getElementById(id);
|
||||
}
|
||||
|
||||
function setInputValue(el, value){
|
||||
if (!el) return;
|
||||
el.value = value ?? '';
|
||||
}
|
||||
|
||||
function setTextValue(el, value){
|
||||
if (!el) return;
|
||||
el.textContent = value || '';
|
||||
}
|
||||
|
||||
function setChecked(el, value){
|
||||
if (!el) return;
|
||||
el.checked = !!value;
|
||||
}
|
||||
|
||||
function setSelectValue(selectEl, value, label){
|
||||
if (!selectEl) return;
|
||||
if (value === undefined || value === null || value === '') {
|
||||
selectEl.value = '';
|
||||
return;
|
||||
}
|
||||
const exists = Array.from(selectEl.options).some(opt => opt.value === value);
|
||||
if (!exists) {
|
||||
selectEl.append(new Option(label || value, value, true, true));
|
||||
}
|
||||
selectEl.value = value;
|
||||
}
|
||||
|
||||
function triggerSelect2(selectEl){
|
||||
if (window.$ && $.fn.select2) $(selectEl).trigger('change');
|
||||
}
|
||||
|
||||
function arrayFilterEmpty(arr){
|
||||
return (arr || []).filter((val) => val !== null && val !== undefined && String(val).trim() !== '');
|
||||
}
|
||||
|
||||
function initSelect2($el, options){
|
||||
if (!$el || !$el.length || !window.$ || !$.fn.select2) return;
|
||||
$el.select2(options);
|
||||
}
|
||||
|
||||
function initEditSelects(){
|
||||
if (editUnitSelect.length) {
|
||||
editUnitSelect.select2({
|
||||
@ -430,7 +380,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
processResults: function (data) {
|
||||
return {
|
||||
results: (data?.data || []).map(item => ({
|
||||
id: String(item.id),
|
||||
id: `${item.id}/${item.name}`,
|
||||
text: item.name
|
||||
}))
|
||||
};
|
||||
@ -453,38 +403,8 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
editUnitSelect.on('change', function(){
|
||||
const val = $(this).val();
|
||||
if (!val) return;
|
||||
loadEditSubUnit(String(val), null, null);
|
||||
});
|
||||
}
|
||||
|
||||
let akreData = [];
|
||||
let akreLoaded = false;
|
||||
let akreFlat = [];
|
||||
|
||||
function initEditExtraSelects(){
|
||||
const akreSelect = byId('edit_akre_select');
|
||||
if (akreSelect) {
|
||||
loadAkreData().then(() => {
|
||||
fillAkreSelect(akreSelect);
|
||||
initSelect2($(akreSelect), {
|
||||
dropdownParent: $('#modalEditPengajuanFile'),
|
||||
placeholder: 'Pilih Instrumen',
|
||||
allowClear: true
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const editKat = $('#edit_kategori');
|
||||
const editHukum = $('#edit_kategori_hukum');
|
||||
initSelect2(editKat, {
|
||||
dropdownParent: $('#modalEditPengajuanFile'),
|
||||
placeholder: 'Pilih Kategori',
|
||||
allowClear: true
|
||||
});
|
||||
initSelect2(editHukum, {
|
||||
dropdownParent: $('#modalEditPengajuanFile'),
|
||||
placeholder: 'Pilih Kategori Hukum',
|
||||
allowClear: true
|
||||
const unitId = String(val).split('/')[0];
|
||||
loadEditSubUnit(unitId, null, null);
|
||||
});
|
||||
}
|
||||
|
||||
@ -497,13 +417,13 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
success: function(response) {
|
||||
if (response?.data) {
|
||||
response.data.forEach(unit => {
|
||||
const optVal = String(unit.id);
|
||||
const optVal = `${unit.id}/${unit.name}`;
|
||||
const isSelected = selectedSubId && String(unit.id) === String(selectedSubId);
|
||||
const option = new Option(unit.name, optVal, false, isSelected);
|
||||
editSubUnitSelect.append(option);
|
||||
});
|
||||
if (selectedSubId && selectedSubName && editSubUnitSelect.find(`option[value="${selectedSubId}"]`).length === 0) {
|
||||
editSubUnitSelect.append(new Option(selectedSubName, String(selectedSubId), true, true));
|
||||
if (selectedSubId && selectedSubName && editSubUnitSelect.find(`option[value="${selectedSubId}/${selectedSubName}"]`).length === 0) {
|
||||
editSubUnitSelect.append(new Option(selectedSubName, `${selectedSubId}/${selectedSubName}`, true, true));
|
||||
}
|
||||
editSubUnitSelect.trigger('change');
|
||||
}
|
||||
@ -511,85 +431,69 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
});
|
||||
}
|
||||
|
||||
function setEditAkreValue(value){
|
||||
const akreEl = byId('edit_akre_select');
|
||||
if (!akreEl) return;
|
||||
loadAkreData().then(() => {
|
||||
fillAkreSelect(akreEl);
|
||||
if (value && akreValueExists(value)) {
|
||||
setSelectValue(akreEl, value, value);
|
||||
} else {
|
||||
akreEl.value = '';
|
||||
}
|
||||
triggerSelect2(akreEl);
|
||||
});
|
||||
}
|
||||
|
||||
function setEditKategoriHukum(value){
|
||||
const hukumEl = byId('edit_kategori_hukum');
|
||||
if (!hukumEl) return;
|
||||
setSelectValue(hukumEl, value, value);
|
||||
triggerSelect2(hukumEl);
|
||||
}
|
||||
|
||||
function setEditKategoriDir(item, kategoriName){
|
||||
const katEl = byId('edit_kategori');
|
||||
const katId = item?.master_kategori_directory_id;
|
||||
if (!katEl || !katId) return;
|
||||
const match = Array.from(katEl.options).find((opt) => String(opt.value).startsWith(`${katId}/`));
|
||||
if (match) {
|
||||
katEl.value = match.value;
|
||||
} else {
|
||||
const label = kategoriName || 'Kategori';
|
||||
const katVal = `${katId}/${label}`;
|
||||
setSelectValue(katEl, katVal, label);
|
||||
}
|
||||
triggerSelect2(katEl);
|
||||
}
|
||||
|
||||
window.editFileReject = function(id){
|
||||
const item = getItemById(id);
|
||||
if (!item) {
|
||||
Swal.fire({ icon: 'error', title: 'Gagal', text: 'Data tidak ditemukan.' });
|
||||
return;
|
||||
}
|
||||
setInputValue(byId('edit_file_directory_id'), item.file_directory_id);
|
||||
setInputValue(byId('edit_no_dokumen'), item.no_dokumen);
|
||||
setInputValue(byId('edit_nama_dokumen'), item.nama_dokumen);
|
||||
setInputValue(byId('edit_tanggal_terbit'), item.tanggal_terbit);
|
||||
setInputValue(byId('edit_tgl_expired'), item.tgl_expired);
|
||||
const idEl = document.getElementById('edit_file_directory_id');
|
||||
const noEl = document.getElementById('edit_no_dokumen');
|
||||
const namaEl = document.getElementById('edit_nama_dokumen');
|
||||
const tglEl = document.getElementById('edit_tanggal_terbit');
|
||||
const tglExpiredEl = document.getElementById('edit_tgl_expired');
|
||||
const hasExpiredEl = document.getElementById('edit_has_expired');
|
||||
const currentFileEl = document.getElementById('edit_current_file');
|
||||
const permYes = document.getElementById('edit_perm_yes');
|
||||
const permNo = document.getElementById('edit_perm_no');
|
||||
const katEl = document.getElementById('edit_kategori');
|
||||
|
||||
const isPublic = item.permission_file === true || item.permission_file === 1 || item.permission_file === '1';
|
||||
setChecked(byId('edit_perm_yes'), isPublic);
|
||||
setChecked(byId('edit_perm_no'), !isPublic);
|
||||
|
||||
const hasExpired = !!item.tgl_expired;
|
||||
setChecked(byId('edit_has_expired'), hasExpired);
|
||||
syncEditExpiredField();
|
||||
|
||||
const displayName = item.fileName || (item.file ? String(item.file).split('/').pop() : '');
|
||||
setTextValue(byId('edit_current_file'), displayName ? `File saat ini: ${displayName}` : '');
|
||||
|
||||
const parts = arrayFilterEmpty((item.file || '').split('/'));
|
||||
const unitNameFromPath = parts[0] || '';
|
||||
const subNameFromPath = parts[1] || '';
|
||||
const kategoriName = parts[2] || '';
|
||||
const unitName = item.unit_kerja_name || item.name_unit || item.nama_unit_kerja || item.unit_name || item.unit_kerja || '';
|
||||
if (editUnitSelect.length && item.id_unit_kerja) {
|
||||
const unitLabel = unitName || String(item.id_unit_kerja);
|
||||
const unitVal = String(item.id_unit_kerja);
|
||||
setSelectValue(editUnitSelect[0], unitVal, unitLabel);
|
||||
triggerSelect2(editUnitSelect[0]);
|
||||
const subLabel = item.sub_unit_kerja_name || item.nama_sub_unit_kerja || item.sub_unit_name || item.sub_unit_kerja || String(item.id_sub_unit_kerja || '');
|
||||
loadEditSubUnit(String(item.id_unit_kerja), item.id_sub_unit_kerja, subLabel || null);
|
||||
if (idEl) idEl.value = item.file_directory_id || '';
|
||||
if (noEl) noEl.value = item.no_dokumen || '';
|
||||
if (namaEl) namaEl.value = item.nama_dokumen || '';
|
||||
if (tglEl) tglEl.value = item.tanggal_terbit || '';
|
||||
if (tglExpiredEl) tglExpiredEl.value = item.tgl_expired || '';
|
||||
if (permYes && permNo) {
|
||||
const isPublic = item.permission_file === true || item.permission_file === 1 || item.permission_file === '1';
|
||||
permYes.checked = isPublic;
|
||||
permNo.checked = !isPublic;
|
||||
}
|
||||
if (hasExpiredEl && tglExpiredEl) {
|
||||
const hasExpired = !!item.tgl_expired;
|
||||
hasExpiredEl.checked = hasExpired;
|
||||
syncEditExpiredField();
|
||||
}
|
||||
if (currentFileEl) {
|
||||
const displayName = item.fileName || (item.file ? String(item.file).split('/').pop() : '');
|
||||
currentFileEl.textContent = displayName ? `File saat ini: ${displayName}` : '';
|
||||
}
|
||||
|
||||
setEditKategoriDir(item, kategoriName);
|
||||
if (item.kategori_hukum) setEditKategoriHukum(item.kategori_hukum);
|
||||
const akreFromFile = parts.length > 1 ? parts.slice(0, -1).join('/') : '';
|
||||
setEditAkreValue(item.akre || akreFromFile || '');
|
||||
const parts = (item.file || '').split('/');
|
||||
const unitName = parts[0] || '';
|
||||
const subName = parts[1] || '';
|
||||
const kategoriName = parts[2] || '';
|
||||
|
||||
$("#modalEditPengajuanFile").modal('show');
|
||||
if (editUnitSelect.length && item.id_unit_kerja) {
|
||||
const unitVal = `${item.id_unit_kerja}/${unitName}`;
|
||||
editUnitSelect.append(new Option(unitName || 'Unit', unitVal, true, true)).trigger('change');
|
||||
const unitId = String(item.id_unit_kerja);
|
||||
loadEditSubUnit(unitId, item.id_sub_unit_kerja, subName);
|
||||
}
|
||||
|
||||
if (katEl && item.master_kategori_directory_id) {
|
||||
const katVal = `${item.master_kategori_directory_id}/${kategoriName}`;
|
||||
if (katEl.querySelector(`option[value="${katVal}"]`)) {
|
||||
katEl.value = katVal;
|
||||
} else {
|
||||
katEl.append(new Option(kategoriName || 'Kategori', katVal, true, true));
|
||||
katEl.value = katVal;
|
||||
}
|
||||
}
|
||||
|
||||
const modalEl = document.getElementById('modalEditPengajuanFile');
|
||||
if (modalEl) {
|
||||
$("#modalEditPengajuanFile").modal('show');
|
||||
}
|
||||
}
|
||||
|
||||
function syncEditExpiredField() {
|
||||
@ -648,7 +552,6 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
}
|
||||
|
||||
initEditSelects();
|
||||
initEditExtraSelects();
|
||||
updateTabUI();
|
||||
fetchData();
|
||||
|
||||
@ -672,124 +575,6 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
$(formCreate).find('input[type="file"]').val('');
|
||||
$(formCreate).find('.file-name').addClass('d-none').text('');
|
||||
}
|
||||
resetAkreFields(0);
|
||||
enableAkreFields(0);
|
||||
}
|
||||
|
||||
function loadAkreData(){
|
||||
if(akreLoaded) return Promise.resolve(akreData);
|
||||
return fetch('/json/akreditasi.jff')
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
akreData = Array.isArray(data) ? data : [];
|
||||
akreFlat = [];
|
||||
akreLoaded = true;
|
||||
return akreData;
|
||||
})
|
||||
.catch(() => {
|
||||
akreData = [];
|
||||
akreFlat = [];
|
||||
akreLoaded = true;
|
||||
return akreData;
|
||||
});
|
||||
}
|
||||
|
||||
function getAkreFlat(){
|
||||
if(akreFlat.length) return akreFlat;
|
||||
akreFlat = (akreData || []).flatMap(type => {
|
||||
const segments = Array.isArray(type.segment) ? type.segment : [];
|
||||
return segments.flatMap(seg => {
|
||||
const children = Array.isArray(seg.turunan) ? seg.turunan : [];
|
||||
return children.map(child => ({
|
||||
value: `${type.name}/${seg.name}/${child.name}`,
|
||||
label: `${type.name} / ${child.name}`,
|
||||
type: type.name,
|
||||
segment: seg.name,
|
||||
item: child.name
|
||||
}));
|
||||
});
|
||||
});
|
||||
return akreFlat;
|
||||
}
|
||||
|
||||
function akreValueExists(value){
|
||||
if (!value) return false;
|
||||
return getAkreFlat().some(opt => String(opt.value) === String(value));
|
||||
}
|
||||
|
||||
function fillAkreSelect(selectEl){
|
||||
if(!selectEl) return;
|
||||
selectEl.innerHTML = '<option value="">Pilih Instrumen</option>';
|
||||
getAkreFlat().forEach(optData => {
|
||||
const opt = document.createElement('option');
|
||||
opt.value = optData.value;
|
||||
opt.textContent = optData.label;
|
||||
selectEl.appendChild(opt);
|
||||
});
|
||||
}
|
||||
|
||||
function setKategoriRequired(index, isRequired){
|
||||
const katSelect = document.getElementById(`select_kategori_${index}`);
|
||||
if (!katSelect) return;
|
||||
if (isRequired) {
|
||||
katSelect.setAttribute('required', 'required');
|
||||
} else {
|
||||
katSelect.removeAttribute('required');
|
||||
}
|
||||
}
|
||||
|
||||
function resetAkreFields(index){
|
||||
const selectEl = document.getElementById(`akre_select_${index}`);
|
||||
const typeInput = document.getElementById(`akre_type_${index}`);
|
||||
const segmentInput = document.getElementById(`akre_segment_${index}`);
|
||||
const itemInput = document.getElementById(`akre_item_${index}`);
|
||||
if(selectEl){
|
||||
selectEl.value = '';
|
||||
if(window.$ && $.fn.select2) $(selectEl).val(null).trigger('change');
|
||||
}
|
||||
if(typeInput) typeInput.value = '';
|
||||
if(segmentInput) segmentInput.value = '';
|
||||
if(itemInput) itemInput.value = '';
|
||||
setKategoriRequired(index, false);
|
||||
}
|
||||
|
||||
function enableAkreFields(index){
|
||||
const selectEl = document.getElementById(`akre_select_${index}`);
|
||||
// if(selectEl){
|
||||
// selectEl.disabled = false;
|
||||
// selectEl.required = true;
|
||||
// }
|
||||
setKategoriRequired(index, false);
|
||||
loadAkreData().then(() => {
|
||||
fillAkreSelect(selectEl);
|
||||
if(window.$ && $.fn.select2){
|
||||
$(selectEl).select2({
|
||||
dropdownParent: $('#modalCreateFile'),
|
||||
placeholder: 'Pilih Instrumen',
|
||||
allowClear:true
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function initKategoriSelect2(index){
|
||||
if(!window.$ || !$.fn.select2) return;
|
||||
const katSelect = $(`#select_kategori_${index}`);
|
||||
const hukumSelect = $(`#select_kategori_hukum_${index}`);
|
||||
if(katSelect.length){
|
||||
katSelect.select2({
|
||||
dropdownParent: $('#modalCreateFile'),
|
||||
placeholder:'Pilih Kategori',
|
||||
allowClear:true
|
||||
});
|
||||
}
|
||||
if(hukumSelect.length){
|
||||
hukumSelect.select2({
|
||||
dropdownParent: $('#modalCreateFile'),
|
||||
placeholder:'Pilih Kategori Hukum',
|
||||
allowClear:true
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function selectOptionUnitKerjaV1(localCol){
|
||||
@ -857,7 +642,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Unit <span class="text-danger">*</span></label>
|
||||
<select class="form-select"
|
||||
name="data[${colCount}][id_unit_kerja]"
|
||||
@ -867,7 +652,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Sub Unit <span class="text-danger">*</span></label>
|
||||
<select class="form-select"
|
||||
name="data[${colCount}][id_sub_unit_kerja]"
|
||||
@ -877,7 +662,16 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Kategori Dokumen <span class="text-danger">*</span></label>
|
||||
<select class="form-select"
|
||||
name="data[${colCount}][master_kategori_directory_id]"
|
||||
id="select_kategori_${colCount}"
|
||||
required>
|
||||
<option value="" disabled selected>Pilih Kategori</option>
|
||||
${katOptions}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Nomor Dokumen</label>
|
||||
@ -903,7 +697,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
type="date"
|
||||
name="data[${colCount}][date_active]">
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="col-md-2">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input toggle-expired"
|
||||
type="checkbox"
|
||||
@ -920,7 +714,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
name="data[${colCount}][tgl_expired]" disabled>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<div class="col-md-5">
|
||||
<label class="form-label fw-semibold">Boleh dilihat unit lain? <span class="text-danger">*</span></label>
|
||||
<div class="border rounded-3 p-2 bg-light">
|
||||
<div class="form-check">
|
||||
@ -930,7 +724,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
id="perm_yes_${colCount}"
|
||||
value="1"
|
||||
required>
|
||||
<label class="form-check-label" for="perm_yes_${colCount}">Ya</label>
|
||||
<label class="form-check-label" for="perm_yes_${colCount}">Iya</label>
|
||||
</div>
|
||||
|
||||
<div class="form-check mt-1">
|
||||
@ -945,40 +739,6 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Instrumen Akreditasi </label>
|
||||
<select class="form-select akre-select" id="akre_select_${colCount}" name="data[${colCount}][akre]" style="width: 350px;">
|
||||
<option value="">Pilih Instrumen</option>
|
||||
</select>
|
||||
<div class="form-text text-muted">Isi form ini bila dokumen yang diunggah merupakan dokumen <strong>akreditasi</strong>.</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Kategori Hukum</label>
|
||||
<select class="form-select select-kat-hukum" name="data[${colCount}][kategori_hukum]" id="select_kategori_hukum_${colCount}" style="width: 350px;">
|
||||
<option value="Kebijakan - Peraturan Direktur">Kebijakan - Peraturan Direktur</option>
|
||||
<option value="Kebijakan - Keputusan Direktur Utama">Kebijakan - Keputusan Direktur Utama</option>
|
||||
<option value="Kebijakan - Surat Edaran">Kebijakan - Surat Edaran</option>
|
||||
<option value="Kebijakan - Pengumuman">Kebijakan - Pengumuman</option>
|
||||
<option value="Kerjasama - Pelayanan Kesehatan">Kerjasama - Pelayanan Kesehatan</option>
|
||||
<option value="Kerjasama - Management">Kerjasama - Management</option>
|
||||
<option value="Kerjasama - Pemeliharan">Kerjasama - Pemeliharan</option>
|
||||
<option value="Kerjasama - Diklat">Kerjasama - Diklat</option>
|
||||
<option value="Kerjasama - Luar Negeri">Kerjasama - Luar Negeri</option>
|
||||
<option value="Kerjasama - Area Bisnis">Kerjasama - Area Bisnis</option>
|
||||
<option value="Kerjasama - Pendidikan">Kerjasama - Pendidikan</option>
|
||||
<option value="Kerjasama - Pengampuan KIA">Kerjasama- Pengampuan KIA</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Kategori Lainnya</label>
|
||||
<select class="form-select"
|
||||
name="data[${colCount}][master_kategori_directory_id]"
|
||||
id="select_kategori_${colCount}" style="width: 350px;">
|
||||
<option value="">Pilih Kategori</option>
|
||||
${katOptions}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="col-md-12">
|
||||
<label for="fileUpload_${colCount}" class="form-label fw-semibold">📂 Upload Dokumen (PDF)</label>
|
||||
<div class="border rounded-3 p-3 bg-white shadow-sm">
|
||||
@ -994,9 +754,6 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
</div>`;
|
||||
col.insertAdjacentHTML('beforeend', html);
|
||||
selectOptionUnitKerjaV1(colCount);
|
||||
initKategoriSelect2(colCount);
|
||||
enableAkreFields(colCount);
|
||||
setKategoriRequired(colCount, false);
|
||||
colCount++;
|
||||
}
|
||||
|
||||
@ -1008,8 +765,6 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
if (formCreate) {
|
||||
const select0 = $('#select_id_unit_kerja_0');
|
||||
if (select0.length) selectOptionUnitKerjaV1(0);
|
||||
initKategoriSelect2(0);
|
||||
enableAkreFields(0);
|
||||
|
||||
formCreate.addEventListener('submit', (e) => {
|
||||
e.preventDefault();
|
||||
@ -1061,21 +816,6 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener('change', function(e){
|
||||
if(e.target.classList.contains('akre-select')){
|
||||
const id = e.target.id || '';
|
||||
const idx = id.split('_').pop();
|
||||
const [typeVal = '', segmentVal = '', itemVal = ''] = (e.target.value || '').split('/');
|
||||
const typeInput = document.getElementById(`akre_type_${idx}`);
|
||||
const segmentInput = document.getElementById(`akre_segment_${idx}`);
|
||||
const itemInput = document.getElementById(`akre_item_${idx}`);
|
||||
if(typeInput) typeInput.value = typeVal;
|
||||
if(segmentInput) segmentInput.value = segmentVal;
|
||||
if(itemInput) itemInput.value = itemVal;
|
||||
return;
|
||||
}
|
||||
});
|
||||
});
|
||||
document.addEventListener('click', function(e){
|
||||
if(e.target.matches('.file-link')){
|
||||
@ -1123,5 +863,5 @@ document.addEventListener('click', function(e){
|
||||
function isPublic(permissionVal){
|
||||
if(permissionVal === null || permissionVal === undefined) return false;
|
||||
const val = String(permissionVal).toLowerCase();
|
||||
return val === '1' || val === 'true' || val === 'ya' || val === 'yes';
|
||||
return val === '1' || val === 'true' || val === 'iya' || val === 'yes';
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -154,6 +154,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@include('dashboard.modal.create')
|
||||
@include('dashboard.modal.view')
|
||||
<script>
|
||||
const klasifikasiDok = @json($klasifikasiDok);
|
||||
@ -165,7 +166,7 @@
|
||||
function isPublic(permissionVal){
|
||||
if(permissionVal === null || permissionVal === undefined) return false;
|
||||
const val = String(permissionVal).toLowerCase();
|
||||
return val === '1' || val === 'true' || val === 'ya' || val === 'yes';
|
||||
return val === '1' || val === 'true' || val === 'iya' || val === 'yes';
|
||||
}
|
||||
|
||||
let currentFile = null;
|
||||
|
||||
96
resources/views/dashboard/modal/create.blade.php
Normal file
96
resources/views/dashboard/modal/create.blade.php
Normal file
@ -0,0 +1,96 @@
|
||||
<div class="modal fade" id="modalCreateFile" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog modal-xl modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
|
||||
<!-- Modal Header -->
|
||||
<div class="modal-header">
|
||||
<h1 class="modal-title fs-5">Aksi </h1>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
|
||||
<!-- Modal Form -->
|
||||
<form id="formFile" action="/uploadv2" enctype="multipart/form-data" method="POST" >
|
||||
@csrf
|
||||
<div class="modal-body">
|
||||
<div class="container" style="max-height: 70vh; overflow-y:auto;">
|
||||
<div class="row g-3">
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Unit <span class="text-danger">*</span></label>
|
||||
<select class="form-control unit_kerja" name="data[0][id_unit_kerja]" id="select_id_unit_kerja_0" required>
|
||||
<option value="" disable>Select Choose</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Sub Unit <span class="text-danger">*</span></label>
|
||||
<select class="form-control" name="data[0][id_sub_unit_kerja]" id="select_id_sub_unit_kerja_0" required>
|
||||
<option value="" disable selected>Select Choose</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Kategori Dokumen <span class="text-danger">*</span></label>
|
||||
<select class="form-control" name="data[0][master_kategori_directory_id]" id="select_kategori_0" required>
|
||||
<option value="" disable>Select Choose</option>
|
||||
@foreach ($katDok as $kat)
|
||||
<option value="{{ $kat->master_kategori_directory_id }}/{{ $kat->nama_kategori_directory }}">{{ $kat->nama_kategori_directory }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-semibold">Nomor Dokumen</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-text">#</span>
|
||||
<input type="text" class="form-control" name="data[0][no_dokumen]" placeholder="Contoh: 001/RS/IT/I/2026">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label class="form-label fw-semibold">Tanggal Terbit</label>
|
||||
<input class="form-control" type="date" name="data[0][date_active]">
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label class="form-label fw-semibold">Boleh dilihat unit lain? <span class="text-danger">*</span></label>
|
||||
|
||||
<div class="border rounded-3 p-2 bg-light">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="radio" name="data[0][is_permission]" id="perm_yes" value="1" required>
|
||||
<label class="form-check-label" for="perm_yes">
|
||||
Iya
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="form-check mt-1">
|
||||
<input class="form-check-input" type="radio" name="data[0][is_permission]" id="perm_no" value="2" required>
|
||||
<label class="form-check-label" for="perm_no">
|
||||
Tidak
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-12 mb-2">
|
||||
<label for="fileUpload0" class="form-label fw-semibold">📂 Upload Dokumen (PDF)</label>
|
||||
<div class="border rounded-3 p-3 bg-white shadow-sm">
|
||||
<input class="form-control file-input" type="file" id="fileUpload0" accept=".pdf" name="data[0][file]">
|
||||
<div class="mt-2 text-success fw-semibold d-none file-name"></div>
|
||||
</div>
|
||||
<div class="form-text text-muted">
|
||||
Format yang didukung: <b>PDF</b> Maksimal <b>10mb</b>.
|
||||
</div>
|
||||
</div>
|
||||
<div id="col_add_file" class="col-12"></div>
|
||||
</div>
|
||||
<button type="button" class="btn btn-outline-primary btn-sm mt-3" onclick="addForm()">
|
||||
+ Tambah Form
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal Footer -->
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Tutup</button>
|
||||
<button type="submit" class="btn btn-primary">Simpan</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -1,916 +0,0 @@
|
||||
@extends('layout.main')
|
||||
<style>
|
||||
/* Baris Folder */
|
||||
.tree-folder {
|
||||
background-color: #fcfcfc;
|
||||
cursor: pointer;
|
||||
transition: background 0.2s;
|
||||
}
|
||||
.tree-folder:hover {
|
||||
background-color: #f4f7fb;
|
||||
}
|
||||
|
||||
/* Container Indentasi */
|
||||
.indent-container {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/* Garis Pandu Vertikal */
|
||||
.tree-line {
|
||||
display: inline-block;
|
||||
width: 24px;
|
||||
height: 40px; /* Sesuaikan dengan tinggi row */
|
||||
border-left: 1px solid #e0e0e0;
|
||||
margin-left: 12px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Menghilangkan garis terakhir agar lebih rapi */
|
||||
.tree-file:last-child .tree-line {
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
/* Ikon dan Teks */
|
||||
.folder-icon { color: #ffc107; font-size: 1.2rem; }
|
||||
.file-icon { color: #6c757d; font-size: 1.1rem; }
|
||||
|
||||
.badge-pdf { background-color: #fff0f0; color: #e44d26; border: 1px solid #ffcccc; }
|
||||
</style>
|
||||
@section('body_main')
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="card">
|
||||
<div class="card-body p-3">
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane fade show active">
|
||||
<div class="d-flex justify-content-between align-items-start mb-3">
|
||||
<h4 class="mb-0">Dokumen Akreditasi</h4>
|
||||
<div class="d-flex align-items-start gap-3">
|
||||
<div class="d-flex flex-column align-items-start">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary btn-sm"
|
||||
id="btnDownloadMultiple"
|
||||
disabled
|
||||
>
|
||||
<i class="ti ti-download me-1"></i>
|
||||
Download Terpilih
|
||||
</button>
|
||||
|
||||
<span
|
||||
id="selectedCount"
|
||||
class="small text-muted mt-1"
|
||||
>
|
||||
0 dipilih
|
||||
</span>
|
||||
</div>
|
||||
<!-- Tambah Dokumen -->
|
||||
@if(!Auth::guard('admin')->check())
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-success btn-sm"
|
||||
data-bs-toggle="modal"
|
||||
data-bs-target="#modalCreateFile"
|
||||
>
|
||||
<i class="ti ti-plus me-1"></i>
|
||||
Tambah Dokumen
|
||||
</button>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex flex-column flex-md-row align-items-md-center gap-2 mb-3">
|
||||
<div class="d-flex flex-column flex-md-row align-items-md-center gap-2 flex-grow-1">
|
||||
<input type="search" id="tableSearch" class="form-control"
|
||||
placeholder="Cari Dokumen / Folder" autocomplete="off">
|
||||
</div>
|
||||
<div class="d-flex align-items-center gap-2">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-responsive" style="max-height: 70vh; overflow-y:auto;">
|
||||
<table class="table table-sm table-hover align-middle mb-0 table-fixed" id="lastUpdatedTable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-center" style="width: 45px;">
|
||||
<input type="checkbox" id="checkAllRows" class="form-check-input">
|
||||
</th>
|
||||
<th style="width: 80px;">Aksi</th>
|
||||
<th style="width: 40%;">Nama Dokumen / Folder</th>
|
||||
<th>Tipe</th>
|
||||
<th>Unit</th>
|
||||
<th>Tgl Unggah</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="tableDataAkreditasi">
|
||||
<!-- data dari fetch masuk sini -->
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="d-flex flex-wrap align-items-center gap-2 mt-3">
|
||||
<div class="d-flex align-items-center gap-1">
|
||||
<span class="small text-muted">Tampilkan</span>
|
||||
<select id="tablePageSize" class="form-select form-select-sm" style="width: 80px;">
|
||||
<option value="5">5</option>
|
||||
<option value="10" selected>10</option>
|
||||
<option value="20">20</option>
|
||||
<option value="50">50</option>
|
||||
<option value="100">100</option>
|
||||
</select>
|
||||
<span class="small text-muted">data</span>
|
||||
</div>
|
||||
|
||||
<div id="paginationControls" class="ms-auto"></div>
|
||||
|
||||
<div class="small text-muted text-nowrap" id="tableSummary">
|
||||
Memuat data...
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@include('dataUnit.modal.create')
|
||||
|
||||
<script>
|
||||
// === STATE MANAGEMENT ===
|
||||
let currentData = [];
|
||||
let selectedIds = [];
|
||||
let expandedFolders = new Set();
|
||||
let searchTimer;
|
||||
const btn = document.getElementById('btnDownloadMultiple');
|
||||
// === INITIALIZATION ===
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
fetchData();
|
||||
initEventListeners();
|
||||
});
|
||||
|
||||
// === EVENT LISTENERS ===
|
||||
function initEventListeners() {
|
||||
// Search dengan Debounce
|
||||
document.getElementById('tableSearch').addEventListener('input', (e) => {
|
||||
clearTimeout(searchTimer);
|
||||
searchTimer = setTimeout(() => {
|
||||
fetchData(e.target.value, 1);
|
||||
}, 500);
|
||||
});
|
||||
|
||||
// Per Page Change
|
||||
document.getElementById('tablePageSize').addEventListener('change', (e) => {
|
||||
const keyword = document.getElementById('tableSearch').value;
|
||||
fetchData(keyword,1);
|
||||
});
|
||||
|
||||
// Check All Rows
|
||||
document.getElementById('checkAllRows').addEventListener('change', function() {
|
||||
const checkboxes = document.querySelectorAll('.row-checkbox');
|
||||
selectedIds = [];
|
||||
checkboxes.forEach(cb => {
|
||||
cb.checked = this.checked;
|
||||
if (this.checked) selectedIds.push(cb.value);
|
||||
});
|
||||
updateDownloadButton();
|
||||
});
|
||||
}
|
||||
|
||||
// === CORE FUNCTIONS ===
|
||||
|
||||
/**
|
||||
* Mengambil data dari server
|
||||
*/
|
||||
function fetchData(keyword = '', page = 1) {
|
||||
const tbody = document.getElementById('tableDataAkreditasi');
|
||||
const perPage = document.getElementById('tablePageSize').value;
|
||||
|
||||
tbody.innerHTML = '<tr><td colspan="6" class="text-center">Memuat data...</td></tr>';
|
||||
|
||||
fetch(`/datatable-akreditasi?keyword=${encodeURIComponent(keyword)}&per_page=${perPage}&page=${page}`)
|
||||
.then(res => res.json())
|
||||
.then(response => {
|
||||
if (response.status) {
|
||||
currentData = response.data || [];
|
||||
renderTable(keyword);
|
||||
updateSummary(response.pagination.total);
|
||||
} else {
|
||||
tbody.innerHTML = `<tr><td colspan="6" class="text-center text-danger">${response.message}</td></tr>`;
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
console.error('Error fetching data:', err);
|
||||
tbody.innerHTML = '<tr><td colspan="6" class="text-center text-danger">Gagal memuat data dari server.</td></tr>';
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Merender tabel berdasarkan mode (Folder vs Search)
|
||||
*/
|
||||
function renderTable(keyword = '') {
|
||||
const tbody = document.getElementById('tableDataAkreditasi');
|
||||
tbody.innerHTML = '';
|
||||
|
||||
if (currentData.length === 0) {
|
||||
tbody.innerHTML = '<tr><td colspan="6" class="text-center">Tidak ada data ditemukan</td></tr>';
|
||||
return;
|
||||
}
|
||||
|
||||
// MODE 1: SEARCH VIEW (Flat View - Langsung tampilkan semua file)
|
||||
if (keyword.length > 0) {
|
||||
currentData.forEach(item => renderFileRow(tbody, item));
|
||||
return;
|
||||
}
|
||||
|
||||
// MODE 2: TREE VIEW (All folders & files)
|
||||
const tree = buildTree(currentData);
|
||||
if (expandedFolders.size === 0) {
|
||||
expandAllFolders(tree, '');
|
||||
}
|
||||
renderTree(tbody, tree, '', 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render Baris File (Digunakan di kedua mode)
|
||||
*/
|
||||
function renderFileRow(targetTbody, item) {
|
||||
const fileName = item.file ? item.file.split('/').pop() : 'Unknown';
|
||||
const typeDok = fileName.split('.').pop().toUpperCase();
|
||||
const isChecked = selectedIds.includes(String(item.file_directory_id)) ? 'checked' : '';
|
||||
|
||||
targetTbody.innerHTML += `
|
||||
<tr>
|
||||
<td class="text-center">
|
||||
<input type="checkbox" class="form-check-input row-checkbox"
|
||||
value="${item.file_directory_id}" ${isChecked} onchange="handleRowCheck(this)">
|
||||
</td>
|
||||
<td>
|
||||
<div class="btn-group">
|
||||
<a href="/file-download/${item.file_directory_id}" target="_blank"
|
||||
class="btn btn-sm btn-outline-primary" download title="Download">
|
||||
<i class="ti ti-download"></i>
|
||||
</a>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="d-flex flex-column">
|
||||
<strong>${item.nama_dokumen}</strong>
|
||||
<small class="text-muted" style="font-size: 10px;">Path: ${item.file}</small>
|
||||
</div>
|
||||
</td>
|
||||
<td><span class="badge bg-light text-primary border">${typeDok}</span></td>
|
||||
<td></td>
|
||||
<td>${item.entry_at || '-'}</td>
|
||||
</tr>`;
|
||||
}
|
||||
|
||||
// === TREE FUNCTIONS ===
|
||||
|
||||
function buildTree(items) {
|
||||
const root = { folders: {}, files: [] };
|
||||
(items || []).forEach(item => {
|
||||
const path = (item.file || '').split('/').filter(Boolean);
|
||||
if (path.length === 0) {
|
||||
root.files.push(item);
|
||||
return;
|
||||
}
|
||||
const fileName = path.pop();
|
||||
let node = root;
|
||||
path.forEach(part => {
|
||||
if (!node.folders[part]) {
|
||||
node.folders[part] = { folders: {}, files: [] };
|
||||
}
|
||||
node = node.folders[part];
|
||||
});
|
||||
node.files.push({ ...item, __fileName: fileName });
|
||||
});
|
||||
return root;
|
||||
}
|
||||
|
||||
function expandAllFolders(node, basePath) {
|
||||
Object.keys(node.folders || {}).forEach(folder => {
|
||||
const folderPath = basePath ? `${basePath}/${folder}` : folder;
|
||||
expandedFolders.add(folderPath);
|
||||
expandAllFolders(node.folders[folder], folderPath);
|
||||
});
|
||||
}
|
||||
|
||||
function renderTree(tbody, node, basePath, level) {
|
||||
const folderNames = Object.keys(node.folders || {}).sort();
|
||||
|
||||
folderNames.forEach(folder => {
|
||||
const folderPath = basePath ? `${basePath}/${folder}` : folder;
|
||||
const isExpanded = expandedFolders.has(folderPath);
|
||||
const folderNode = node.folders[folder];
|
||||
|
||||
let lines = '';
|
||||
for (let i = 0; i < level; i++) {
|
||||
lines += '<span class="tree-line"></span>';
|
||||
}
|
||||
|
||||
tbody.innerHTML += `
|
||||
<tr class="tree-folder" onclick="toggleFolder('${folderPath}')">
|
||||
<td></td> <td></td> <td>
|
||||
<div class="indent-container">
|
||||
${lines}
|
||||
<span class="folder-toggle me-1">
|
||||
<i class="ti ${isExpanded ? 'ti-chevron-down' : 'ti-chevron-right'} text-muted" style="font-size: 12px;"></i>
|
||||
</span>
|
||||
<i class="ti ti-folder-filled folder-icon me-2"></i>
|
||||
<strong class="text-dark">${folder}</strong>
|
||||
</div>
|
||||
</td>
|
||||
<td><span class="badge bg-light text-muted border-0">FOLDER</span></td>
|
||||
<td class="text-muted small"></td> <td class="text-muted small"></td> </tr>
|
||||
`;
|
||||
|
||||
if (isExpanded) {
|
||||
renderTree(tbody, folderNode, folderPath, level + 1);
|
||||
}
|
||||
});
|
||||
|
||||
// Bagian ini akan memanggil renderTreeFileRow yang menampilkan tanggal
|
||||
(node.files || []).forEach(item => {
|
||||
renderTreeFileRow(tbody, item, level);
|
||||
});
|
||||
}
|
||||
|
||||
function getFolderMaxDate(node) {
|
||||
let dates = [];
|
||||
|
||||
// Ambil tanggal dari file di level ini
|
||||
(node.files || []).forEach(f => {
|
||||
if (f.entry_at) dates.push(new Date(f.entry_at));
|
||||
});
|
||||
|
||||
// Ambil tanggal dari sub-folder (rekursif)
|
||||
Object.values(node.folders || {}).forEach(subNode => {
|
||||
const subDate = getFolderMaxDate(subNode);
|
||||
if (subDate) dates.push(new Date(subDate));
|
||||
});
|
||||
|
||||
if (dates.length === 0) return null;
|
||||
|
||||
// Cari tanggal paling besar (terbaru)
|
||||
const maxDate = new Date(Math.max(...dates));
|
||||
|
||||
// Format balik ke YYYY-MM-DD
|
||||
return maxDate.toISOString().split('T')[0];
|
||||
}
|
||||
|
||||
function renderTreeFileRow(targetTbody, item, level){
|
||||
const fileName = item.__fileName || (item.file ? item.file.split('/').pop() : 'Unknown');
|
||||
const typeDok = fileName.split('.').pop().toUpperCase();
|
||||
const isChecked = selectedIds.includes(String(item.file_directory_id)) ? 'checked' : '';
|
||||
|
||||
let lines = '';
|
||||
for (let i = 0; i < level; i++) {
|
||||
lines += '<span class="tree-line"></span>';
|
||||
}
|
||||
|
||||
targetTbody.innerHTML += `
|
||||
<tr class="tree-file">
|
||||
<td class="text-center">
|
||||
<input type="checkbox" class="form-check-input row-checkbox"
|
||||
value="${item.file_directory_id}" ${isChecked} onchange="handleRowCheck(this)">
|
||||
</td>
|
||||
<td>
|
||||
<a href="/file-download/${item.file_directory_id}" target="_blank"
|
||||
class="btn btn-sm btn-primary text-white border">
|
||||
<i class="ti ti-download"></i>
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<div class="indent-container">
|
||||
${lines}
|
||||
<span style="width: 24px;"></span> <i class="ti ti-file-text file-icon me-2"></i>
|
||||
<div class="d-flex flex-column">
|
||||
<span class="text-dark fw-medium">${item.nama_dokumen}</span>
|
||||
<small class="text-muted" style="font-size: 10px;">${fileName}</small>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td><span class="badge bg-danger">${typeDok}</span></td>
|
||||
<td>${item.unit?.name || '-'}</td>
|
||||
<td class="text-muted small">${formatDateTime(item.entry_at)}</td>
|
||||
</tr>`;
|
||||
}
|
||||
// Tambahkan fungsi ini di dalam <script>
|
||||
function toggleFolder(folderPath) {
|
||||
if (expandedFolders.has(folderPath)) {
|
||||
expandedFolders.delete(folderPath);
|
||||
} else {
|
||||
expandedFolders.add(folderPath);
|
||||
}
|
||||
renderTable(document.getElementById('tableSearch').value || '');
|
||||
}
|
||||
|
||||
// === UTILITY FUNCTIONS ===
|
||||
|
||||
function handleRowCheck(checkbox) {
|
||||
const val = String(checkbox.value);
|
||||
if (checkbox.checked) {
|
||||
if (!selectedIds.includes(val)) selectedIds.push(val);
|
||||
} else {
|
||||
selectedIds = selectedIds.filter(id => id !== val);
|
||||
document.getElementById('checkAllRows').checked = false;
|
||||
}
|
||||
updateDownloadButton();
|
||||
}
|
||||
|
||||
function updateDownloadButton() {
|
||||
|
||||
const countLabel = document.getElementById('selectedCount');
|
||||
btn.disabled = selectedIds.length === 0;
|
||||
countLabel.innerText = `${selectedIds.length} dipilih`;
|
||||
}
|
||||
|
||||
function updateSummary(total) {
|
||||
const summary = document.getElementById('tableSummary');
|
||||
if (summary) summary.innerText = `Total: ${total} data`;
|
||||
}
|
||||
|
||||
const downloadBtn = document.getElementById('btnDownloadMultiple');
|
||||
if (downloadBtn) {
|
||||
downloadBtn.addEventListener('click', function(){
|
||||
if(selectedIds.length === 0){
|
||||
return;
|
||||
}
|
||||
const payload = { ids: Array.from(selectedIds) };
|
||||
downloadBtn.disabled = true;
|
||||
downloadBtn.textContent = 'Menyiapkan...';
|
||||
fetch('/download-multiple', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content,
|
||||
'X-Requested-With': 'XMLHttpRequest'
|
||||
},
|
||||
body: JSON.stringify(payload)
|
||||
})
|
||||
.then(async (res) => {
|
||||
const contentType = res.headers.get('content-type') || '';
|
||||
if(!res.ok || contentType.includes('application/json')){
|
||||
const err = await res.json().catch(() => ({}));
|
||||
throw new Error(err?.message || 'Gagal download file');
|
||||
}
|
||||
const blob = await res.blob();
|
||||
const url = window.URL.createObjectURL(blob);
|
||||
const a = document.createElement('a');
|
||||
const disposition = res.headers.get('content-disposition') || '';
|
||||
const match = disposition.match(/filename="?([^"]+)"?/);
|
||||
a.href = url;
|
||||
a.download = match?.[1] || 'files.zip';
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
a.remove();
|
||||
window.URL.revokeObjectURL(url);
|
||||
})
|
||||
.catch(err => {
|
||||
Swal.fire({ icon: 'error', title: 'Gagal', text: err.message || 'Gagal download file' });
|
||||
})
|
||||
.finally(() => {
|
||||
downloadBtn.disabled = selectedIds.length === 0;
|
||||
downloadBtn.textContent = 'Download Terpilih';
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener('click', function(e){
|
||||
const toggle = e.target.closest('.folder-toggle');
|
||||
if (!toggle) return;
|
||||
const folderPath = toggle.getAttribute('data-folder');
|
||||
if (!folderPath) return;
|
||||
if (expandedFolders.has(folderPath)) {
|
||||
expandedFolders.delete(folderPath);
|
||||
} else {
|
||||
expandedFolders.add(folderPath);
|
||||
}
|
||||
renderTable(document.getElementById('tableSearch').value || '');
|
||||
});
|
||||
|
||||
function formatDateTime(value) {
|
||||
if (!value) return '—';
|
||||
const d = new Date(value);
|
||||
if (isNaN(d)) return value;
|
||||
const pad = n => String(n).padStart(2, '0');
|
||||
return `${d.getFullYear()}-${pad(d.getMonth()+1)}-${pad(d.getDate())} `
|
||||
+ `${pad(d.getHours())}:${pad(d.getMinutes())}`;
|
||||
}
|
||||
const katDok = @json($katDok);
|
||||
const formCreate = document.getElementById('formFile');
|
||||
const modalCreate = document.getElementById('modalCreateFile');
|
||||
let colCount = 1;
|
||||
|
||||
document.addEventListener('change', function(e){
|
||||
if(!e.target.classList.contains('toggle-expired')) return;
|
||||
const targetId = e.target.getAttribute('data-target');
|
||||
if(!targetId) return;
|
||||
const fieldWrap = document.getElementById(targetId);
|
||||
const input = fieldWrap?.querySelector('input');
|
||||
if (input) input.disabled = !e.target.checked;
|
||||
});
|
||||
|
||||
let akreData = [];
|
||||
let akreLoaded = false;
|
||||
let akreFlat = [];
|
||||
|
||||
function loadAkreData(){
|
||||
if(akreLoaded) return Promise.resolve(akreData);
|
||||
return fetch('/json/akreditasi.jff')
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
akreData = Array.isArray(data) ? data : [];
|
||||
akreFlat = [];
|
||||
akreLoaded = true;
|
||||
return akreData;
|
||||
})
|
||||
.catch(() => {
|
||||
akreData = [];
|
||||
akreFlat = [];
|
||||
akreLoaded = true;
|
||||
return akreData;
|
||||
});
|
||||
}
|
||||
|
||||
function getAkreFlat(){
|
||||
if(akreFlat.length) return akreFlat;
|
||||
akreFlat = (akreData || []).flatMap(type => {
|
||||
const segments = Array.isArray(type.segment) ? type.segment : [];
|
||||
return segments.flatMap(seg => {
|
||||
const children = Array.isArray(seg.turunan) ? seg.turunan : [];
|
||||
return children.map(child => ({
|
||||
value: `${type.name}/${seg.name}/${child.name}`,
|
||||
label: `${type.name} / ${child.name}`,
|
||||
type: type.name,
|
||||
segment: seg.name,
|
||||
item: child.name
|
||||
}));
|
||||
});
|
||||
});
|
||||
return akreFlat;
|
||||
}
|
||||
|
||||
function fillAkreSelect(selectEl){
|
||||
if(!selectEl) return;
|
||||
selectEl.innerHTML = '<option value="">Pilih Instrumen</option>';
|
||||
getAkreFlat().forEach(optData => {
|
||||
const opt = document.createElement('option');
|
||||
opt.value = optData.value;
|
||||
opt.textContent = optData.label;
|
||||
selectEl.appendChild(opt);
|
||||
});
|
||||
}
|
||||
|
||||
function setKategoriRequired(index, isRequired){
|
||||
const katSelect = document.getElementById(`select_kategori_${index}`);
|
||||
if (!katSelect) return;
|
||||
if (isRequired) {
|
||||
katSelect.setAttribute('required', 'required');
|
||||
} else {
|
||||
katSelect.removeAttribute('required');
|
||||
}
|
||||
}
|
||||
|
||||
function resetAkreFields(index){
|
||||
const selectEl = document.getElementById(`akre_select_${index}`);
|
||||
const typeInput = document.getElementById(`akre_type_${index}`);
|
||||
const segmentInput = document.getElementById(`akre_segment_${index}`);
|
||||
const itemInput = document.getElementById(`akre_item_${index}`);
|
||||
if(selectEl){
|
||||
selectEl.value = '';
|
||||
if(window.$ && $.fn.select2) $(selectEl).val(null).trigger('change');
|
||||
}
|
||||
if(typeInput) typeInput.value = '';
|
||||
if(segmentInput) segmentInput.value = '';
|
||||
if(itemInput) itemInput.value = '';
|
||||
setKategoriRequired(index, false);
|
||||
}
|
||||
|
||||
function enableAkreFields(index){
|
||||
const selectEl = document.getElementById(`akre_select_${index}`);
|
||||
setKategoriRequired(index, false);
|
||||
loadAkreData().then(() => {
|
||||
fillAkreSelect(selectEl);
|
||||
if(window.$ && $.fn.select2){
|
||||
$(selectEl).select2({
|
||||
dropdownParent: $('#modalCreateFile'),
|
||||
placeholder: 'Pilih Instrumen',
|
||||
allowClear: true
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function initKategoriSelect2(index){
|
||||
if(!window.$ || !$.fn.select2) return;
|
||||
const katSelect = $(`#select_kategori_${index}`);
|
||||
const hukumSelect = $(`#select_kategori_hukum_${index}`);
|
||||
if(katSelect.length){
|
||||
katSelect.select2({
|
||||
dropdownParent: $('#modalCreateFile'),
|
||||
placeholder:'Pilih Kategori',
|
||||
allowClear: true
|
||||
});
|
||||
}
|
||||
if(hukumSelect.length){
|
||||
hukumSelect.select2({
|
||||
dropdownParent: $('#modalCreateFile'),
|
||||
placeholder:'Pilih Kategori Hukum',
|
||||
allowClear:true
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function selectOptionUnitKerjaV1(localCol){
|
||||
const selectUnit = $(`#select_id_unit_kerja_${localCol}`);
|
||||
const selectSubUnit = $(`#select_id_sub_unit_kerja_${localCol}`);
|
||||
|
||||
selectUnit.select2({
|
||||
placeholder: '-- Pilih Unit Kerja --',
|
||||
allowClear:true,
|
||||
width: '100%',
|
||||
dropdownParent: selectUnit.parent(),
|
||||
ajax:{
|
||||
url : '/select-unit-kerja-mapping',
|
||||
dataType: 'json',
|
||||
delay: 250,
|
||||
data: function(params){
|
||||
return { q: params.term }
|
||||
},
|
||||
processResults: function(data){
|
||||
return {
|
||||
results : (data?.data || []).map(item => ({
|
||||
id: item.id+'/'+item.name,
|
||||
text: item.name,
|
||||
sub_units: item.sub_unit_kerja
|
||||
}))
|
||||
}
|
||||
},
|
||||
cache: true,
|
||||
},
|
||||
minimumInputLength: 0,
|
||||
});
|
||||
|
||||
selectSubUnit.select2({
|
||||
placeholder: '-- Pilih Sub Unit Kerja --',
|
||||
allowClear: true,
|
||||
width: '100%',
|
||||
dropdownParent: selectSubUnit.parent()
|
||||
});
|
||||
|
||||
selectUnit.on('select2:select', function (e) {
|
||||
const data = e.params.data;
|
||||
selectSubUnit.empty().append('<option value="" disabled selected>-- Pilih Sub Unit Kerja --</option>');
|
||||
if (data.sub_units && data.sub_units.length > 0) {
|
||||
data.sub_units.forEach(sub => {
|
||||
selectSubUnit.append(`<option value="${sub.id}/${sub.name}">${sub.name}</option>`);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
window.addFormV2 = function(){
|
||||
const col = document.getElementById('col_add_fileV2');
|
||||
if (!col) return;
|
||||
const katOptions = (Array.isArray(katDok) ? katDok : [])
|
||||
.map(k => `<option value="${k.master_kategori_directory_id}/${k.nama_kategori_directory}">${k.nama_kategori_directory}</option>`)
|
||||
.join('');
|
||||
|
||||
let html = `
|
||||
<div class="row g-3 align-items-start" id="col-${colCount}">
|
||||
<hr class="my-3" />
|
||||
<div class="col-12 d-flex justify-content-end">
|
||||
<button type="button"
|
||||
class="btn btn-sm btn-danger"
|
||||
onclick="removeCol(${colCount})">
|
||||
<i class="fa-solid fa-trash"></i> Hapus
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-semibold">Unit <span class="text-danger">*</span></label>
|
||||
<select class="form-select"
|
||||
name="data[${colCount}][id_unit_kerja]"
|
||||
id="select_id_unit_kerja_${colCount}"
|
||||
required>
|
||||
<option value="" disabled selected>Pilih Unit</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-semibold">Sub Unit <span class="text-danger">*</span></label>
|
||||
<select class="form-select"
|
||||
name="data[${colCount}][id_sub_unit_kerja]"
|
||||
id="select_id_sub_unit_kerja_${colCount}"
|
||||
required>
|
||||
<option value="" disabled selected>Pilih Sub Unit</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Nomor Dokumen</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-text">#</span>
|
||||
<input type="text"
|
||||
class="form-control"
|
||||
name="data[${colCount}][no_dokumen]"
|
||||
placeholder="Contoh: 001/RS/IT/I/2026">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Nama Dokumen<span class="text-danger">*</span></label>
|
||||
<input type="text"
|
||||
class="form-control"
|
||||
name="data[${colCount}][nama_dokumen]"
|
||||
placeholder="Contoh: Panduan Mencuci Tangan" required>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Tanggal Terbit</label>
|
||||
<input class="form-control"
|
||||
type="date"
|
||||
name="data[${colCount}][date_active]">
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input toggle-expired"
|
||||
type="checkbox"
|
||||
id="hasExpired_${colCount}"
|
||||
data-target="expiredField_${colCount}">
|
||||
<label class="form-check-label" for="hasExpired_${colCount}">Masa Berlaku Dokumen?</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-5" id="expiredField_${colCount}">
|
||||
<label class="form-label fw-semibold">Tanggal Kedaluwarsa Dokumen</label>
|
||||
<input class="form-control"
|
||||
type="date"
|
||||
name="data[${colCount}][tgl_expired]" disabled>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Boleh dilihat unit lain? <span class="text-danger">*</span></label>
|
||||
<div class="border rounded-3 p-2 bg-light">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input"
|
||||
type="radio"
|
||||
name="data[${colCount}][is_permission]"
|
||||
id="perm_yes_${colCount}"
|
||||
value="1"
|
||||
required>
|
||||
<label class="form-check-label" for="perm_yes_${colCount}">Ya</label>
|
||||
</div>
|
||||
<div class="form-check mt-1">
|
||||
<input class="form-check-input"
|
||||
type="radio"
|
||||
name="data[${colCount}][is_permission]"
|
||||
id="perm_no_${colCount}"
|
||||
value="2"
|
||||
required>
|
||||
<label class="form-check-label" for="perm_no_${colCount}">Tidak</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Instrumen Akreditasi </label>
|
||||
<select class="form-select akre-select" id="akre_select_${colCount}" name="data[${colCount}][akre]" style="width: 350px;">
|
||||
<option value="">Pilih Instrumen</option>
|
||||
</select>
|
||||
<div class="form-text text-muted">Isi form ini bila dokumen yang diunggah merupakan dokumen <strong>akreditasi</strong>.</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Kategori Hukum</label>
|
||||
<select class="form-select select-kat-hukum" name="data[${colCount}][kategori_hukum]" id="select_kategori_hukum_${colCount}" style="width: 350px;">
|
||||
<option value="">Pilih Kategori Hukum</option>
|
||||
<option value="Kebijakan - Peraturan Direktur">Kebijakan - Peraturan Direktur</option>
|
||||
<option value="Kebijakan - Keputusan Direktur Utama">Kebijakan - Keputusan Direktur Utama</option>
|
||||
<option value="Kebijakan - Surat Edaran">Kebijakan - Surat Edaran</option>
|
||||
<option value="Kebijakan - Pengumuman">Kebijakan - Pengumuman</option>
|
||||
<option value="Kerjasama - Pelayanan Kesehatan">Kerjasama - Pelayanan Kesehatan</option>
|
||||
<option value="Kerjasama - Management">Kerjasama - Management</option>
|
||||
<option value="Kerjasama - Pemeliharan">Kerjasama - Pemeliharan</option>
|
||||
<option value="Kerjasama - Diklat">Kerjasama - Diklat</option>
|
||||
<option value="Kerjasama - Luar Negeri">Kerjasama - Luar Negeri</option>
|
||||
<option value="Kerjasama - Area Bisnis">Kerjasama - Area Bisnis</option>
|
||||
<option value="Kerjasama - Pendidikan">Kerjasama - Pendidikan</option>
|
||||
<option value="Kerjasama - Pengampuan KIA">Kerjasama- Pengampuan KIA</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Kategori Lainnya</label>
|
||||
<select class="form-select"
|
||||
name="data[${colCount}][master_kategori_directory_id]"
|
||||
id="select_kategori_${colCount}" style="width: 350px;">
|
||||
<option value="">Pilih Kategori</option>
|
||||
${katOptions}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="col-md-12">
|
||||
<label for="fileUpload_${colCount}" class="form-label fw-semibold">📂 Upload Dokumen (PDF)</label>
|
||||
<div class="border rounded-3 p-3 bg-white shadow-sm">
|
||||
<input class="form-control"
|
||||
type="file"
|
||||
id="fileUpload_${colCount}"
|
||||
accept=".pdf"
|
||||
name="data[${colCount}][file]">
|
||||
<div class="mt-2 text-success fw-semibold d-none file-name" id="fileName_${colCount}"></div>
|
||||
</div>
|
||||
<div class="form-text text-muted">Format yang didukung: <b>PDF</b>.</div>
|
||||
</div>
|
||||
</div>`;
|
||||
col.insertAdjacentHTML('beforeend', html);
|
||||
selectOptionUnitKerjaV1(colCount);
|
||||
initKategoriSelect2(colCount);
|
||||
enableAkreFields(colCount);
|
||||
setKategoriRequired(colCount, false);
|
||||
colCount++;
|
||||
}
|
||||
|
||||
window.removeCol = function(count){
|
||||
const el = document.getElementById(`col-${count}`);
|
||||
if (el) el.remove();
|
||||
}
|
||||
|
||||
function resetCreateForm(){
|
||||
colCount = 1;
|
||||
const colAdd = document.getElementById('col_add_fileV2');
|
||||
if (colAdd) colAdd.innerHTML = '';
|
||||
if (formCreate) {
|
||||
formCreate.reset();
|
||||
$(formCreate).find('select').val(null).trigger('change');
|
||||
$(formCreate).find('input[type="file"]').val('');
|
||||
$(formCreate).find('.file-name').addClass('d-none').text('');
|
||||
}
|
||||
resetAkreFields(0);
|
||||
enableAkreFields(0);
|
||||
}
|
||||
|
||||
if (formCreate) {
|
||||
const select0 = $('#select_id_unit_kerja_0');
|
||||
if (select0.length) selectOptionUnitKerjaV1(0);
|
||||
initKategoriSelect2(0);
|
||||
enableAkreFields(0);
|
||||
|
||||
formCreate.addEventListener('submit', (e) => {
|
||||
e.preventDefault();
|
||||
const submitBtn = formCreate.querySelector('button[type="submit"]');
|
||||
if (submitBtn) submitBtn.disabled = true;
|
||||
if (submitBtn) submitBtn.textContent = 'menyimpan...';
|
||||
const formData = new FormData(formCreate);
|
||||
|
||||
fetch(`/uploadv2`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': document.querySelector('input[name="_token"]')?.value || ''
|
||||
},
|
||||
body: formData
|
||||
}).then(async(res) => {
|
||||
const responseData = await res.json();
|
||||
if(responseData.status){
|
||||
Swal.fire({
|
||||
icon: 'success',
|
||||
title: 'Berhasil',
|
||||
text: responseData.message || 'Data berhasil disimpan.',
|
||||
timer: 1500,
|
||||
showConfirmButton: false
|
||||
});
|
||||
const modalInstance = bootstrap.Modal.getInstance(modalCreate);
|
||||
modalInstance?.hide();
|
||||
resetCreateForm();
|
||||
fetchData();
|
||||
} else {
|
||||
throw new Error(responseData.message || 'Terjadi kesalahan saat menyimpan data.');
|
||||
}
|
||||
}).catch(err => {
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Gagal',
|
||||
text: err.message || 'Terjadi kesalahan.'
|
||||
});
|
||||
}).finally(() => {
|
||||
if (submitBtn) submitBtn.disabled = false;
|
||||
if (submitBtn) submitBtn.textContent = 'Simpan';
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener('change', function(e){
|
||||
if(e.target.classList.contains('akre-select')){
|
||||
const id = e.target.id || '';
|
||||
const idx = id.split('_').pop();
|
||||
const [typeVal = '', segmentVal = '', itemVal = ''] = (e.target.value || '').split('/');
|
||||
const typeInput = document.getElementById(`akre_type_${idx}`);
|
||||
const segmentInput = document.getElementById(`akre_segment_${idx}`);
|
||||
const itemInput = document.getElementById(`akre_item_${idx}`);
|
||||
if(typeInput) typeInput.value = typeVal;
|
||||
if(segmentInput) segmentInput.value = segmentVal;
|
||||
if(itemInput) itemInput.value = itemVal;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@endsection
|
||||
@ -35,37 +35,6 @@
|
||||
border: 1px solid #dee2e6 !important;
|
||||
color: #111 !important;
|
||||
}
|
||||
|
||||
.select2-container--default .select2-selection--single .select2-selection__clear {
|
||||
display: inline-block !important;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
color: #999;
|
||||
margin-right: 8px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.table-header-filter .dropdown-menu {
|
||||
z-index: 1080;
|
||||
}
|
||||
.table-fixed-height {
|
||||
min-height: 70vh;
|
||||
}
|
||||
|
||||
/* --- Warna kategori baris --- */
|
||||
.row-shade {
|
||||
background-color: var(--row-bg, transparent) !important;
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
.legend-dot {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
border-radius: 4px;
|
||||
display: inline-block;
|
||||
border: 1px solid rgba(0,0,0,0.08);
|
||||
vertical-align: middle;
|
||||
margin-right: 6px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@section('body_main')
|
||||
@ -119,11 +88,12 @@
|
||||
<div class="d-flex flex-column flex-md-row align-items-md-center gap-2 mb-3">
|
||||
<div class="d-flex flex-column flex-md-row align-items-md-center gap-2 flex-grow-1">
|
||||
<select id="tableUnit" class="form-select form-select-sm unit_kerja_filter" style="max-width: 260px;" multiple></select>
|
||||
<select id="tableKategori" class="form-select form-select-sm kategori_kerja_filter" style="max-width: 260px;">
|
||||
<option value="">Kategori (Semua)</option>
|
||||
<option value="akreditasi">Kategori Akreditasi</option>
|
||||
<option value="hukum">Kategori Hukum</option>
|
||||
<option value="lainnya">Kategori Lainnya</option>
|
||||
<select id="tableKategori" class="form-select form-select-sm kategori_kerja_filter" style="max-width: 260px;" multiple>
|
||||
@foreach ($katDok as $kat)
|
||||
<option value="{{ $kat->master_kategori_directory_id }}">
|
||||
{{ $kat->nama_kategori_directory }}
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<input type="search"
|
||||
id="tableSearch"
|
||||
@ -136,7 +106,7 @@
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-responsive table-fixed-height" style="max-height: 70vh; overflow-y:auto;">
|
||||
<div class="table-responsive" style="max-height: 70vh; overflow-y:auto;">
|
||||
<table class="table table-sm table-hover align-middle mb-0 table-fixed" id="lastUpdatedTable">
|
||||
<thead>
|
||||
<tr>
|
||||
@ -146,21 +116,7 @@
|
||||
<th>Aksi</th>
|
||||
<th>No Dokumen</th>
|
||||
<th>Nama Dokumen</th>
|
||||
<th>
|
||||
<div class="d-flex align-items-center gap-2 table-header-filter">
|
||||
<span>Kategori</span>
|
||||
<div class="dropdown">
|
||||
<button class="btn btn-light btn-sm border" type="button" id="tableKategoriHeaderBtn" data-bs-toggle="dropdown" data-bs-auto-close="outside" aria-expanded="false">
|
||||
<i class="ti ti-filter"></i>
|
||||
</button>
|
||||
<div class="dropdown-menu p-2" id="tableKategoriHeaderMenu" style="min-width: 220px;">
|
||||
<div class="small text-muted px-1">Filter kategori (BETA)</div>
|
||||
<div class="dropdown-divider"></div>
|
||||
<div class="kategori-header-list"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</th>
|
||||
<th>Kategori</th>
|
||||
<th>Unit</th>
|
||||
<th>Tanggal Unggah</th>
|
||||
</tr>
|
||||
@ -170,7 +126,6 @@
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="d-flex flex-wrap align-items-center gap-2 mt-3">
|
||||
<div class="d-flex align-items-center gap-1">
|
||||
<span class="small text-muted">Tampilkan</span>
|
||||
@ -198,6 +153,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@include('dataUmum.modal.create')
|
||||
@include('dataUmum.modal.view')
|
||||
<script>
|
||||
const katDok = @json($katDok);
|
||||
@ -207,24 +163,19 @@
|
||||
const authPegawai = @json(auth()->user()->objectpegawaifk);
|
||||
const formCreate = $("#formFile")
|
||||
const modalCreate = document.getElementById('modalCreateFile')
|
||||
const tableState = { data: [], page: 1, pageSize: 8, search: '', unit: [], kategori: [], kategoriType: [], kategoriHeader: [], lastPage: 1, total: 0 };
|
||||
let kategoriOptionCache = [];
|
||||
const tableState = { data: [], page: 1, pageSize: 8, search: '', unit: [], kategori: [], lastPage: 1, total: 0 };
|
||||
const tbody = document.getElementById('tableDataUmum');
|
||||
const paginationEl = document.getElementById('paginationControls');
|
||||
const summaryEl = document.getElementById('tableSummary');
|
||||
const legendEl = document.getElementById('tableLegend');
|
||||
const pageSizeSelect = document.getElementById('tablePageSize');
|
||||
const unitSelect = document.getElementById('tableUnit');
|
||||
const kategoriSelect = document.getElementById('tableKategori');
|
||||
const kategoriHeaderMenu = document.getElementById('tableKategoriHeaderMenu');
|
||||
const searchInput = document.getElementById('tableSearch');
|
||||
const searchBtn = document.getElementById('btnTableSearch');
|
||||
const downloadBtn = document.getElementById('btnDownloadMultiple');
|
||||
const selectedCountEl = document.getElementById('selectedCount');
|
||||
const checkAllEl = document.getElementById('checkAllRows');
|
||||
const selectedIds = new Set();
|
||||
const colorCache = {};
|
||||
const colorPalette = ['#e8f4ff', '#fff6e5', '#e9f7ef', '#f3e8ff', '#ffe6ea', '#e6f5f3'];
|
||||
|
||||
document.addEventListener('change', function(e){
|
||||
if(!e.target.classList.contains('toggle-expired')) return;
|
||||
@ -284,35 +235,16 @@
|
||||
}
|
||||
if (kategoriSelect) {
|
||||
$('#tableKategori').select2({
|
||||
placeholder: 'Kategori (Semua)',
|
||||
placeholder: 'Pilih Kategori',
|
||||
allowClear: true,
|
||||
width: '100%'
|
||||
width: '100%',
|
||||
closeOnSelect: false
|
||||
});
|
||||
$('#tableKategori').on('change', function () {
|
||||
const val = $(this).val() || '';
|
||||
console.log(val);
|
||||
|
||||
tableState.kategoriType = val ? [val] : [];
|
||||
tableState.page = 1;
|
||||
fetchData();
|
||||
tableState.kategori = $(this).val() || [];
|
||||
});
|
||||
}
|
||||
}
|
||||
if (kategoriHeaderMenu) {
|
||||
kategoriHeaderMenu.addEventListener('change', function(e){
|
||||
const checkbox = e.target.closest('input[type="checkbox"]');
|
||||
if (!checkbox) return;
|
||||
const selected = Array.from(kategoriHeaderMenu.querySelectorAll('input[type="checkbox"]:checked'))
|
||||
.map(el => el.value);
|
||||
tableState.kategoriHeader = selected;
|
||||
if (kategoriSelect && window.$ && $.fn.select2) {
|
||||
const single = selected.length === 1 ? selected[0] : '';
|
||||
$('#tableKategori').val(single).trigger('change');
|
||||
}
|
||||
tableState.page = 1;
|
||||
fetchData();
|
||||
});
|
||||
}
|
||||
|
||||
function resetCreateForm(){
|
||||
colCount = 1;
|
||||
@ -326,48 +258,7 @@
|
||||
function isPublic(permissionVal){
|
||||
if(permissionVal === null || permissionVal === undefined) return false;
|
||||
const val = String(permissionVal).toLowerCase();
|
||||
return val === '1' || val === 'true' || val === 'ya' || val === 'yes';
|
||||
}
|
||||
|
||||
function resolveKategoriFlag(item){
|
||||
if(Number(item.is_akre) === 1 || item.is_akre === true || String(item.is_akre).toLowerCase() === 'true'){
|
||||
return { key: 'akre', label: 'Kategori Akreditasi' };
|
||||
}
|
||||
if(item.kategori_hukum){
|
||||
return { key: 'hukum', label: 'Kategori Hukum' };
|
||||
}
|
||||
const label = (item.nama_kategori || item.nama_kategori_directory || item.kategori || '').trim() || 'Kategori Lainnya';
|
||||
const key = String(item.master_kategori_directory_id || label || 'lainnya');
|
||||
return { key, label };
|
||||
}
|
||||
|
||||
function pickColor(key, label){
|
||||
if(colorCache[key]) return colorCache[key];
|
||||
const index = Object.keys(colorCache).length % colorPalette.length;
|
||||
colorCache[key] = colorPalette[index];
|
||||
return colorCache[key];
|
||||
}
|
||||
|
||||
function renderLegend(items){
|
||||
if(!legendEl) return;
|
||||
const map = new Map();
|
||||
(items || []).forEach(item => {
|
||||
const flag = resolveKategoriFlag(item);
|
||||
const color = pickColor(flag.key, flag.label);
|
||||
if(!map.has(flag.key)){
|
||||
map.set(flag.key, { label: flag.label, color });
|
||||
}
|
||||
});
|
||||
if(map.size === 0){
|
||||
legendEl.textContent = '';
|
||||
return;
|
||||
}
|
||||
legendEl.innerHTML = Array.from(map.values()).map(entry => `
|
||||
<span class="me-3">
|
||||
<span class="legend-dot" style="background:${entry.color};"></span>
|
||||
<span>${entry.label}</span>
|
||||
</span>
|
||||
`).join('');
|
||||
return val === '1' || val === 'true' || val === 'iya' || val === 'yes';
|
||||
}
|
||||
|
||||
function getExpiryStatus(dateStr){
|
||||
@ -403,19 +294,12 @@
|
||||
statusClass = 'bg-secondary';
|
||||
}
|
||||
const checked = selectedIds.has(String(item.file_directory_id)) ? 'checked' : '';
|
||||
const kategoriFlag = resolveKategoriFlag(item);
|
||||
|
||||
const rowColor = pickColor(kategoriFlag.key, kategoriFlag.label);
|
||||
const isAkre = kategoriFlag.key === 'akre';
|
||||
const rowClass = isAkre ? 'table-info' : (expiryStatus === 'expired' ? 'table-danger' : (expiryStatus === 'soon' ? 'table-warning' : 'row-shade'));
|
||||
const rowClass = expiryStatus === 'expired' ? 'table-danger' : (expiryStatus === 'soon' ? 'table-warning' : '');
|
||||
const expiryBadge = expiryStatus === 'expired'
|
||||
? `<span class="badge bg-danger" style="font-size:10px;">Expired</span>`
|
||||
: (expiryStatus === 'soon' ? `<span class="badge bg-warning text-dark" style="font-size:10px;">Akan Expired</span>` : '');
|
||||
const akreBadge = isAkre
|
||||
? `<span class="badge bg-primary text-white" style="font-size:10px;">Akreditasi</span>`
|
||||
: '';
|
||||
return `
|
||||
<tr class="${rowClass}" style="--row-bg:${rowColor};">
|
||||
<tr class="${rowClass}">
|
||||
|
||||
<td class="text-center">
|
||||
<input type="checkbox"
|
||||
@ -474,7 +358,7 @@
|
||||
word-break:break-word;
|
||||
"
|
||||
>
|
||||
${item.nama_dokumen || '-'} ${akreBadge}
|
||||
${item.nama_dokumen || '-'}
|
||||
</a>
|
||||
${expiryBadge}
|
||||
|
||||
@ -483,10 +367,10 @@
|
||||
</td>
|
||||
|
||||
<td>
|
||||
${item.nama_kategori || '-'}
|
||||
${kategoriName}
|
||||
</td>
|
||||
<td>
|
||||
${item.unit?.name || '-'}
|
||||
${unitName}
|
||||
</td>
|
||||
<td class="text-nowrap">${formatTanggal(item.entry_at)}</td>
|
||||
</tr>
|
||||
@ -537,12 +421,12 @@
|
||||
}
|
||||
|
||||
function renderTable(){
|
||||
const pageData = filterByKategoriType(tableState.data || []);
|
||||
const pageData = tableState.data || [];
|
||||
|
||||
if(pageData.length === 0){
|
||||
tbody.innerHTML = `
|
||||
<tr>
|
||||
<td colspan="8" class="text-center text-muted py-4">
|
||||
<td colspan="7" class="text-center text-muted py-4">
|
||||
Tidak ada data yang cocok
|
||||
</td>
|
||||
</tr>
|
||||
@ -560,85 +444,17 @@
|
||||
renderPagination(tableState.lastPage || 1);
|
||||
syncCheckAllState();
|
||||
updateSelectedCount();
|
||||
renderLegend(pageData);
|
||||
}
|
||||
|
||||
function applyTableSearch(){
|
||||
const value = searchInput ? searchInput.value : '';
|
||||
tableState.search = (value || '').trim();
|
||||
tableState.unit = unitSelect && window.$ ? ($('#tableUnit').val() || []) : (tableState.unit || []);
|
||||
const katVal = kategoriSelect && window.$ ? ($('#tableKategori').val() || '') : (kategoriSelect?.value || '');
|
||||
tableState.kategoriType = katVal ? [katVal] : (tableState.kategoriType || []);
|
||||
tableState.kategori = kategoriSelect && window.$ ? ($('#tableKategori').val() || []) : (tableState.kategori || []);
|
||||
tableState.page = 1;
|
||||
fetchData();
|
||||
}
|
||||
|
||||
function getKategoriLabel(item){
|
||||
const parts = String(item?.file || '').split('/');
|
||||
return (parts[2] || item?.nama_kategori_directory || item?.kategori || '').trim();
|
||||
}
|
||||
|
||||
function getKategoriId(item){
|
||||
const label = getKategoriLabel(item);
|
||||
return String(item?.master_kategori_directory_id || label);
|
||||
}
|
||||
|
||||
function getKategoriOptionsFromData(){
|
||||
const seen = new Map();
|
||||
(tableState.data || []).forEach(item => {
|
||||
const label = getKategoriLabel(item);
|
||||
if(!label) return;
|
||||
const id = getKategoriId(item);
|
||||
if(!seen.has(id)){
|
||||
seen.set(id, { id, label });
|
||||
}
|
||||
});
|
||||
return Array.from(seen.values()).sort((a,b) => a.label.localeCompare(b.label));
|
||||
}
|
||||
|
||||
function isKategoriMatch(item, types){
|
||||
if (!types.length) return true;
|
||||
const lowerTypes = types.map(t => String(t).toLowerCase());
|
||||
const isAkre = (item.is_akre === true) || String(item.is_akre).toLowerCase() === 'true' || Number(item.is_akre) === 1;
|
||||
const isHukum = !!item.kategori_hukum;
|
||||
const hasKategoriId = !!item.master_kategori_directory_id;
|
||||
if (isAkre && lowerTypes.includes('akreditasi')) return true;
|
||||
if (isHukum && lowerTypes.includes('hukum')) return true;
|
||||
if (!isAkre && !isHukum && hasKategoriId && lowerTypes.includes('lainnya')) return true;
|
||||
|
||||
const catId = String(getKategoriId(item)).toLowerCase();
|
||||
const catLabel = String(getKategoriLabel(item)).toLowerCase();
|
||||
return lowerTypes.includes(catId) || lowerTypes.includes(catLabel);
|
||||
}
|
||||
|
||||
function filterByKategoriType(items){
|
||||
const types = (tableState.kategoriType || []).map(v => String(v));
|
||||
if (!types.length) return items;
|
||||
return items.filter(item => isKategoriMatch(item, types));
|
||||
}
|
||||
|
||||
function renderKategoriHeaderOptions(){
|
||||
if (!kategoriHeaderMenu) return;
|
||||
const list = kategoriHeaderMenu.querySelector('.kategori-header-list');
|
||||
if (!list) return;
|
||||
const options = kategoriOptionCache.length ? kategoriOptionCache : getKategoriOptionsFromData();
|
||||
const selected = (tableState.kategoriHeader || []).map(v => String(v));
|
||||
if(options.length === 0){
|
||||
list.innerHTML = '<div class=\"dropdown-item text-muted\">Tidak ada kategori</div>';
|
||||
return;
|
||||
}
|
||||
list.innerHTML = options.map(opt => {
|
||||
const checked = selected.includes(opt.id) ? 'checked' : '';
|
||||
return `
|
||||
<label class="dropdown-item d-flex align-items-center gap-2">
|
||||
<input type="checkbox" class="form-check-input m-0" value="${opt.id}" ${checked}>
|
||||
<span>${opt.label}</span>
|
||||
</label>
|
||||
`;
|
||||
}).join('');
|
||||
}
|
||||
|
||||
|
||||
function fetchData(){
|
||||
if(summaryEl) summaryEl.textContent = 'Memuat data...';
|
||||
const params = new URLSearchParams({
|
||||
@ -649,20 +465,15 @@
|
||||
if (tableState.unit && tableState.unit.length > 0) {
|
||||
tableState.unit.forEach(id => params.append('unit[]', id));
|
||||
}
|
||||
if (tableState.kategoriType && tableState.kategoriType.length > 0) {
|
||||
tableState.kategoriType.forEach(id => params.append('kategori[]', id));
|
||||
}
|
||||
if (tableState.kategoriHeader && tableState.kategoriHeader.length > 0) {
|
||||
tableState.kategoriHeader.forEach(id => params.append('kategori_header[]', id));
|
||||
if (tableState.kategori && tableState.kategori.length > 0) {
|
||||
tableState.kategori.forEach(kat => params.append('kategori[]', kat));
|
||||
}
|
||||
fetch(`/datatable-umum?${params.toString()}`)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
tableState.data = data?.data || [];
|
||||
kategoriOptionCache = data?.kategori_list || kategoriOptionCache;
|
||||
tableState.lastPage = data?.pagination?.last_page || 1;
|
||||
tableState.total = data?.pagination?.total || 0;
|
||||
renderKategoriHeaderOptions();
|
||||
renderTable();
|
||||
})
|
||||
.catch(error => {
|
||||
@ -692,7 +503,6 @@
|
||||
year: 'numeric'
|
||||
});
|
||||
}
|
||||
renderKategoriHeaderOptions();
|
||||
fetchData()
|
||||
|
||||
function updateSelectedCount(){
|
||||
@ -869,6 +679,144 @@
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function addFormV2(){
|
||||
let col = $("#col_add_fileV2");
|
||||
let html = '';
|
||||
|
||||
html += `
|
||||
<div class="row g-3 align-items-start" id="col-${colCount}">
|
||||
<hr class="my-3" />
|
||||
<div class="col-12 d-flex justify-content-end">
|
||||
<button type="button"
|
||||
class="btn btn-sm btn-danger"
|
||||
onclick="removeCol(${colCount})">
|
||||
<i class="fa-solid fa-trash"></i> Hapus
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Unit <span class="text-danger">*</span></label>
|
||||
<select class="form-select"
|
||||
name="data[${colCount}][id_unit_kerja]"
|
||||
id="select_id_unit_kerja_${colCount}"
|
||||
required>
|
||||
<option value="" disabled selected>Pilih Unit</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Sub Unit <span class="text-danger">*</span></label>
|
||||
<select class="form-select"
|
||||
name="data[${colCount}][id_sub_unit_kerja]"
|
||||
id="select_id_sub_unit_kerja_${colCount}"
|
||||
required>
|
||||
<option value="" disabled selected>Pilih Sub Unit</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Kategori Dokumen <span class="text-danger">*</span></label>
|
||||
<select class="form-select"
|
||||
name="data[${colCount}][master_kategori_directory_id]"
|
||||
id="select_kategori_${colCount}"
|
||||
required>
|
||||
<option value="" disabled selected>Pilih Kategori</option>
|
||||
@foreach ($katDok as $kat)
|
||||
<option value="{{ $kat->master_kategori_directory_id }}/{{ $kat->nama_kategori_directory }}">
|
||||
{{ $kat->nama_kategori_directory }}
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Nomor Dokumen</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-text">#</span>
|
||||
<input type="text"
|
||||
class="form-control"
|
||||
name="data[${colCount}][no_dokumen]"
|
||||
placeholder="Contoh: 001/RS/IT/I/2026">
|
||||
</div>
|
||||
<div class="form-text text-muted"></div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Nama Dokumen<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control"
|
||||
name="data[${colCount}][nama_dokumen]"
|
||||
placeholder="Contoh: 001/RS/IT/I/2026" required>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Tanggal Terbit</label>
|
||||
<input class="form-control"
|
||||
type="date"
|
||||
name="data[${colCount}][date_active]">
|
||||
</div>
|
||||
<div class="col-md-2 d-flex align-items-end">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input toggle-expired"
|
||||
type="checkbox"
|
||||
id="hasExpired_${colCount}"
|
||||
data-target="expiredField_${colCount}">
|
||||
<label class="form-check-label" for="hasExpired_${colCount}">Ada Expired?</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-5 d-none" id="expiredField_${colCount}">
|
||||
<label class="form-label fw-semibold">Tanggal Kedaluwarsa Dokumen</label>
|
||||
<input class="form-control" type="date" name="data[${colCount}][tgl_expired]">
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
<label class="form-label fw-semibold">Boleh dilihat unit lain? <span class="text-danger">*</span></label>
|
||||
|
||||
<div class="border rounded-3 p-2 bg-light">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input"
|
||||
type="radio"
|
||||
name="data[${colCount}][is_permission]"
|
||||
id="perm_yes_${colCount}"
|
||||
value="1"
|
||||
required>
|
||||
<label class="form-check-label" for="perm_yes_${colCount}">Iya</label>
|
||||
</div>
|
||||
|
||||
<div class="form-check mt-1">
|
||||
<input class="form-check-input"
|
||||
type="radio"
|
||||
name="data[${colCount}][is_permission]"
|
||||
id="perm_no_${colCount}"
|
||||
value="2"
|
||||
required>
|
||||
<label class="form-check-label" for="perm_no_${colCount}">Tidak</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="col-md-12">
|
||||
<label for="fileUpload_${colCount}" class="form-label fw-semibold">📂 Upload Dokumen (PDF)</label>
|
||||
<div class="border rounded-3 p-3 bg-white shadow-sm">
|
||||
<input class="form-control"
|
||||
type="file"
|
||||
id="fileUpload_${colCount}"
|
||||
accept=".pdf"
|
||||
name="data[${colCount}][file]">
|
||||
<div class="mt-2 text-success fw-semibold d-none file-name" id="fileName_${colCount}"></div>
|
||||
</div>
|
||||
|
||||
<div class="form-text text-muted">
|
||||
Format yang didukung: <b>PDF</b>.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
`;
|
||||
col.append(html)
|
||||
selectOptionUnitKerjaV1(colCount)
|
||||
colCount++;
|
||||
}
|
||||
|
||||
function removeCol(count){
|
||||
$(`#col-${count}`).remove()
|
||||
}
|
||||
|
||||
119
resources/views/dataUmum/modal/create.blade.php
Normal file
119
resources/views/dataUmum/modal/create.blade.php
Normal file
@ -0,0 +1,119 @@
|
||||
<div class="modal fade" id="modalCreateFile" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog modal-xl modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
|
||||
<!-- Modal Header -->
|
||||
<div class="modal-header">
|
||||
<h1 class="modal-title fs-5">Aksi </h1>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
|
||||
<!-- Modal Form -->
|
||||
<form id="formFile" action="/uploadv2" enctype="multipart/form-data" method="POST">
|
||||
@csrf
|
||||
<div class="modal-body">
|
||||
<div class="container" style="max-height: 70vh; overflow-y:auto;">
|
||||
<div class="row g-3">
|
||||
<div class="col-12">
|
||||
<div class="p-2 rounded-3 bg-light border">
|
||||
<span class="fw-semibold">Informasi Dokumen</span>
|
||||
<div class="small text-muted">Lengkapi detail dokumen sebelum upload.</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Unit <span class="text-danger">*</span></label>
|
||||
<select class="form-control unit_kerja" name="data[0][id_unit_kerja]" id="select_id_unit_kerja_0" required>
|
||||
<option value="" disable>Pilih Unit</option>
|
||||
</select>
|
||||
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Sub Unit <span class="text-danger">*</span></label>
|
||||
<select class="form-control" name="data[0][id_sub_unit_kerja]" id="select_id_sub_unit_kerja_0" required>
|
||||
<option value="" disable selected>Pilih Sub Unit</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Kategori Dokumen <span class="text-danger">*</span></label>
|
||||
<select class="form-control" name="data[0][master_kategori_directory_id]" id="select_kategori_0" required>
|
||||
<option value="" disable>Pilih Kategori</option>
|
||||
@foreach ($katDok as $kat)
|
||||
<option value="{{ $kat->master_kategori_directory_id }}/{{ $kat->nama_kategori_directory }}">{{ $kat->nama_kategori_directory }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Nomor Dokumen</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-text">#</span>
|
||||
<input type="text" class="form-control" name="data[0][no_dokumen]" placeholder="Contoh: 001/RS/IT/I/2026">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Nama Dokumen<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" name="data[0][nama_dokumen]" placeholder="Contoh: Panduan Mencuci Tangan" required>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Tanggal Terbit</label>
|
||||
<input class="form-control" type="date" name="data[0][date_active]">
|
||||
</div>
|
||||
<div class="col-md-2 d-flex align-items-end">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input toggle-expired" type="checkbox" id="hasExpired0" data-target="expiredField_0">
|
||||
<label class="form-check-label" for="hasExpired0">Ada Expired?</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-5 d-none" id="expiredField_0">
|
||||
<label class="form-label fw-semibold">Tanggal Kedaluwarsa Dokumen</label>
|
||||
<input class="form-control" type="date" name="data[0][tgl_expired]">
|
||||
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
<label class="form-label fw-semibold">Boleh dilihat unit lain? <span class="text-danger">*</span></label>
|
||||
|
||||
<div class="border rounded-3 p-2 bg-light">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="radio" name="data[0][is_permission]" id="perm_yes" value="1" required>
|
||||
<label class="form-check-label" for="perm_yes">
|
||||
Iya
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="form-check mt-1">
|
||||
<input class="form-check-input" type="radio" name="data[0][is_permission]" id="perm_no" value="2" required>
|
||||
<label class="form-check-label" for="perm_no">
|
||||
Tidak
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="col-md-12 mb-2">
|
||||
<label for="fileUpload0" class="form-label fw-semibold">📂 Upload Dokumen (PDF)</label>
|
||||
<div class="border rounded-3 p-3 bg-white shadow-sm">
|
||||
<input class="form-control" type="file" id="fileUpload0" accept=".pdf" name="data[0][file]">
|
||||
<div class="mt-2 text-success fw-semibold d-none file-name"></div>
|
||||
</div>
|
||||
<div class="form-text text-muted">
|
||||
Format yang didukung: <b>PDF</b> Maksimal <b>10mb</b>.
|
||||
</div>
|
||||
</div>
|
||||
<div id="col_add_fileV2" class="col-12"></div>
|
||||
</div>
|
||||
<button type="button" class="btn btn-outline-primary btn-sm mt-3" onclick="addFormV2()">
|
||||
+ Tambah Form
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal Footer -->
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Tutup</button>
|
||||
<button type="submit" class="btn btn-primary">Simpan</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -1,10 +1,10 @@
|
||||
@extends('layout.main')
|
||||
<style>
|
||||
/* --- SELECT2: teks terlihat (hitam) --- */
|
||||
|
||||
.select2-container--default .select2-selection--multiple {
|
||||
background: #fff !important;
|
||||
border: 1px solid rgb(206, 212, 218) !important;
|
||||
border: 1px solid #ced4da !important;
|
||||
min-height: 31px; /* cocok form-select-sm */
|
||||
}
|
||||
|
||||
.select2-container--default .select2-selection--multiple .select2-selection__rendered {
|
||||
@ -35,35 +35,6 @@
|
||||
border: 1px solid #dee2e6 !important;
|
||||
color: #111 !important;
|
||||
}
|
||||
.select2-container--default .select2-selection--single .select2-selection__clear {
|
||||
display: inline-block !important;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
color: #999;
|
||||
margin-right: 8px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.table-header-filter .dropdown-menu {
|
||||
z-index: 1080;
|
||||
}
|
||||
.table-fixed-height {
|
||||
min-height: 70vh;
|
||||
}
|
||||
|
||||
/* --- Warna kategori baris --- */
|
||||
.row-shade {
|
||||
background-color: var(--row-bg, transparent) !important;
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
.legend-dot {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
border-radius: 4px;
|
||||
display: inline-block;
|
||||
border: 1px solid rgba(0,0,0,0.08);
|
||||
vertical-align: middle;
|
||||
margin-right: 6px;
|
||||
}
|
||||
</style>
|
||||
@section('body_main')
|
||||
<div class="row">
|
||||
@ -101,7 +72,6 @@
|
||||
</span>
|
||||
</div>
|
||||
<!-- Tambah Dokumen -->
|
||||
@if(!Auth::guard('admin')->check())
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-success btn-sm"
|
||||
@ -111,19 +81,17 @@
|
||||
<i class="ti ti-plus me-1"></i>
|
||||
Tambah Dokumen
|
||||
</button>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex flex-column flex-md-row align-items-md-center gap-2 mb-3">
|
||||
<div class="d-flex flex-column flex-md-row align-items-md-center gap-2 flex-grow-1">
|
||||
<select id="tableUnit" style="max-width: 260px;">
|
||||
<option value=""></option>
|
||||
</select>
|
||||
<select id="tableKategori" class="form-select form-select-sm" style="max-width: 260px;">
|
||||
<option value="">Kategori (Semua)</option>
|
||||
<option value="akreditasi">Kategori Akreditasi</option>
|
||||
<option value="hukum">Kategori Hukum</option>
|
||||
<option value="lainnya">Kategori Lainnya</option>
|
||||
<select id="tableUnit" class="form-select form-select-sm unit_kerja_filter" style="max-width: 260px;" multiple></select>
|
||||
<select id="tableKategori" class="form-select form-select-sm kategori_kerja_filter" style="max-width: 260px;" multiple>
|
||||
@foreach ($katDok as $kat)
|
||||
<option value="{{ $kat->master_kategori_directory_id }}">
|
||||
{{ $kat->nama_kategori_directory }}
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<input type="search"
|
||||
id="tableSearch"
|
||||
@ -133,7 +101,7 @@
|
||||
</div>
|
||||
<button class="btn btn-primary" type="button" id="btnTableSearch">Cari</button>
|
||||
</div>
|
||||
<div class="table-responsive table-fixed-height" style="max-height: 70vh; overflow-y:auto;">
|
||||
<div class="table-responsive" style="max-height: 70vh; overflow-y:auto;">
|
||||
<table class="table table-sm table-hover align-middle mb-0 table-fixed" id="lastUpdatedTable">
|
||||
<thead>
|
||||
<tr>
|
||||
@ -143,21 +111,7 @@
|
||||
<th>Aksi</th>
|
||||
<th>No Dokumen</th>
|
||||
<th>Nama Dokumen</th>
|
||||
<th>
|
||||
<div class="d-flex align-items-center gap-2 table-header-filter">
|
||||
<span>Kategori</span>
|
||||
<div class="dropdown">
|
||||
<button class="btn btn-light btn-sm border" type="button" id="tableKategoriHeaderBtn" data-bs-toggle="dropdown" data-bs-auto-close="outside" aria-expanded="false">
|
||||
<i class="ti ti-filter"></i>
|
||||
</button>
|
||||
<div class="dropdown-menu p-2" id="tableKategoriHeaderMenu" style="min-width: 220px;">
|
||||
<div class="small text-muted px-1">Filter kategori (BETA)</div>
|
||||
<div class="dropdown-divider"></div>
|
||||
<div class="kategori-header-list"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</th>
|
||||
<th>Kategori</th>
|
||||
<th>Unit</th>
|
||||
<th>Tanggal Unggah</th>
|
||||
<th>Pengunggah</th>
|
||||
@ -168,7 +122,6 @@
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="d-flex flex-wrap align-items-center gap-2 mt-3">
|
||||
<div class="d-flex align-items-center gap-1">
|
||||
<span class="small text-muted">Tampilkan</span>
|
||||
@ -211,32 +164,19 @@
|
||||
const authPegawai = @json(auth()->user()->objectpegawaifk);
|
||||
const formCreate = $("#formFile");
|
||||
const modalCreate = document.getElementById('modalCreateFile');
|
||||
const tableState = { data: [], page: 1, pageSize: 8, search: '', unit: [], kategori: [], kategoriType: [], kategoriHeader: [], lastPage: 1, total: 0 };
|
||||
let kategoriOptionCache = [];
|
||||
const tableState = { data: [], page: 1, pageSize: 8, search: '', unit: [], kategori: [], lastPage: 1, total: 0 };
|
||||
const tbody = document.getElementById('tableDataUnit');
|
||||
const paginationEl = document.getElementById('paginationControls');
|
||||
const summaryEl = document.getElementById('tableSummary');
|
||||
const legendEl = document.getElementById('tableLegend');
|
||||
const pageSizeSelect = document.getElementById('tablePageSize');
|
||||
const unitSelect = document.getElementById('tableUnit');
|
||||
const kategoriSelect = document.getElementById('tableKategori');
|
||||
const kategoriHeaderMenu = document.getElementById('tableKategoriHeaderMenu');
|
||||
const searchInput = document.getElementById('tableSearch');
|
||||
const searchBtn = document.getElementById('btnTableSearch');
|
||||
const downloadBtn = document.getElementById('btnDownloadMultiple');
|
||||
const selectedCountEl = document.getElementById('selectedCount');
|
||||
const checkAllEl = document.getElementById('checkAllRows');
|
||||
const selectedIds = new Set();
|
||||
const colorCache = {};
|
||||
const colorPalette = ['#e8f4ff', '#fff6e5', '#e9f7ef', '#f3e8ff', '#ffe6ea', '#e6f5f3'];
|
||||
|
||||
function normalizeToArray(value){
|
||||
if (Array.isArray(value)) {
|
||||
return value.filter(v => v !== null && v !== undefined && v !== '');
|
||||
}
|
||||
if (value === null || value === undefined || value === '') return [];
|
||||
return [value];
|
||||
}
|
||||
|
||||
document.addEventListener('change', function(e){
|
||||
if(!e.target.classList.contains('toggle-expired')) return;
|
||||
@ -261,11 +201,13 @@
|
||||
}
|
||||
if (window.$ && $.fn.select2) {
|
||||
if (unitSelect) {
|
||||
$('#tableUnit').select2({
|
||||
$('#tableUnit').select2({
|
||||
placeholder: 'Pilih Unit',
|
||||
allowClear: true,
|
||||
width: '100%',
|
||||
closeOnSelect: false,
|
||||
selectionCssClass: 'select2-filter-selection',
|
||||
dropdownCssClass: 'select2-filter-dropdown',
|
||||
ajax: {
|
||||
url: '/select-unit-kerja-mapping',
|
||||
dataType: 'json',
|
||||
@ -284,39 +226,24 @@
|
||||
cache: true
|
||||
}
|
||||
});
|
||||
|
||||
$('#tableUnit').on('change', function () {
|
||||
tableState.unit = $(this).val() || [];
|
||||
});
|
||||
}
|
||||
if (kategoriSelect) {
|
||||
$('#tableKategori').select2({
|
||||
placeholder: 'Kategori (Semua)',
|
||||
placeholder: 'Pilih Kategori',
|
||||
allowClear: true,
|
||||
width: '100%',
|
||||
closeOnSelect: false,
|
||||
selectionCssClass: 'select2-filter-selection',
|
||||
dropdownCssClass: 'select2-filter-dropdown'
|
||||
});
|
||||
$('#tableKategori').on('change', function () {
|
||||
const val = $(this).val() || '';
|
||||
tableState.kategoriType = val ? [val] : [];
|
||||
tableState.page = 1;
|
||||
fetchData();
|
||||
tableState.kategori = $(this).val() || [];
|
||||
});
|
||||
}
|
||||
}
|
||||
if (kategoriHeaderMenu) {
|
||||
kategoriHeaderMenu.addEventListener('change', function(e){
|
||||
const checkbox = e.target.closest('input[type="checkbox"]');
|
||||
if (!checkbox) return;
|
||||
const selected = Array.from(kategoriHeaderMenu.querySelectorAll('input[type="checkbox"]:checked'))
|
||||
.map(el => el.value);
|
||||
tableState.kategoriHeader = selected;
|
||||
if (kategoriSelect && window.$ && $.fn.select2) {
|
||||
const single = selected.length === 1 ? selected[0] : '';
|
||||
$('#tableKategori').val(single).trigger('change');
|
||||
}
|
||||
tableState.page = 1;
|
||||
fetchData();
|
||||
});
|
||||
}
|
||||
|
||||
function resetCreateForm(){
|
||||
colCount = 1;
|
||||
@ -325,186 +252,12 @@
|
||||
formCreate.find('select').val(null).trigger('change');
|
||||
formCreate.find('input[type="file"]').val('');
|
||||
formCreate.find('.file-name').addClass('d-none').text('');
|
||||
resetAkreFields(0);
|
||||
enableAkreFields(0);
|
||||
}
|
||||
|
||||
let akreData = [];
|
||||
let akreLoaded = false;
|
||||
let akreFlat = [];
|
||||
|
||||
function loadAkreData(){
|
||||
if(akreLoaded) return Promise.resolve(akreData);
|
||||
return fetch('/json/akreditasi.jff')
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
akreData = Array.isArray(data) ? data : [];
|
||||
akreFlat = [];
|
||||
akreLoaded = true;
|
||||
return akreData;
|
||||
})
|
||||
.catch(() => {
|
||||
akreData = [];
|
||||
akreFlat = [];
|
||||
akreLoaded = true;
|
||||
return akreData;
|
||||
});
|
||||
}
|
||||
|
||||
function getAkreFlat(){
|
||||
if(akreFlat.length) return akreFlat;
|
||||
akreFlat = (akreData || []).flatMap(type => {
|
||||
const segments = Array.isArray(type.segment) ? type.segment : [];
|
||||
return segments.flatMap(seg => {
|
||||
const children = Array.isArray(seg.turunan) ? seg.turunan : [];
|
||||
return children.map(child => ({
|
||||
value: `${type.name}/${seg.name}/${child.name}`,
|
||||
label: `${type.name} / ${child.name}`,
|
||||
type: type.name,
|
||||
segment: seg.name,
|
||||
item: child.name
|
||||
}));
|
||||
});
|
||||
});
|
||||
return akreFlat;
|
||||
}
|
||||
|
||||
function fillAkreSelect(selectEl){
|
||||
if(!selectEl) return;
|
||||
selectEl.innerHTML = '<option value="" disabled selected>Pilih Instrumen</option>';
|
||||
getAkreFlat().forEach(optData => {
|
||||
const opt = document.createElement('option');
|
||||
opt.value = optData.value;
|
||||
opt.textContent = optData.label;
|
||||
selectEl.appendChild(opt);
|
||||
});
|
||||
}
|
||||
|
||||
function setKategoriRequired(index, isRequired){
|
||||
const katSelect = document.getElementById(`select_kategori_${index}`);
|
||||
if (!katSelect) return;
|
||||
if (isRequired) {
|
||||
katSelect.setAttribute('required', 'required');
|
||||
} else {
|
||||
katSelect.removeAttribute('required');
|
||||
}
|
||||
}
|
||||
|
||||
function resetAkreFields(index){
|
||||
const selectEl = document.getElementById(`akre_select_${index}`);
|
||||
const typeInput = document.getElementById(`akre_type_${index}`);
|
||||
const segmentInput = document.getElementById(`akre_segment_${index}`);
|
||||
const itemInput = document.getElementById(`akre_item_${index}`);
|
||||
if(selectEl){
|
||||
selectEl.value = '';
|
||||
if(window.$ && $.fn.select2) $(selectEl).val(null).trigger('change');
|
||||
}
|
||||
if(typeInput) typeInput.value = '';
|
||||
if(segmentInput) segmentInput.value = '';
|
||||
if(itemInput) itemInput.value = '';
|
||||
setKategoriRequired(index, false);
|
||||
}
|
||||
|
||||
function enableAkreFields(index){
|
||||
const selectEl = document.getElementById(`akre_select_${index}`);
|
||||
// if(selectEl){
|
||||
// selectEl.disabled = false;
|
||||
// selectEl.required = true;
|
||||
// }
|
||||
setKategoriRequired(index, false);
|
||||
loadAkreData().then(() => {
|
||||
fillAkreSelect(selectEl);
|
||||
if(window.$ && $.fn.select2){
|
||||
$(selectEl).select2({
|
||||
dropdownParent: $('#modalCreateFile'),
|
||||
placeholder: 'Pilih Instrumen',
|
||||
allowClear: true
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function initKategoriSelect2(index){
|
||||
if(!window.$ || !$.fn.select2) return;
|
||||
const katSelect = $(`#select_kategori_${index}`);
|
||||
const hukumSelect = $(`#select_kategori_hukum_${index}`);
|
||||
if(katSelect.length){
|
||||
katSelect.select2({
|
||||
dropdownParent: $('#modalCreateFile'),
|
||||
placeholder:'Pilih Kategori',
|
||||
allowClear: true
|
||||
});
|
||||
}
|
||||
if(hukumSelect.length){
|
||||
hukumSelect.select2({
|
||||
dropdownParent: $('#modalCreateFile'),
|
||||
placeholder:'Pilih Kategori Hukum',
|
||||
allowClear:true
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('change', function(e){
|
||||
if(e.target.classList.contains('akre-select')){
|
||||
const id = e.target.id || '';
|
||||
const idx = id.split('_').pop();
|
||||
const [typeVal = '', segmentVal = '', itemVal = ''] = (e.target.value || '').split('/');
|
||||
const typeInput = document.getElementById(`akre_type_${idx}`);
|
||||
const segmentInput = document.getElementById(`akre_segment_${idx}`);
|
||||
const itemInput = document.getElementById(`akre_item_${idx}`);
|
||||
if(typeInput) typeInput.value = typeVal;
|
||||
if(segmentInput) segmentInput.value = segmentVal;
|
||||
if(itemInput) itemInput.value = itemVal;
|
||||
return;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
function isPublic(permissionVal){
|
||||
if(permissionVal === null || permissionVal === undefined) return false;
|
||||
const val = String(permissionVal).toLowerCase();
|
||||
return val === '1' || val === 'true' || val === 'ya' || val === 'yes';
|
||||
}
|
||||
|
||||
function resolveKategoriFlag(item){
|
||||
if(Number(item.is_akre) === 1 || item.is_akre === true || String(item.is_akre).toLowerCase() === 'true'){
|
||||
return { key: 'akre', label: 'Kategori Akreditasi' };
|
||||
}
|
||||
if(item.kategori_hukum){
|
||||
return { key: 'hukum', label: 'Kategori Hukum' };
|
||||
}
|
||||
const label = (item.nama_kategori || item.nama_kategori_directory || item.kategori || '').trim() || 'Kategori Lainnya';
|
||||
const key = String(item.master_kategori_directory_id || label || 'lainnya');
|
||||
return { key, label };
|
||||
}
|
||||
|
||||
function pickColor(key, label){
|
||||
if(colorCache[key]) return colorCache[key];
|
||||
const index = Object.keys(colorCache).length % colorPalette.length;
|
||||
colorCache[key] = colorPalette[index];
|
||||
return colorCache[key];
|
||||
}
|
||||
|
||||
function renderLegend(items){
|
||||
if(!legendEl) return;
|
||||
const map = new Map();
|
||||
(items || []).forEach(item => {
|
||||
const flag = resolveKategoriFlag(item);
|
||||
const color = pickColor(flag.key, flag.label);
|
||||
if(!map.has(flag.key)){
|
||||
map.set(flag.key, { label: flag.label, color });
|
||||
}
|
||||
});
|
||||
if(map.size === 0){
|
||||
legendEl.textContent = '';
|
||||
return;
|
||||
}
|
||||
legendEl.innerHTML = Array.from(map.values()).map(entry => `
|
||||
<span class="me-3">
|
||||
<span class="legend-dot" style="background:${entry.color};"></span>
|
||||
<span>${entry.label}</span>
|
||||
</span>
|
||||
`).join('');
|
||||
return val === '1' || val === 'true' || val === 'iya' || val === 'yes';
|
||||
}
|
||||
|
||||
function getExpiryStatus(dateStr){
|
||||
@ -540,18 +293,12 @@
|
||||
statusClass = 'bg-secondary';
|
||||
}
|
||||
const checked = selectedIds.has(String(item.file_directory_id)) ? 'checked' : '';
|
||||
const kategoriFlag = resolveKategoriFlag(item);
|
||||
const rowColor = pickColor(kategoriFlag.key, kategoriFlag.label);
|
||||
const isAkre = kategoriFlag.key === 'akre';
|
||||
const rowClass = isAkre ? 'table-info' : (expiryStatus === 'expired' ? 'table-danger' : (expiryStatus === 'soon' ? 'table-warning' : 'row-shade'));
|
||||
const rowClass = expiryStatus === 'expired' ? 'table-danger' : (expiryStatus === 'soon' ? 'table-warning' : '');
|
||||
const expiryBadge = expiryStatus === 'expired'
|
||||
? `<span class="badge bg-danger" style="font-size:10px;">Expired</span>`
|
||||
: (expiryStatus === 'soon' ? `<span class="badge bg-warning text-dark" style="font-size:10px;">Akan Expired</span>` : '');
|
||||
const akreBadge = isAkre
|
||||
? `<span class="badge bg-primary text-white ms-2" style="font-size:10px;">Akreditasi</span>`
|
||||
: '';
|
||||
return `
|
||||
<tr class="${rowClass}" style="--row-bg:${rowColor};">
|
||||
<tr class="${rowClass}">
|
||||
<td class="text-center">
|
||||
<input type="checkbox"
|
||||
class="form-check-input row-check"
|
||||
@ -600,17 +347,17 @@
|
||||
>
|
||||
${item.nama_dokumen || '-'}
|
||||
</a>
|
||||
${akreBadge}${expiryBadge}
|
||||
${expiryBadge}
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
${item.nama_kategori || '-'}
|
||||
${kategoriName}
|
||||
</td>
|
||||
<td>
|
||||
${item.unit?.name || '-'}
|
||||
${unitName}
|
||||
</td>
|
||||
<td class="text-nowrap">${formatTanggal(item.entry_at)}</td>
|
||||
<td style="max-width: 200px; white-space: normal; word-wrap: break-word;">${item.pegawai_nama_entry || '-'}</td>
|
||||
<td class="text-nowrap">${item.pegawai_nama_entry || '-'}</td>
|
||||
</tr>
|
||||
`;
|
||||
}
|
||||
@ -659,12 +406,12 @@
|
||||
}
|
||||
|
||||
function renderTable(){
|
||||
const pageData = filterByKategoriType(tableState.data || []);
|
||||
const pageData = tableState.data || [];
|
||||
|
||||
if(pageData.length === 0){
|
||||
tbody.innerHTML = `
|
||||
<tr>
|
||||
<td colspan="8" class="text-center text-muted py-4">
|
||||
<td colspan="7" class="text-center text-muted py-4">
|
||||
Tidak ada data yang cocok
|
||||
</td>
|
||||
</tr>
|
||||
@ -682,110 +429,17 @@
|
||||
renderPagination(tableState.lastPage || 1);
|
||||
syncCheckAllState();
|
||||
updateSelectedCount();
|
||||
renderLegend(pageData);
|
||||
}
|
||||
|
||||
function applyTableSearch(){
|
||||
const value = searchInput ? searchInput.value : '';
|
||||
tableState.search = (value || '').trim();
|
||||
tableState.unit = normalizeToArray(
|
||||
unitSelect && window.$ ? $('#tableUnit').val() : tableState.unit
|
||||
);
|
||||
const katVal = kategoriSelect && window.$ ? ($('#tableKategori').val() || '') : (kategoriSelect?.value || '');
|
||||
tableState.kategoriType = katVal ? [katVal] : (tableState.kategoriType || []);
|
||||
tableState.unit = unitSelect && window.$ ? ($('#tableUnit').val() || []) : (tableState.unit || []);
|
||||
tableState.kategori = kategoriSelect && window.$ ? ($('#tableKategori').val() || []) : (tableState.kategori || []);
|
||||
tableState.page = 1;
|
||||
fetchData();
|
||||
}
|
||||
|
||||
function getKategoriLabel(item){
|
||||
const parts = String(item?.file || '').split('/');
|
||||
return (item?.nama_kategori || parts[2] || item?.nama_kategori_directory || item?.kategori || '').trim();
|
||||
}
|
||||
|
||||
function getKategoriId(item){
|
||||
const label = getKategoriLabel(item);
|
||||
return String(item?.master_kategori_directory_id || label);
|
||||
}
|
||||
|
||||
function getKategoriOptionsFromData(){
|
||||
const seen = new Map();
|
||||
(tableState.data || []).forEach(item => {
|
||||
const label = getKategoriLabel(item);
|
||||
if(!label) return;
|
||||
const id = getKategoriId(item);
|
||||
if(!seen.has(id)){
|
||||
seen.set(id, { id, label });
|
||||
}
|
||||
});
|
||||
return Array.from(seen.values()).sort((a,b) => a.label.localeCompare(b.label));
|
||||
}
|
||||
|
||||
function isKategoriMatch(item, types){
|
||||
if (!types.length) return true;
|
||||
const lowerTypes = types.map(t => String(t).toLowerCase());
|
||||
const isAkre = (item.is_akre === true) || String(item.is_akre).toLowerCase() === 'true' || Number(item.is_akre) === 1;
|
||||
const isHukum = !!item.kategori_hukum;
|
||||
const hasKategoriId = !!item.master_kategori_directory_id;
|
||||
// special buckets
|
||||
if (isAkre && lowerTypes.includes('akreditasi')) return true;
|
||||
if (isHukum && lowerTypes.includes('hukum')) return true;
|
||||
if (!isAkre && !isHukum && hasKategoriId && lowerTypes.includes('lainnya')) return true;
|
||||
|
||||
// fallback to id/label comparison
|
||||
const catId = String(getKategoriId(item)).toLowerCase();
|
||||
const catLabel = String(getKategoriLabel(item)).toLowerCase();
|
||||
return lowerTypes.includes(catId) || lowerTypes.includes(catLabel);
|
||||
}
|
||||
|
||||
function filterByKategoriType(items){
|
||||
const types = (tableState.kategoriType || []).map(v => String(v));
|
||||
if (!types.length) return items;
|
||||
return items.filter(item => isKategoriMatch(item, types));
|
||||
}
|
||||
|
||||
function renderKategoriHeaderOptions(){
|
||||
if (!kategoriHeaderMenu) return;
|
||||
const list = kategoriHeaderMenu.querySelector('.kategori-header-list');
|
||||
if (!list) return;
|
||||
const options = kategoriOptionCache.length ? kategoriOptionCache : getKategoriOptionsFromData();
|
||||
const selected = (tableState.kategoriHeader || []).map(v => String(v));
|
||||
if(options.length === 0){
|
||||
list.innerHTML = '<div class=\"dropdown-item text-muted\">Tidak ada kategori</div>';
|
||||
return;
|
||||
}
|
||||
list.innerHTML = options.map(opt => {
|
||||
const checked = selected.includes(opt.id) ? 'checked' : '';
|
||||
return `
|
||||
<label class="dropdown-item d-flex align-items-center gap-2 kategori-option" data-kat="${opt.id}">
|
||||
<input type="checkbox" class="form-check-input m-0" value="${opt.id}" ${checked}>
|
||||
<span>${opt.label}</span>
|
||||
</label>
|
||||
`;
|
||||
}).join('');
|
||||
}
|
||||
|
||||
if (kategoriHeaderMenu) {
|
||||
kategoriHeaderMenu.addEventListener('click', function(e){
|
||||
const option = e.target.closest('.kategori-option');
|
||||
if (!option) return;
|
||||
const id = option.getAttribute('data-kat');
|
||||
const checkbox = option.querySelector('input[type="checkbox"]');
|
||||
if(checkbox){
|
||||
checkbox.checked = !checkbox.checked;
|
||||
const event = new Event('change', { bubbles: true });
|
||||
checkbox.dispatchEvent(event);
|
||||
}else{
|
||||
tableState.kategoriHeader = [id];
|
||||
if (kategoriSelect && window.$ && $.fn.select2) {
|
||||
$('#tableKategori').val(id).trigger('change');
|
||||
}
|
||||
tableState.page = 1;
|
||||
fetchData();
|
||||
}
|
||||
}, true);
|
||||
}
|
||||
|
||||
|
||||
function fetchData(){
|
||||
if(summaryEl) summaryEl.textContent = 'Memuat data...';
|
||||
const params = new URLSearchParams({
|
||||
@ -793,24 +447,18 @@
|
||||
per_page: tableState.pageSize,
|
||||
keyword: tableState.search
|
||||
});
|
||||
const unitValues = normalizeToArray(tableState.unit);
|
||||
if (unitValues.length > 0) {
|
||||
unitValues.forEach(id => params.append('unit[]', id));
|
||||
if (tableState.unit && tableState.unit.length > 0) {
|
||||
tableState.unit.forEach(id => params.append('unit[]', id));
|
||||
}
|
||||
if (tableState.kategoriType && tableState.kategoriType.length > 0) {
|
||||
tableState.kategoriType.forEach(id => params.append('kategori[]', id));
|
||||
}
|
||||
if (tableState.kategoriHeader && tableState.kategoriHeader.length > 0) {
|
||||
tableState.kategoriHeader.forEach(id => params.append('kategori_header[]', id));
|
||||
if (tableState.kategori && tableState.kategori.length > 0) {
|
||||
tableState.kategori.forEach(kat => params.append('kategori[]', kat));
|
||||
}
|
||||
fetch(`/data-internal?${params.toString()}`)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
tableState.data = data?.data || [];
|
||||
kategoriOptionCache = data?.kategori_list || kategoriOptionCache;
|
||||
tableState.lastPage = data?.pagination?.last_page || 1;
|
||||
tableState.total = data?.pagination?.total || 0;
|
||||
renderKategoriHeaderOptions();
|
||||
renderTable();
|
||||
})
|
||||
.catch(error => {
|
||||
@ -819,13 +467,17 @@
|
||||
})
|
||||
}
|
||||
|
||||
searchBtn.addEventListener('click', applyTableSearch);
|
||||
searchInput.addEventListener('keydown', (e) => {
|
||||
if (searchBtn) {
|
||||
searchBtn.addEventListener('click', applyTableSearch);
|
||||
}
|
||||
if (searchInput) {
|
||||
searchInput.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Enter') {
|
||||
e.preventDefault();
|
||||
applyTableSearch();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function formatTanggal(dateString) {
|
||||
const d = new Date(dateString);
|
||||
@ -835,7 +487,6 @@
|
||||
year: 'numeric'
|
||||
});
|
||||
}
|
||||
renderKategoriHeaderOptions();
|
||||
fetchData()
|
||||
|
||||
function updateSelectedCount(){
|
||||
@ -985,8 +636,6 @@
|
||||
});
|
||||
|
||||
selectOptionUnitKerjaV1(0);
|
||||
initKategoriSelect2(0);
|
||||
enableAkreFields(0);
|
||||
});
|
||||
|
||||
function loadSubUnitKerja(unitId){
|
||||
@ -1024,7 +673,7 @@
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Unit <span class="text-danger">*</span></label>
|
||||
<select class="form-select"
|
||||
name="data[${colCount}][id_unit_kerja]"
|
||||
@ -1034,7 +683,7 @@
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Sub Unit <span class="text-danger">*</span></label>
|
||||
<select class="form-select"
|
||||
name="data[${colCount}][id_sub_unit_kerja]"
|
||||
@ -1044,7 +693,20 @@
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Kategori Dokumen <span class="text-danger">*</span></label>
|
||||
<select class="form-select"
|
||||
name="data[${colCount}][master_kategori_directory_id]"
|
||||
id="select_kategori_${colCount}"
|
||||
required>
|
||||
<option value="" disabled selected>Pilih Kategori</option>
|
||||
@foreach ($katDok as $kat)
|
||||
<option value="{{ $kat->master_kategori_directory_id }}/{{ $kat->nama_kategori_directory }}">
|
||||
{{ $kat->nama_kategori_directory }}
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Nomor Dokumen</label>
|
||||
@ -1071,7 +733,7 @@
|
||||
type="date"
|
||||
name="data[${colCount}][date_active]">
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="col-md-2">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input toggle-expired"
|
||||
type="checkbox"
|
||||
@ -1088,7 +750,7 @@
|
||||
name="data[${colCount}][tgl_expired]" disabled>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<div class="col-md-5">
|
||||
<label class="form-label fw-semibold">Boleh dilihat unit lain? <span class="text-danger">*</span></label>
|
||||
|
||||
<div class="border rounded-3 p-2 bg-light">
|
||||
@ -1099,7 +761,7 @@
|
||||
id="perm_yes_${colCount}"
|
||||
value="1"
|
||||
required>
|
||||
<label class="form-check-label" for="perm_yes_${colCount}">Ya</label>
|
||||
<label class="form-check-label" for="perm_yes_${colCount}">Iya</label>
|
||||
</div>
|
||||
|
||||
<div class="form-check mt-1">
|
||||
@ -1114,44 +776,6 @@
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Instrumen Akreditasi </label>
|
||||
<select class="form-select akre-select" id="akre_select_${colCount}" name="data[${colCount}][akre]" style="width: 350px;">
|
||||
<option value="" disabled selected>Pilih Instrumen</option>
|
||||
</select>
|
||||
<div class="form-text text-muted">Isi form ini bila dokumen yang diunggah merupakan dokumen <strong>akreditasi</strong>.</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Kategori Hukum</label>
|
||||
<select class="form-select select-kat-hukum" name="data[${colCount}][kategori_hukum]" id="select_kategori_hukum_${colCount}" style="width: 350px;">
|
||||
<option value="" disabled selected>Pilih Kategori Hukum</option>
|
||||
<option value="Kebijakan - Peraturan Direktur">Kebijakan - Peraturan Direktur</option>
|
||||
<option value="Kebijakan - Keputusan Direktur Utama">Kebijakan - Keputusan Direktur Utama</option>
|
||||
<option value="Kebijakan - Surat Edaran">Kebijakan - Surat Edaran</option>
|
||||
<option value="Kebijakan - Pengumuman">Kebijakan - Pengumuman</option>
|
||||
<option value="Kerjasama - Pelayanan Kesehatan">Kerjasama - Pelayanan Kesehatan</option>
|
||||
<option value="Kerjasama - Management">Kerjasama - Management</option>
|
||||
<option value="Kerjasama - Pemeliharan">Kerjasama - Pemeliharan</option>
|
||||
<option value="Kerjasama - Diklat">Kerjasama - Diklat</option>
|
||||
<option value="Kerjasama - Luar Negeri">Kerjasama - Luar Negeri</option>
|
||||
<option value="Kerjasama - Area Bisnis">Kerjasama - Area Bisnis</option>
|
||||
<option value="Kerjasama - Pendidikan">Kerjasama - Pendidikan</option>
|
||||
<option value="Kerjasama - Pengampuan KIA">Kerjasama- Pengampuan KIA</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Kategori Lainnya</label>
|
||||
<select class="form-select"
|
||||
name="data[${colCount}][master_kategori_directory_id]"
|
||||
id="select_kategori_${colCount}" style="width: 350px;">
|
||||
<option value="" disabled selected>Pilih Kategori</option>
|
||||
@foreach ($katDok as $kat)
|
||||
<option value="{{ $kat->master_kategori_directory_id }}/{{ $kat->nama_kategori_directory }}">
|
||||
{{ $kat->nama_kategori_directory }}
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="col-md-12">
|
||||
<label for="fileUpload_${colCount}" class="form-label fw-semibold">📂 Upload Dokumen (PDF)</label>
|
||||
@ -1168,17 +792,14 @@
|
||||
<div class="form-text text-muted">
|
||||
Format yang didukung: <b>PDF</b>.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
`;
|
||||
col.append(html)
|
||||
selectOptionUnitKerjaV1(colCount)
|
||||
initKategoriSelect2(colCount)
|
||||
enableAkreFields(colCount)
|
||||
setKategoriRequired(colCount, false)
|
||||
colCount++;
|
||||
}
|
||||
</div>
|
||||
`;
|
||||
col.append(html)
|
||||
selectOptionUnitKerjaV1(colCount)
|
||||
colCount++;
|
||||
}
|
||||
|
||||
function removeCol(count){
|
||||
$(`#col-${count}`).remove()
|
||||
|
||||
@ -20,19 +20,28 @@
|
||||
<div class="small text-muted">Lengkapi detail dokumen sebelum upload.</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Unit <span class="text-danger">*</span></label>
|
||||
<select class="form-control unit_kerja" name="data[0][id_unit_kerja]" id="select_id_unit_kerja_0" required>
|
||||
<option value="" disable>Pilih Unit</option>
|
||||
</select>
|
||||
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Sub Unit <span class="text-danger">*</span></label>
|
||||
<select class="form-control" name="data[0][id_sub_unit_kerja]" id="select_id_sub_unit_kerja_0" required>
|
||||
<option value="" disable selected>Pilih Sub Unit</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Kategori Dokumen <span class="text-danger">*</span></label>
|
||||
<select class="form-control" name="data[0][master_kategori_directory_id]" id="select_kategori_0" required>
|
||||
<option value="" disable>Pilih Kategori</option>
|
||||
@foreach ($katDok as $kat)
|
||||
<option value="{{ $kat->master_kategori_directory_id }}/{{ $kat->nama_kategori_directory }}">{{ $kat->nama_kategori_directory }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Nomor Dokumen</label>
|
||||
<div class="input-group">
|
||||
@ -48,26 +57,27 @@
|
||||
<label class="form-label fw-semibold">Tanggal Terbit</label>
|
||||
<input class="form-control" type="date" name="data[0][date_active]">
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="col-md-2">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input toggle-expired" type="checkbox" id="hasExpired0" data-target="expiredField_0">
|
||||
<label class="form-check-label" for="hasExpired0">Masa Berlaku Dokumen?</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4" id="expiredField_0">
|
||||
<div class="col-md-5" id="expiredField_0">
|
||||
<label class="form-label fw-semibold">Tanggal Kedaluwarsa Dokumen</label>
|
||||
<input class="form-control" type="date" name="data[0][tgl_expired]" disabled>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="col-md-5">
|
||||
<label class="form-label fw-semibold">Boleh dilihat unit lain? <span class="text-danger">*</span></label>
|
||||
|
||||
<div class="border rounded-3 p-2 bg-light">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="radio" name="data[0][is_permission]" id="perm_yes" value="1" required>
|
||||
<label class="form-check-label" for="perm_yes">
|
||||
Ya
|
||||
Iya
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="form-check mt-1">
|
||||
<input class="form-check-input" type="radio" name="data[0][is_permission]" id="perm_no" value="2" required>
|
||||
<label class="form-check-label" for="perm_no">
|
||||
@ -75,41 +85,9 @@
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Instrumen Akreditasi</label>
|
||||
<select class="form-select akre-select" name="data[0][akre]" id="akre_select_0" style="width: 350px;">
|
||||
<option value="">Pilih Instrumen</option>
|
||||
</select>
|
||||
<div class="form-text text-muted">Isi form ini bila dokumen yang diunggah merupakan dokumen <strong>akreditasi</strong>.</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Kategori Hukum</label>
|
||||
<select class="form-select select-kat-hukum" name="data[0][kategori_hukum]" id="select_kategori_hukum_0" style="width: 350px;">
|
||||
<option value="">Pilih Kategori Hukum</option>
|
||||
<option value="Kebijakan - Peraturan Direktur">Kebijakan - Peraturan Direktur</option>
|
||||
<option value="Kebijakan - Keputusan Direktur Utama">Kebijakan - Keputusan Direktur Utama</option>
|
||||
<option value="Kebijakan - Surat Edaran">Kebijakan - Surat Edaran</option>
|
||||
<option value="Kebijakan - Pengumuman">Kebijakan - Pengumuman</option>
|
||||
<option value="Kerjasama - Pelayanan Kesehatan">Kerjasama - Pelayanan Kesehatan</option>
|
||||
<option value="Kerjasama - Management">Kerjasama - Management</option>
|
||||
<option value="Kerjasama - Pemeliharan">Kerjasama - Pemeliharan</option>
|
||||
<option value="Kerjasama - Diklat">Kerjasama - Diklat</option>
|
||||
<option value="Kerjasama - Luar Negeri">Kerjasama - Luar Negeri</option>
|
||||
<option value="Kerjasama - Area Bisnis">Kerjasama - Area Bisnis</option>
|
||||
<option value="Kerjasama - Pendidikan">Kerjasama - Pendidikan</option>
|
||||
<option value="Kerjasama - Pengampuan KIA">Kerjasama- Pengampuan KIA</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Kategori lainnya</label>
|
||||
<select class="form-select select-kat-lain" name="data[0][master_kategori_directory_id]" id="select_kategori_0" style="width: 350px;">
|
||||
<option value="">Pilih Kategori</option>
|
||||
@foreach ($katDok as $kat)
|
||||
<option value="{{ $kat->master_kategori_directory_id }}/{{ $kat->nama_kategori_directory }}">{{ $kat->nama_kategori_directory }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="col-md-12 mb-2">
|
||||
<label for="fileUpload0" class="form-label fw-semibold">📂 Upload Dokumen (PDF)</label>
|
||||
<div class="border rounded-3 p-3 bg-white shadow-sm">
|
||||
|
||||
@ -30,7 +30,7 @@
|
||||
<thead class="table-light shadow-sm">
|
||||
<tr>
|
||||
<th style="width:5%;" class="text-center">#</th>
|
||||
<th style="width:30%;">Unit / Akreditasi</th>
|
||||
<th style="width:30%;">Unit</th>
|
||||
<th style="width:20%;">Kategori</th>
|
||||
<th style="width:15%;" class="text-center">Jumlah File</th>
|
||||
</tr>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,152 +0,0 @@
|
||||
@php($showRecapTitle = $showRecapTitle ?? true)
|
||||
<div class="d-flex flex-column flex-md-row align-items-md-center gap-2 mb-3">
|
||||
@if ($showRecapTitle)
|
||||
<div>
|
||||
<h4 class="mb-0">Rekap Dokumen Expired</h4>
|
||||
<small class="text-muted">Ringkasan jumlah file per Unit dan Kategori</small>
|
||||
</div>
|
||||
@endif
|
||||
<div class="{{ $showRecapTitle ? 'ms-md-auto' : '' }} d-flex gap-2 align-items-center">
|
||||
<div class="input-group input-group-sm" style="max-width:320px;">
|
||||
<span class="input-group-text bg-white border-end-0">
|
||||
<i class="fa fa-search text-muted"></i>
|
||||
</span>
|
||||
<input type="search" id="recapSearch" class="form-control border-start-0" placeholder="Cari unit atau folder" oninput="debouncedRecapSearch(this.value)">
|
||||
</div>
|
||||
<select id="recapPerPage" class="form-select form-select-sm" style="width:auto;" onchange="changePerPage(this.value)">
|
||||
<option value="5">5</option>
|
||||
<option value="10" selected>10</option>
|
||||
<option value="20">20</option>
|
||||
<option value="50">50</option>
|
||||
</select>
|
||||
<button class="btn btn-outline-secondary btn-sm d-flex align-items-center gap-1" onclick="fetchRecap()">
|
||||
<i class="fa fa-rotate"></i>
|
||||
<span>Refresh</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-responsive" style="max-height: 55vh; overflow-y:auto;">
|
||||
<table class="table table-sm table-hover align-middle">
|
||||
<thead class="table-light shadow-sm">
|
||||
<tr>
|
||||
<th style="width:5%;" class="text-center">#</th>
|
||||
<th style="width:30%;">Unit / Akreditasi</th>
|
||||
<th style="width:20%;">Kategori</th>
|
||||
<th style="width:15%;" class="text-center">Jumlah File</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="recapBody">
|
||||
<tr>
|
||||
<td colspan="4" class="text-center text-muted py-4">Memuat data...</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="d-flex flex-column flex-md-row align-items-center justify-content-between gap-2 mt-3" id="recapPagination"></div>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', () => fetchRecap());
|
||||
|
||||
let recapDebounce;
|
||||
const recapState = { page:1, perPage:10, keyword:'', lastPage:1 };
|
||||
|
||||
function debouncedRecapSearch(val){
|
||||
clearTimeout(recapDebounce);
|
||||
recapDebounce = setTimeout(() => {
|
||||
recapState.keyword = val;
|
||||
recapState.page = 1;
|
||||
fetchRecap();
|
||||
}, 250);
|
||||
}
|
||||
|
||||
function changePerPage(val){
|
||||
recapState.perPage = parseInt(val) || 10;
|
||||
recapState.page = 1;
|
||||
fetchRecap();
|
||||
}
|
||||
|
||||
function fetchRecap(){
|
||||
const tbody = document.getElementById('recapBody');
|
||||
const pager = document.getElementById('recapPagination');
|
||||
if(!tbody) return;
|
||||
tbody.innerHTML = `<tr><td colspan="4" class="text-center text-muted py-4">Memuat data...</td></tr>`;
|
||||
if(pager) pager.innerHTML = '';
|
||||
|
||||
const params = new URLSearchParams({
|
||||
page: recapState.page,
|
||||
per_page: recapState.perPage,
|
||||
keyword: recapState.keyword || ''
|
||||
});
|
||||
fetch('/data/recapExp?' + params.toString())
|
||||
.then(res => res.json())
|
||||
.then(json => {
|
||||
const rows = json?.data || [];
|
||||
recapState.lastPage = json?.pagination?.last_page || 1;
|
||||
if(!rows.length){
|
||||
tbody.innerHTML = `<tr><td colspan="4" class="text-center text-muted py-4">Tidak ada data</td></tr>`;
|
||||
return;
|
||||
}
|
||||
let grandTotal = 0;
|
||||
const html = rows.map((row, idx) => {
|
||||
const folderRows = (row.data || []).map((f, i) => `
|
||||
<tr>
|
||||
${i === 0 ? `<td rowspan="${row.data.length}" class="text-center align-middle fw-semibold">${idx+1}</td>` : ''}
|
||||
${i === 0 ? `<td rowspan="${row.data.length}" class="fw-semibold">${row.unit || '-'}</td>` : ''}
|
||||
<td>${f.folder || '-'}</td>
|
||||
<td class="text-center fw-bold">${f.count || 0}</td>
|
||||
</tr>
|
||||
`).join('');
|
||||
(row.data || []).forEach(f => { grandTotal += (parseInt(f.count, 10) || 0); });
|
||||
return folderRows;
|
||||
}).join('');
|
||||
tbody.innerHTML = html + `
|
||||
<tr class="table-light">
|
||||
<td colspan="3" class="text-end fw-semibold">Total File</td>
|
||||
<td class="text-center fw-bold">${grandTotal}</td>
|
||||
</tr>
|
||||
`;
|
||||
renderRecapPagination();
|
||||
})
|
||||
.catch(err => {
|
||||
console.error(err);
|
||||
tbody.innerHTML = `<tr><td colspan="4" class="text-center text-danger py-4">Gagal memuat data</td></tr>`;
|
||||
});
|
||||
}
|
||||
|
||||
function renderRecapPagination(){
|
||||
const pager = document.getElementById('recapPagination');
|
||||
if(!pager) return;
|
||||
if(recapState.lastPage <= 1){
|
||||
pager.innerHTML = '';
|
||||
return;
|
||||
}
|
||||
const maxButtons = 5;
|
||||
let start = Math.max(1, recapState.page - Math.floor(maxButtons/2));
|
||||
let end = Math.min(recapState.lastPage, start + maxButtons - 1);
|
||||
start = Math.max(1, end - maxButtons + 1);
|
||||
|
||||
let buttons = '';
|
||||
buttons += `<button class="btn btn-outline-secondary btn-sm" data-page="prev" ${recapState.page === 1 ? 'disabled' : ''}>‹</button>`;
|
||||
for(let i=start; i<=end; i++){
|
||||
buttons += `<button class="btn btn-sm ${i === recapState.page ? 'btn-primary' : 'btn-outline-secondary'}" data-page="${i}">${i}</button>`;
|
||||
}
|
||||
buttons += `<button class="btn btn-outline-secondary btn-sm" data-page="next" ${recapState.page === recapState.lastPage ? 'disabled' : ''}>›</button>`;
|
||||
|
||||
pager.innerHTML = `
|
||||
<div class="d-flex align-items-center gap-2 flex-wrap">
|
||||
<div class="btn-group" role="group">${buttons}</div>
|
||||
<span class="small text-muted">Halaman ${recapState.page} dari ${recapState.lastPage}</span>
|
||||
</div>
|
||||
`;
|
||||
|
||||
pager.querySelectorAll('button[data-page]').forEach(btn => {
|
||||
btn.addEventListener('click', () => {
|
||||
const page = btn.getAttribute('data-page');
|
||||
if(page === 'prev' && recapState.page > 1) recapState.page--;
|
||||
else if(page === 'next' && recapState.page < recapState.lastPage) recapState.page++;
|
||||
else if(!isNaN(parseInt(page))) recapState.page = parseInt(page);
|
||||
fetchRecap();
|
||||
});
|
||||
});
|
||||
}
|
||||
</script>
|
||||
@ -41,47 +41,38 @@
|
||||
<span class="hide-menu">Dokumen Umum</span>
|
||||
</a>
|
||||
</li>
|
||||
@if(Auth::guard('admin')->check() || (Auth::check() && auth()->user()->dataUser->mappingUnitKerjaPegawai()->whereIn('objectunitkerjapegawaifk', [51, 22])->exists()))
|
||||
<li class="sidebar-item">
|
||||
<a class="sidebar-link" href="{{ url('/data-akreditasi') }}" aria-expanded="false">
|
||||
<i class="fa-solid fa-sliders"></i>
|
||||
<span class="hide-menu">Dokumen Akreditasi</span>
|
||||
</a>
|
||||
</li>
|
||||
@endif
|
||||
|
||||
{{-- AKTIVITAS --}}
|
||||
<li class="nav-small-cap"><span class="hide-menu">Aktivitas</span></li>
|
||||
|
||||
|
||||
@php
|
||||
$isAtasan = \App\Models\MappingUnitKerjaPegawai::where('statusenabled', true)->where('objectatasanlangsungfk', auth()->user()->objectpegawaifk)->exists();
|
||||
@endphp
|
||||
@if($isAtasan)
|
||||
@if(!Auth::guard('admin')->check())
|
||||
<li class="sidebar-item">
|
||||
<a class="sidebar-link d-flex align-items-center justify-content-between"
|
||||
href="{{ url('/pending-file') }}" aria-expanded="false">
|
||||
<li class="sidebar-item">
|
||||
<a class="sidebar-link d-flex align-items-center justify-content-between"
|
||||
href="{{ url('/pending-file') }}" aria-expanded="false">
|
||||
|
||||
<div class="d-flex align-items-center gap-3">
|
||||
<i class="ti ti-clock"></i>
|
||||
<span class="hide-menu">Persetujuan</span>
|
||||
</div>
|
||||
<div class="d-flex align-items-center gap-3">
|
||||
<i class="ti ti-clock"></i>
|
||||
<span class="hide-menu">Persetujuan</span>
|
||||
</div>
|
||||
|
||||
<span class="badge bg-danger rounded-pill d-none" id="pendingCountBadge">0</span>
|
||||
</a>
|
||||
</li>
|
||||
@endif
|
||||
<span class="badge bg-danger rounded-pill d-none" id="pendingCountBadge">0</span>
|
||||
</a>
|
||||
</li>
|
||||
@else
|
||||
@if(!Auth::guard('admin')->check())
|
||||
<li class="sidebar-item">
|
||||
<a class="sidebar-link d-flex align-items-center justify-content-between"
|
||||
href="{{ url('/pengajuan-file') }}" aria-expanded="false">
|
||||
<li class="sidebar-item">
|
||||
<a class="sidebar-link d-flex align-items-center justify-content-between"
|
||||
href="{{ url('/pengajuan-file') }}" aria-expanded="false">
|
||||
|
||||
<div class="d-flex align-items-center gap-3">
|
||||
<i class="ti ti-clock"></i>
|
||||
<span class="hide-menu">Pengajuan</span>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
@endif
|
||||
<div class="d-flex align-items-center gap-3">
|
||||
<i class="ti ti-clock"></i>
|
||||
<span class="hide-menu">Pengajuan</span>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
@endif
|
||||
<li class="sidebar-item">
|
||||
<a class="sidebar-link d-flex align-items-center justify-content-between"
|
||||
@ -106,14 +97,6 @@
|
||||
</li> --}}
|
||||
|
||||
{{-- MASTER --}}
|
||||
<li class="nav-small-cap"><span class="hide-menu">History</span></li>
|
||||
<li class="sidebar-item">
|
||||
<a class="sidebar-link" href="{{ url('/expired-dokumen') }}" aria-expanded="false">
|
||||
<i class="ti ti-clock"></i>
|
||||
<span class="hide-menu">Expired Dokumen</span>
|
||||
</a>
|
||||
</li>
|
||||
@if(!Auth::guard('admin')->check())
|
||||
@if(auth()->user()->dataUser->mappingUnitKerjaPegawai()->where('objectunitkerjapegawaifk', 43)->exists())
|
||||
<li class="nav-small-cap"><span class="hide-menu">Master</span></li>
|
||||
|
||||
@ -154,7 +137,6 @@
|
||||
</ul>
|
||||
</li>
|
||||
@endif
|
||||
@endif
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
@ -78,7 +78,7 @@
|
||||
<div class="message-body">
|
||||
<a href="javascript:void(0)" class="d-flex align-items-center gap-2 dropdown-item">
|
||||
<i class="ti ti-user fs-6"></i>
|
||||
<p class="mb-0 fs-3">{{ auth()->user()->namauser ?? 'admin' }}</p>
|
||||
<p class="mb-0 fs-3">{{ auth()->user()->namauser }}</p>
|
||||
</a>
|
||||
<form action="/logout" method="POST">
|
||||
@csrf
|
||||
|
||||
@ -139,7 +139,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
const paginationBtns = document.getElementById('logPaginationBtns');
|
||||
const summaryText = document.getElementById('logSummaryText');
|
||||
|
||||
if(tbody) tbody.innerHTML = '<tr><td colspan="5" class="text-center text-muted py-3">Memuat...</td></tr>';
|
||||
if(tbody) tbody.innerHTML = '<tr><td colspan="4" class="text-center text-muted py-3">Memuat...</td></tr>';
|
||||
if(summaryText) summaryText.textContent = 'Memuat data...';
|
||||
if(searchInput) searchInput.value = keyword || '';
|
||||
|
||||
@ -160,12 +160,11 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
<td>${((currentPage - 1) * (pagination.per_page || 10)) + idx + 1}</td>
|
||||
<td>${row.pegawai_nama_entry || '-'}</td>
|
||||
<td>${row.total_open || 0}</td>
|
||||
<td>${row.total_download || 0}</td>
|
||||
<td>${formatTanggal(row.last_open)}</td>
|
||||
</tr>
|
||||
`).join('');
|
||||
|
||||
const emptyState = logs.length === 0 ? '<tr><td colspan="6" class="text-center text-muted py-3">Belum ada aktivitas</td></tr>' : '';
|
||||
const emptyState = logs.length === 0 ? '<tr><td colspan="4" class="text-center text-muted py-3">Belum ada aktivitas</td></tr>' : '';
|
||||
if(tbody) tbody.innerHTML = logs.length ? rows : emptyState;
|
||||
|
||||
if(summaryText){
|
||||
@ -256,7 +255,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
if(pageData.length === 0){
|
||||
tbody.innerHTML = `
|
||||
<tr>
|
||||
<td colspan="7" class="text-center text-muted py-4">
|
||||
<td colspan="6" class="text-center text-muted py-4">
|
||||
Tidak ada data
|
||||
</td>
|
||||
</tr>
|
||||
@ -342,7 +341,6 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
<th>#</th>
|
||||
<th>Nama</th>
|
||||
<th>Jumlah Membuka</th>
|
||||
<th>Jumlah Mengunduh</th>
|
||||
<th>Terakhir Dilihat</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
@ -18,18 +18,27 @@
|
||||
<div class="small text-muted">Perbarui detail dokumen sebelum mengirim ulang.</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Unit <span class="text-danger">*</span></label>
|
||||
<select class="form-control unit_kerja" name="id_unit_kerja" id="edit_id_unit_kerja" required>
|
||||
<option value="" disabled selected>Pilih Unit</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Sub Unit <span class="text-danger">*</span></label>
|
||||
<select class="form-control sub_unit_kerja" name="id_sub_unit_kerja" id="edit_id_sub_unit_kerja" required>
|
||||
<option value="" disabled selected>Pilih Sub Unit</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Kategori Dokumen <span class="text-danger">*</span></label>
|
||||
<select class="form-control" name="master_kategori_directory_id" id="edit_kategori" required>
|
||||
<option value="" disabled selected>Pilih Kategori</option>
|
||||
@foreach ($katDok as $kat)
|
||||
<option value="{{ $kat->master_kategori_directory_id }}/{{ $kat->nama_kategori_directory }}">{{ $kat->nama_kategori_directory }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Nomor Dokumen</label>
|
||||
@ -46,22 +55,22 @@
|
||||
<label class="form-label fw-semibold">Tanggal Terbit</label>
|
||||
<input class="form-control" type="date" name="tanggal_terbit" id="edit_tanggal_terbit">
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="col-md-2 d-flex align-items-end">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input toggle-expired" type="checkbox" id="edit_has_expired" data-target="edit_expired_field">
|
||||
<label class="form-check-label" for="edit_has_expired">Masa Berlaku Dokumen?</label>
|
||||
<input class="form-check-input" type="checkbox" id="edit_has_expired" data-target="edit_expired_field">
|
||||
<label class="form-check-label" for="edit_has_expired">Ada Expired?</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4" id="edit_expired_field">
|
||||
<div class="col-md-5" id="edit_expired_field">
|
||||
<label class="form-label fw-semibold">Tanggal Kedaluwarsa Dokumen</label>
|
||||
<input class="form-control" type="date" name="tgl_expired" id="edit_tgl_expired" disabled>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="col-md-5">
|
||||
<label class="form-label fw-semibold">Boleh dilihat unit lain? <span class="text-danger">*</span></label>
|
||||
<div class="border rounded-3 p-2 bg-light">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="radio" name="permission_file" id="edit_perm_yes" value="1" required>
|
||||
<label class="form-check-label" for="edit_perm_yes">Ya</label>
|
||||
<label class="form-check-label" for="edit_perm_yes">Iya</label>
|
||||
</div>
|
||||
<div class="form-check mt-1">
|
||||
<input class="form-check-input" type="radio" name="permission_file" id="edit_perm_no" value="0" required>
|
||||
@ -70,41 +79,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Instrumen Akreditasi</label>
|
||||
<select class="form-select akre-select" id="edit_akre_select" name="akre" style="width: 350px;">
|
||||
<option value="">Pilih Instrumen</option>
|
||||
</select>
|
||||
<div class="form-text text-muted">Isi form ini bila dokumen yang diunggah merupakan dokumen <strong>akreditasi</strong>.</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Kategori Hukum</label>
|
||||
<select class="form-select select-kat-hukum" name="kategori_hukum" id="edit_kategori_hukum" style="width: 350px;">
|
||||
<option value="">Pilih Kategori Hukum</option>
|
||||
<option value="Kebijakan - Peraturan Direktur">Kebijakan - Peraturan Direktur</option>
|
||||
<option value="Kebijakan - Keputusan Direktur Utama">Kebijakan - Keputusan Direktur Utama</option>
|
||||
<option value="Kebijakan - Surat Edaran">Kebijakan - Surat Edaran</option>
|
||||
<option value="Kebijakan - Pengumuman">Kebijakan - Pengumuman</option>
|
||||
<option value="Kerjasama - Pelayanan Kesehatan">Kerjasama - Pelayanan Kesehatan</option>
|
||||
<option value="Kerjasama - Management">Kerjasama - Management</option>
|
||||
<option value="Kerjasama - Pemeliharan">Kerjasama - Pemeliharan</option>
|
||||
<option value="Kerjasama - Diklat">Kerjasama - Diklat</option>
|
||||
<option value="Kerjasama - Luar Negeri">Kerjasama - Luar Negeri</option>
|
||||
<option value="Kerjasama - Area Bisnis">Kerjasama - Area Bisnis</option>
|
||||
<option value="Kerjasama - Pendidikan">Kerjasama - Pendidikan</option>
|
||||
<option value="Kerjasama - Pengampuan KIA">Kerjasama- Pengampuan KIA</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Kategori lainnya</label>
|
||||
<select class="form-select" name="master_kategori_directory_id" id="edit_kategori" style="width: 350px;">
|
||||
<option value="">Pilih Kategori</option>
|
||||
@foreach ($katDok as $kat)
|
||||
<option value="{{ $kat->master_kategori_directory_id }}/{{ $kat->nama_kategori_directory }}">{{ $kat->nama_kategori_directory }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="col-md-12 mb-2">
|
||||
<label for="edit_file_upload" class="form-label fw-semibold">📂 Upload Dokumen (PDF)</label>
|
||||
<div class="border rounded-3 p-3 bg-white shadow-sm">
|
||||
|
||||
@ -9,15 +9,13 @@ use App\Http\Controllers\LogActivityController;
|
||||
use App\Http\Controllers\masterPersetujuanController;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
Route::middleware(['auth:admin,web'])->group(function(){
|
||||
Route::middleware(['auth'])->group(function(){
|
||||
|
||||
Route::get('/', [DashboardController::class, 'index']);
|
||||
Route::get('/data-internal', [DashboardController::class, 'dataUnitInternal']);
|
||||
Route::get('/download-excel/data-unit', [DashboardController::class, 'downloadDataUnitExcel']);
|
||||
Route::get('/data-umum', [DashboardController::class, 'dataUmum']);
|
||||
Route::get('/datatable-umum', [DashboardController::class, 'datatableDataUmum']);
|
||||
Route::get('/data-akreditasi', [DashboardController::class, 'dataAkreditasi']);
|
||||
Route::get('/datatable-akreditasi', [DashboardController::class, 'dataTableAkreditasi']);
|
||||
Route::get('/download-excel/data-umum', [DashboardController::class, 'downloadDataUmumExcel']);
|
||||
Route::post('/uploadv2', [DashboardController::class, 'storeVersion2']);
|
||||
Route::get('/file-preview/{id}', [DashboardController::class, 'dataPdf']);
|
||||
@ -66,22 +64,18 @@ Route::middleware(['auth:admin,web'])->group(function(){
|
||||
Route::post('/pengajuan-file/{id}/update', [DashboardController::class, 'updatePengajuanFile']);
|
||||
|
||||
// Route::middleware(['master.persetujuan'])->group(function () {
|
||||
Route::get('/pending-file', [DashboardController::class, 'pendingFile']);
|
||||
Route::get('/datatable/pending-file', [DashboardController::class, 'dataPendingFile']);
|
||||
Route::post('/pending-file/{id}/approve', [DashboardController::class, 'approvePendingFile']);
|
||||
Route::post('/pending-file/approve-multiple', [DashboardController::class, 'approvePendingFileMultiple']);
|
||||
Route::post('/pending-file/{id}/reject', [DashboardController::class, 'rejectPendingFile']);
|
||||
Route::get('/data/count-pending', [DashboardController::class, 'countDataPending']);
|
||||
Route::get('/data/count-rejected', [DashboardController::class, 'countRejectedPengajuan']);
|
||||
Route::get('/pending-file', [DashboardController::class, 'pendingFile']);
|
||||
Route::get('/datatable/pending-file', [DashboardController::class, 'dataPendingFile']);
|
||||
Route::post('/pending-file/{id}/approve', [DashboardController::class, 'approvePendingFile']);
|
||||
Route::post('/pending-file/approve-multiple', [DashboardController::class, 'approvePendingFileMultiple']);
|
||||
Route::post('/pending-file/{id}/reject', [DashboardController::class, 'rejectPendingFile']);
|
||||
Route::get('/data/count-pending', [DashboardController::class, 'countDataPending']);
|
||||
Route::get('/data/count-rejected', [DashboardController::class, 'countRejectedPengajuan']);
|
||||
// });
|
||||
Route::get('/data/notifications', [DashboardController::class, 'notifkasiList']);
|
||||
Route::post('/data/notifications/read', [DashboardController::class, 'notifkasiMarkRead']);
|
||||
|
||||
Route::get('/data/log-dokumen', [DashboardController::class, 'logDokumen']);
|
||||
|
||||
Route::get('/expired-dokumen', [DashboardController::class, 'expDokumen']);
|
||||
Route::get('/data/expired-dokumen', [DashboardController::class, 'dataUnitExp']);
|
||||
Route::get('/data/recapExp', [DashboardController::class, 'recapDataExp']);
|
||||
});
|
||||
|
||||
Route::get('/login', [AuthController::class, 'index'])->name('login');
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user