progress action approval
This commit is contained in:
parent
44c4689f77
commit
093a8f2b4d
@ -3,9 +3,9 @@
|
|||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
use App\Models\AksesFile;
|
use App\Models\AksesFile;
|
||||||
|
use App\Models\AksesFileDetail;
|
||||||
use App\Models\DataUser;
|
use App\Models\DataUser;
|
||||||
use App\Models\FileDirectory;
|
use App\Models\FileDirectory;
|
||||||
use App\Models\MappingUnitKerjaPegawai;
|
|
||||||
use App\Models\UnitKerja;
|
use App\Models\UnitKerja;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
@ -41,21 +41,25 @@ class AksesFileController extends Controller
|
|||||||
try {
|
try {
|
||||||
$datas = request('data');
|
$datas = request('data');
|
||||||
foreach ($datas as $data) {
|
foreach ($datas as $data) {
|
||||||
$pegawai = MappingUnitKerjaPegawai::where(['objectpegawaifk'=> $data['pegawai_id'], 'statusenabled' => true])->first();
|
|
||||||
$payload = [
|
$payload = [
|
||||||
'pegawai_id' => $data['pegawai_id'],
|
'pegawai_id' => $data['pegawai_id'],
|
||||||
'pegawai_id_entry' => auth()->user()?->dataUser?->id,
|
'pegawai_id_entry' => auth()->user()?->dataUser?->id,
|
||||||
'pegawai_nama_entry' => auth()->user()?->dataUser?->namalengkap,
|
'pegawai_nama_entry' => auth()->user()?->dataUser?->namalengkap,
|
||||||
'entry_at' => Carbon::now()->format('Y-m-d H:i:s.u'),
|
'entry_at' => Carbon::now()->format('Y-m-d H:i:s.u'),
|
||||||
|
'all_akses' => $data['akses'] === "all" ? true : false,
|
||||||
];
|
];
|
||||||
if($data['akses'] === "all"){
|
$af = AksesFile::create($payload);
|
||||||
$payload['all_akses'] = true;
|
if($data['akses'] === "unit"){
|
||||||
}else{
|
$unitIds = collect($data['unit_akses'] ?? [])->filter()->unique()->values();
|
||||||
$payload['all_akses'] = false;
|
foreach ($unitIds as $unitId) {
|
||||||
$payload['unit_akses'] = $pegawai->objectunitkerjapegawaifk ?? null;
|
$payloadDetail = [
|
||||||
|
'akses_file_id' => $af->akses_file_id,
|
||||||
|
'statusenabled' => true,
|
||||||
|
'id_unit_kerja' => $unitId,
|
||||||
|
];
|
||||||
|
AksesFileDetail::create($payloadDetail);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
AksesFile::create($payload);
|
|
||||||
}
|
}
|
||||||
DB::connection('dbDirectory')->commit();
|
DB::connection('dbDirectory')->commit();
|
||||||
return response()->json([
|
return response()->json([
|
||||||
@ -76,7 +80,55 @@ class AksesFileController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function show(string $id)
|
public function show(string $id)
|
||||||
{
|
{
|
||||||
//
|
$data = AksesFile::where('akses_file_id', $id)->first();
|
||||||
|
if (!$data) {
|
||||||
|
return response()->json([
|
||||||
|
'status' => false,
|
||||||
|
'message' => 'Data tidak ditemukan'
|
||||||
|
], 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
$aksesAll = $data->akses ?? null;
|
||||||
|
if (is_null($aksesAll)) {
|
||||||
|
$aksesAll = $data->all_akses ?? null;
|
||||||
|
}
|
||||||
|
$aksesType = $aksesAll ? 'all' : 'unit';
|
||||||
|
|
||||||
|
$units = [];
|
||||||
|
$detailUnits = AksesFileDetail::where('akses_file_id', $id)
|
||||||
|
->where('statusenabled', true)
|
||||||
|
->get();
|
||||||
|
if ($detailUnits->isNotEmpty()) {
|
||||||
|
$unitIds = $detailUnits->pluck('id_unit_kerja');
|
||||||
|
$units = UnitKerja::whereIn('id', $unitIds)
|
||||||
|
->select('id', 'name')
|
||||||
|
->get()
|
||||||
|
->map(function ($unit) {
|
||||||
|
return [
|
||||||
|
'id' => $unit->id,
|
||||||
|
'text' => $unit->name,
|
||||||
|
];
|
||||||
|
})
|
||||||
|
->values();
|
||||||
|
} elseif (!empty($data->unit_akses)) {
|
||||||
|
$unit = UnitKerja::where('id', $data->unit_akses)->select('id', 'name')->first();
|
||||||
|
if ($unit) {
|
||||||
|
$units[] = [
|
||||||
|
'id' => $unit->id,
|
||||||
|
'text' => $unit->name,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'status' => true,
|
||||||
|
'data' => [
|
||||||
|
'akses_type' => $aksesType,
|
||||||
|
'pegawai_id' => $data->pegawai_id,
|
||||||
|
'pegawai_nama' => $data?->pegawai?->namalengkap,
|
||||||
|
'units' => $units,
|
||||||
|
]
|
||||||
|
], 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -92,19 +144,40 @@ class AksesFileController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function update(Request $request, string $id)
|
public function update(Request $request, string $id)
|
||||||
{
|
{
|
||||||
|
DB::connection('dbDirectory')->beginTransaction();
|
||||||
try {
|
try {
|
||||||
$data = AksesFile::where('akses_file_id', $id)->first();
|
$data = AksesFile::where('akses_file_id', $id)->first();
|
||||||
$pegawai = MappingUnitKerjaPegawai::where(['objectpegawaifk' => request('pegawai_id'), 'statusenabled' => true])->first();
|
if (!$data) {
|
||||||
|
return response()->json([
|
||||||
|
'status' => false,
|
||||||
|
'message' => 'Data tidak ditemukan'
|
||||||
|
], 404);
|
||||||
|
}
|
||||||
|
|
||||||
$payload = [
|
$payload = [
|
||||||
'pegawai_id' => request('pegawai_id'),
|
'pegawai_id' => request('pegawai_id'),
|
||||||
'pegawai_id_modified' => auth()->user()?->dataUser?->id,
|
'pegawai_id_modified' => auth()->user()?->dataUser?->id,
|
||||||
'pegawai_nama_modified' => auth()->user()?->dataUser?->namalengkap,
|
'pegawai_nama_modified' => auth()->user()?->dataUser?->namalengkap,
|
||||||
'modified_at' => Carbon::now()->format('Y-m-d H:i:s.u'),
|
'modified_at' => Carbon::now()->format('Y-m-d H:i:s.u'),
|
||||||
'all_akses' => request('akses') === "all" ? true : false,
|
'all_akses' => request('akses') === "all" ? true : false,
|
||||||
'unit_akses' => $pegawai?->objectunitkerjapegawaifk ?? null
|
|
||||||
];
|
];
|
||||||
$data->update($payload);
|
$data->update($payload);
|
||||||
|
|
||||||
|
AksesFileDetail::where('akses_file_id', $id)->delete();
|
||||||
|
|
||||||
|
if (request('akses') === 'unit') {
|
||||||
|
$unitIds = collect(request('unit_akses') ?? [])->filter()->unique()->values();
|
||||||
|
foreach ($unitIds as $unitId) {
|
||||||
|
$payloadDetail = [
|
||||||
|
'akses_file_id' => $data->akses_file_id,
|
||||||
|
'statusenabled' => true,
|
||||||
|
'id_unit_kerja' => $unitId,
|
||||||
|
];
|
||||||
|
AksesFileDetail::create($payloadDetail);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DB::connection('dbDirectory')->commit();
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'status' => true,
|
'status' => true,
|
||||||
'message' => 'Data berhasil diperbarui',
|
'message' => 'Data berhasil diperbarui',
|
||||||
@ -123,26 +196,43 @@ class AksesFileController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function destroy(string $id)
|
public function destroy(string $id)
|
||||||
{
|
{
|
||||||
$data = AksesFile::where('akses_file_id', $id)->first();
|
try {
|
||||||
if(!$data){
|
$data = AksesFile::where('akses_file_id', $id)
|
||||||
|
->where('statusenabled', true)
|
||||||
|
->first();
|
||||||
|
|
||||||
|
if (!$data) {
|
||||||
|
return response()->json([
|
||||||
|
'status' => false,
|
||||||
|
'message' => 'Data tidak ditemukan'
|
||||||
|
], 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
DB::transaction(function () use ($id, $data) {
|
||||||
|
AksesFileDetail::where('akses_file_id', $id)
|
||||||
|
->where('statusenabled', true)
|
||||||
|
->update(['statusenabled' => false]);
|
||||||
|
$data->update(['statusenabled' => false]);
|
||||||
|
});
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'status' => true,
|
||||||
|
'message' => 'Data berhasil dihapus'
|
||||||
|
], 200);
|
||||||
|
|
||||||
|
} catch (\Throwable $th) {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'status' => false,
|
'status' => false,
|
||||||
'message' => 'Data tidak ditemukan'
|
'message' => 'Gagal menghapus data',
|
||||||
], 404);
|
], 500);
|
||||||
}
|
}
|
||||||
$payload =[
|
|
||||||
'statusenabled' => false
|
|
||||||
];
|
|
||||||
$data->update($payload);
|
|
||||||
return response()->json([
|
|
||||||
'status' => true,
|
|
||||||
'message' => 'Data berhasil dihapus'
|
|
||||||
], 200);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function datatable(){
|
public function datatable(){
|
||||||
return AksesFile::where('statusenabled', true)->get();
|
return AksesFile::with(['details.unit'])
|
||||||
|
->where('statusenabled', true)
|
||||||
|
->get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function optionPegawai(){
|
public function optionPegawai(){
|
||||||
|
|||||||
@ -3,12 +3,14 @@
|
|||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
use App\Models\AksesFile;
|
use App\Models\AksesFile;
|
||||||
|
use App\Models\AksesFileDetail;
|
||||||
use App\Models\FileDirectory;
|
use App\Models\FileDirectory;
|
||||||
use App\Models\LogActivity;
|
use App\Models\LogActivity;
|
||||||
use App\Models\MasterKategori;
|
use App\Models\MasterKategori;
|
||||||
use App\Models\MasterKlasifikasi;
|
use App\Models\MasterKlasifikasi;
|
||||||
use App\Models\SubUnitKerja;
|
use App\Models\SubUnitKerja;
|
||||||
use App\Models\UnitKerja;
|
use App\Models\UnitKerja;
|
||||||
|
use Carbon\Carbon;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
@ -43,19 +45,37 @@ class DashboardController extends Controller
|
|||||||
public function dataUnitKerja(){
|
public function dataUnitKerja(){
|
||||||
$user = auth()->user()?->dataUser;
|
$user = auth()->user()?->dataUser;
|
||||||
$akses = AksesFile::where(['pegawai_id' => $user->id, 'statusenabled' => true])->first();
|
$akses = AksesFile::where(['pegawai_id' => $user->id, 'statusenabled' => true])->first();
|
||||||
|
$aksesAll = $akses?->akses ?? $akses?->all_akses ?? false;
|
||||||
|
$detailUnitIds = collect();
|
||||||
|
if ($akses?->akses_file_id) {
|
||||||
|
$detailUnitIds = AksesFileDetail::where('akses_file_id', $akses->akses_file_id)
|
||||||
|
->where('statusenabled', true)
|
||||||
|
->pluck('id_unit_kerja')
|
||||||
|
->unique()
|
||||||
|
->values();
|
||||||
|
}
|
||||||
|
$allowedUnitIds = null;
|
||||||
|
if (!$aksesAll) {
|
||||||
|
if ($detailUnitIds->isNotEmpty()) {
|
||||||
|
$allowedUnitIds = $detailUnitIds;
|
||||||
|
} elseif (!empty($akses?->unit_akses)) {
|
||||||
|
$allowedUnitIds = collect([$akses->unit_akses]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$kategori = request('kategori');
|
$kategori = request('kategori');
|
||||||
$filterUnit = request('unitKerja');
|
$filterUnit = request('unitKerja');
|
||||||
$subUnit = request('subUnit');
|
$subUnit = request('subUnit');
|
||||||
$klasifikasi = request('klasifikasi');
|
|
||||||
$keyword = request('keyword');
|
$keyword = request('keyword');
|
||||||
$subArray = $subUnit ? explode(',', $subUnit) : [];
|
$subArray = $subUnit ? explode(',', $subUnit) : [];
|
||||||
$katArray = $kategori ? explode(',', $kategori) : [];
|
$katArray = $kategori ? explode(',', $kategori) : [];
|
||||||
$klaArray = $klasifikasi ? explode(',', $klasifikasi) : [];
|
|
||||||
$katDok = MasterKategori::when($katArray, fn($q) => $q->whereIn('master_kategori_directory_id', $katArray))->where('statusenabled', true)->select('master_kategori_directory_id', 'nama_kategori_directory')->get();
|
$katDok = MasterKategori::when($katArray, fn($q) => $q->whereIn('master_kategori_directory_id', $katArray))->where('statusenabled', true)->select('master_kategori_directory_id', 'nama_kategori_directory')->get();
|
||||||
|
|
||||||
if ($katArray && $filterUnit && $subArray && $klaArray) {
|
if ($katArray && $filterUnit && $subArray) {
|
||||||
/* mode pencarian lengkap */
|
/* mode pencarian lengkap */
|
||||||
|
if ($allowedUnitIds && !$allowedUnitIds->contains((int) $filterUnit)) {
|
||||||
|
$unitKerja = collect();
|
||||||
|
} else {
|
||||||
$unitKerja = UnitKerja::where('statusenabled', true)
|
$unitKerja = UnitKerja::where('statusenabled', true)
|
||||||
->where('id', $filterUnit)
|
->where('id', $filterUnit)
|
||||||
->with(['subUnitKerja' => fn($q) => $q->whereIn('id', $subArray)
|
->with(['subUnitKerja' => fn($q) => $q->whereIn('id', $subArray)
|
||||||
@ -63,7 +83,6 @@ class DashboardController extends Controller
|
|||||||
->where('id_unit_kerja', $filterUnit)
|
->where('id_unit_kerja', $filterUnit)
|
||||||
->when($subArray, fn($q) => $q->whereIn('id_sub_unit_kerja', $subArray))
|
->when($subArray, fn($q) => $q->whereIn('id_sub_unit_kerja', $subArray))
|
||||||
->when($katArray, fn($q) => $q->whereIn('master_kategori_directory_id', $katArray))
|
->when($katArray, fn($q) => $q->whereIn('master_kategori_directory_id', $katArray))
|
||||||
->when($klaArray, fn($q) => $q->whereIn('master_klasifikasi_directory_id', $klaArray))
|
|
||||||
->when($keyword, fn($q) =>
|
->when($keyword, fn($q) =>
|
||||||
$q->where(function($query) use ($keyword) {
|
$q->where(function($query) use ($keyword) {
|
||||||
$query->where('file', 'ilike', "%{$keyword}%")
|
$query->where('file', 'ilike', "%{$keyword}%")
|
||||||
@ -74,8 +93,9 @@ class DashboardController extends Controller
|
|||||||
])
|
])
|
||||||
->select('id', 'name')
|
->select('id', 'name')
|
||||||
->get();
|
->get();
|
||||||
|
}
|
||||||
|
|
||||||
} elseif ($akses?->all_akses) {
|
} elseif ($aksesAll) {
|
||||||
/* all akses */
|
/* all akses */
|
||||||
$unitKerja = UnitKerja::where('statusenabled', true)->with([ // muat relasi
|
$unitKerja = UnitKerja::where('statusenabled', true)->with([ // muat relasi
|
||||||
'subUnitKerja' => fn($q) => $q->with([ // sub-unit
|
'subUnitKerja' => fn($q) => $q->with([ // sub-unit
|
||||||
@ -88,9 +108,10 @@ class DashboardController extends Controller
|
|||||||
->select('id', 'name')
|
->select('id', 'name')
|
||||||
->get();
|
->get();
|
||||||
|
|
||||||
} elseif ($akses?->unit_akses) {
|
} elseif ($allowedUnitIds) {
|
||||||
/* akses per unit */
|
/* akses per unit (single/multiple) */
|
||||||
$unitKerja = UnitKerja::where(['statusenabled' => true, 'id' => $akses->unit_akses])
|
$unitKerja = UnitKerja::where('statusenabled', true)
|
||||||
|
->whereIn('id', $allowedUnitIds)
|
||||||
->with([ // muat relasi
|
->with([ // muat relasi
|
||||||
'subUnitKerja' => fn($q) => $q->with([ // sub-unit
|
'subUnitKerja' => fn($q) => $q->with([ // sub-unit
|
||||||
'fileDirectory' => fn($f) => $f->when($keyword, fn($q) =>
|
'fileDirectory' => fn($f) => $f->when($keyword, fn($q) =>
|
||||||
@ -378,23 +399,43 @@ class DashboardController extends Controller
|
|||||||
public function dataDocumentLast(){
|
public function dataDocumentLast(){
|
||||||
$perPage = (int) request('per_page', 10);
|
$perPage = (int) request('per_page', 10);
|
||||||
$authUnitId = auth()->user()->dataUser?->mappingUnitKerjaPegawai[0]?->objectunitkerjapegawaifk;
|
$authUnitId = auth()->user()->dataUser?->mappingUnitKerjaPegawai[0]?->objectunitkerjapegawaifk;
|
||||||
|
$user = auth()->user()?->dataUser;
|
||||||
|
$akses = AksesFile::where(['pegawai_id' => $user->id, 'statusenabled' => true])->first();
|
||||||
$keyword = request('keyword');
|
$keyword = request('keyword');
|
||||||
|
|
||||||
$data = FileDirectory::where('statusenabled', true)
|
$query = FileDirectory::where('statusenabled', true)
|
||||||
->where(function ($query) use ($authUnitId) {
|
|
||||||
$query->where('permission_file', true)
|
|
||||||
->orWhere(function ($sub) use ($authUnitId) {
|
|
||||||
$sub->where('permission_file', false)
|
|
||||||
->where('id_unit_kerja', $authUnitId);
|
|
||||||
});
|
|
||||||
})
|
|
||||||
->when($keyword, function ($q) use ($keyword) {
|
->when($keyword, function ($q) use ($keyword) {
|
||||||
$q->where(function ($sub) use ($keyword) {
|
$q->where(function ($sub) use ($keyword) {
|
||||||
$sub->where('file', 'ILIKE', "%{$keyword}%")
|
$sub->where('file', 'ILIKE', "%{$keyword}%")
|
||||||
->orWhere('no_dokumen', 'ILIKE', "%{$keyword}%");
|
->orWhere('no_dokumen', 'ILIKE', "%{$keyword}%");
|
||||||
});
|
});
|
||||||
})
|
});
|
||||||
->orderBy('entry_at', 'desc')
|
if($akses){
|
||||||
|
if(!$akses->all_akses){
|
||||||
|
$aksesFile = AksesFileDetail::where('akses_file_id', $akses->akses_file_id)->pluck('id_unit_kerja');
|
||||||
|
$query->where(function ($query) use ($authUnitId, $aksesFile) {
|
||||||
|
$query->where('permission_file', true)
|
||||||
|
->orWhere(function ($sub) use ($authUnitId, $aksesFile) {
|
||||||
|
$sub->where('permission_file', false)
|
||||||
|
->whereIn('id_unit_kerja', $aksesFile);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}else{
|
||||||
|
$query;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
$query->where(function ($query) use ($authUnitId) {
|
||||||
|
$query->where('permission_file', true)
|
||||||
|
->orWhere(function ($sub) use ($authUnitId) {
|
||||||
|
$sub->where('permission_file', false)
|
||||||
|
->where('id_unit_kerja', $authUnitId);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
$data = $query->orderBy('entry_at', 'desc')
|
||||||
->paginate($perPage);
|
->paginate($perPage);
|
||||||
|
|
||||||
$payload = [
|
$payload = [
|
||||||
@ -661,8 +702,10 @@ class DashboardController extends Controller
|
|||||||
foreach ($grouped as $unitName => $folders) {
|
foreach ($grouped as $unitName => $folders) {
|
||||||
$data = [];
|
$data = [];
|
||||||
foreach ($folders as $folder => $count) {
|
foreach ($folders as $folder => $count) {
|
||||||
|
$sliceText = array_values(array_filter(explode('/', $folder)));
|
||||||
$data[] = [
|
$data[] = [
|
||||||
'folder'=> $folder,
|
'subUnit' => $sliceText[0],
|
||||||
|
'folder'=> $sliceText[1],
|
||||||
'count' => $count,
|
'count' => $count,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@ -701,4 +744,161 @@ class DashboardController extends Controller
|
|||||||
public function recapView(){
|
public function recapView(){
|
||||||
return view('dashboard.recap', ['title' => 'Rekap Dokumen']);
|
return view('dashboard.recap', ['title' => 'Rekap Dokumen']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function pendingFile(){
|
||||||
|
return view('pendingFile.index', ['title' => 'Data Pending']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function dataPendingFile(){
|
||||||
|
$perPage = (int) request('per_page', 10);
|
||||||
|
$keyword = request('keyword');
|
||||||
|
$start = request('start_date');
|
||||||
|
$end = request('end_date');
|
||||||
|
|
||||||
|
$query = FileDirectory::where('statusenabled', true)->whereNull('status_action')->orderBy('entry_at','desc');
|
||||||
|
if($keyword){
|
||||||
|
$query->where(function($q) use ($keyword){
|
||||||
|
$q->where('file', 'ILIKE', "%{$keyword}%")
|
||||||
|
->orWhere('no_dokumen', 'ILIKE', "%{$keyword}%");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if($start){
|
||||||
|
$query->whereDate('entry_at','>=',$start);
|
||||||
|
}
|
||||||
|
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)));
|
||||||
|
return [
|
||||||
|
'file_directory_id' => $item->file_directory_id,
|
||||||
|
'pegawai_nama_entry' => $item->pegawai_nama_entry,
|
||||||
|
'part' => $dataSlice[0] . '/' . $dataSlice[1],
|
||||||
|
'folder' => $dataSlice[2],
|
||||||
|
'fileName' =>$dataSlice[3],
|
||||||
|
'file' => $item->file,
|
||||||
|
'no_dokumen' => $item->no_dokumen,
|
||||||
|
'entry_at' => $item->entry_at,
|
||||||
|
'tanggal_terbit' => $item->tanggal_terbit,
|
||||||
|
'permission_file' => $item->permission_file,
|
||||||
|
];
|
||||||
|
});
|
||||||
|
return response()->json([
|
||||||
|
'status' => true,
|
||||||
|
'data' => $data,
|
||||||
|
'pagination' => [
|
||||||
|
'current_page' => $paginated->currentPage(),
|
||||||
|
'next_page' => $paginated->hasMorePages() ? $paginated->currentPage() + 1 : null,
|
||||||
|
'has_more' => $paginated->hasMorePages(),
|
||||||
|
'last_page' => $paginated->lastPage(),
|
||||||
|
'per_page' => $paginated->perPage(),
|
||||||
|
'total' => $paginated->total(),
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function approvePendingFile(string $id){
|
||||||
|
try {
|
||||||
|
$data = FileDirectory::where('file_directory_id', $id)->first();
|
||||||
|
if(!$data){
|
||||||
|
return response()->json([
|
||||||
|
'status' => false,
|
||||||
|
'message' => 'Data tidak ditemukan'
|
||||||
|
], 404);
|
||||||
|
}
|
||||||
|
$data->update([
|
||||||
|
'status_action' => 'approved',
|
||||||
|
'action_at' => Carbon::now(),
|
||||||
|
'action_by' => auth()->user()->dataUser->id,
|
||||||
|
]);
|
||||||
|
$payloadLog = [
|
||||||
|
'file_directory_id' => $data->file_directory_id,
|
||||||
|
'pegawai_id_entry' => $data->action_by,
|
||||||
|
'pegawai_nama_entry' => auth()->user()->dataUser->namalengkap,
|
||||||
|
'entry_at' => $data->action_at,
|
||||||
|
'action_type' => 'Approval Dokumen',
|
||||||
|
'statusenabled' => true,
|
||||||
|
'mod_change' => $data->entry_at,
|
||||||
|
'id_unit_kerja' => $data->id_unit_kerja,
|
||||||
|
'id_sub_unit_kerja' => $data->id_sub_unit_kerja,
|
||||||
|
'file' => $data->file,
|
||||||
|
'tanggal_terbit' => $data->tanggal_terbit,
|
||||||
|
'no_dokumen' => $data->no_dokumen,
|
||||||
|
'permission_file' => $data->permission_file,
|
||||||
|
];
|
||||||
|
LogActivity::create($payloadLog);
|
||||||
|
return response()->json([
|
||||||
|
'status' => true,
|
||||||
|
'message' => 'File berhasil di-approve'
|
||||||
|
], 200);
|
||||||
|
} catch (\Throwable $th) {
|
||||||
|
return response()->json([
|
||||||
|
'status' => false,
|
||||||
|
'message' => $th->getMessage()
|
||||||
|
], 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rejectPendingFile(string $id){
|
||||||
|
try {
|
||||||
|
$data = FileDirectory::where('file_directory_id', $id)->first();
|
||||||
|
if(!$data){
|
||||||
|
return response()->json([
|
||||||
|
'status' => false,
|
||||||
|
'message' => 'Data tidak ditemukan'
|
||||||
|
], 404);
|
||||||
|
}
|
||||||
|
$data->update([
|
||||||
|
'status_action' => 'rejected',
|
||||||
|
'action_at' => Carbon::now(),
|
||||||
|
'action_by' => auth()->user()->dataUser->id,
|
||||||
|
]);
|
||||||
|
$payloadLog = [
|
||||||
|
'file_directory_id' => $data->file_directory_id,
|
||||||
|
'pegawai_id_entry' => $data->action_by,
|
||||||
|
'pegawai_nama_entry' => auth()->user()->dataUser->namalengkap,
|
||||||
|
'entry_at' => $data->action_at,
|
||||||
|
'action_type' => 'Reject Dokumen',
|
||||||
|
'statusenabled' => true,
|
||||||
|
'mod_change' => $data->entry_at,
|
||||||
|
'id_unit_kerja' => $data->id_unit_kerja,
|
||||||
|
'id_sub_unit_kerja' => $data->id_sub_unit_kerja,
|
||||||
|
'file' => $data->file,
|
||||||
|
'tanggal_terbit' => $data->tanggal_terbit,
|
||||||
|
'no_dokumen' => $data->no_dokumen,
|
||||||
|
'permission_file' => $data->permission_file,
|
||||||
|
];
|
||||||
|
LogActivity::create($payloadLog);
|
||||||
|
return response()->json([
|
||||||
|
'status' => true,
|
||||||
|
'message' => 'File berhasil di-reject'
|
||||||
|
], 200);
|
||||||
|
} catch (\Throwable $th) {
|
||||||
|
return response()->json([
|
||||||
|
'status' => false,
|
||||||
|
'message' => $th->getMessage()
|
||||||
|
], 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function countDataPending(){
|
||||||
|
try {
|
||||||
|
$count = FileDirectory::where('statusenabled', true)
|
||||||
|
->whereNull('status_action')
|
||||||
|
->count();
|
||||||
|
return response()->json([
|
||||||
|
'status' => true,
|
||||||
|
'count' => $count,
|
||||||
|
'message' => 'Berhasil mendapatkan data'
|
||||||
|
]);
|
||||||
|
} catch (\Throwable $th) {
|
||||||
|
return response()->json([
|
||||||
|
'status' => false,
|
||||||
|
'message' => 'Terdapat kesalahan!'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,7 +9,7 @@ class LogActivityController extends Controller
|
|||||||
{
|
{
|
||||||
public function index(){
|
public function index(){
|
||||||
$data =[
|
$data =[
|
||||||
'title' => 'Log Activity'
|
'title' => 'Log Aktivitas'
|
||||||
];
|
];
|
||||||
return view('logActivity.index', $data);
|
return view('logActivity.index', $data);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use App\Models\AksesFileDetail;
|
||||||
|
|
||||||
class AksesFile extends Model
|
class AksesFile extends Model
|
||||||
{
|
{
|
||||||
@ -21,4 +22,9 @@ class AksesFile extends Model
|
|||||||
public function akses(){
|
public function akses(){
|
||||||
return $this->belongsTo(UnitKerja::class, 'unit_akses', 'id')->select('id', 'name');
|
return $this->belongsTo(UnitKerja::class, 'unit_akses', 'id')->select('id', 'name');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function details()
|
||||||
|
{
|
||||||
|
return $this->hasMany(AksesFileDetail::class, 'akses_file_id', 'akses_file_id');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
20
app/Models/AksesFileDetail.php
Normal file
20
app/Models/AksesFileDetail.php
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use App\Models\UnitKerja;
|
||||||
|
|
||||||
|
class AksesFileDetail extends Model
|
||||||
|
{
|
||||||
|
protected $connection = 'dbDirectory';
|
||||||
|
protected $table = 'public.akses_file_unit_detail';
|
||||||
|
public $timestamps = false;
|
||||||
|
protected $primaryKey = 'id';
|
||||||
|
protected $guarded = ['id'];
|
||||||
|
|
||||||
|
public function unit()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(UnitKerja::class, 'id_unit_kerja', 'id')->select('id', 'name');
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -103,13 +103,36 @@ function editAkses(e){
|
|||||||
const data = $(e).data();
|
const data = $(e).data();
|
||||||
new bootstrap.Modal(modalEdit).show();
|
new bootstrap.Modal(modalEdit).show();
|
||||||
formEditAkses.attr('action', `/akses/${data.akses_file_id}`)
|
formEditAkses.attr('action', `/akses/${data.akses_file_id}`)
|
||||||
$("#akses_id_edit").val(data.akses === 1 ? 'all' : 'unit')
|
$("#unit_akses_edit").empty().trigger('change');
|
||||||
|
$("#unit_akses_wrapper_edit").addClass('d-none');
|
||||||
|
|
||||||
selectOptionPegawaiEdit()
|
selectOptionPegawaiEdit()
|
||||||
|
selectOptionUnitKerjaEdit()
|
||||||
if (data.pegawai_id) {
|
if (data.pegawai_id) {
|
||||||
setOldSelect2Value('#pegawai_id_edit', data.pegawai_id, data.pegawai_nama);
|
setOldSelect2Value('#pegawai_id_edit', data.pegawai_id, data.pegawai_nama);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fetch(`/akses/${data.akses_file_id}`)
|
||||||
|
.then(async(res) => {
|
||||||
|
const responseData = await res.json();
|
||||||
|
if (!responseData.status) {
|
||||||
|
throw new Error(responseData.message || 'Gagal memuat data akses.');
|
||||||
|
}
|
||||||
|
const detail = responseData.data;
|
||||||
|
if (detail?.akses_type === 'all') {
|
||||||
|
$("#akses_all_edit").prop('checked', true);
|
||||||
|
} else {
|
||||||
|
$("#akses_unit_edit").prop('checked', true);
|
||||||
|
}
|
||||||
|
toggleUnitAksesEdit();
|
||||||
|
if (detail?.akses_type === 'unit' && Array.isArray(detail.units)) {
|
||||||
|
setOldSelect2Values('#unit_akses_edit', detail.units);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
$("#akses_all_edit").prop('checked', true);
|
||||||
|
toggleUnitAksesEdit();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -143,6 +166,46 @@ function selectOptionPegawaiEdit() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function selectOptionUnitKerjaEdit() {
|
||||||
|
let selectUnit = $(`#unit_akses_edit`);
|
||||||
|
if (selectUnit.data('select2')) return;
|
||||||
|
selectUnit.select2({
|
||||||
|
placeholder: '-- Pilih Unit Kerja --',
|
||||||
|
allowClear:true,
|
||||||
|
width: '100%',
|
||||||
|
dropdownParent: selectUnit.parent(),
|
||||||
|
ajax:{
|
||||||
|
url : '/select-unit-kerja',
|
||||||
|
dataType: 'json',
|
||||||
|
delay: 250,
|
||||||
|
data: function(params){
|
||||||
|
return { q: params.term }
|
||||||
|
},
|
||||||
|
processResults: function(data){
|
||||||
|
return {
|
||||||
|
results : data?.data.map(item => ({
|
||||||
|
id: item.id,
|
||||||
|
text: item.name,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
cache: true,
|
||||||
|
},
|
||||||
|
minimumInputLength: 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleUnitAksesEdit() {
|
||||||
|
const wrapper = $("#unit_akses_wrapper_edit");
|
||||||
|
const unitSelect = $("#unit_akses_edit");
|
||||||
|
const isUnit = $("#akses_unit_edit").is(':checked');
|
||||||
|
if (isUnit) {
|
||||||
|
wrapper.removeClass('d-none');
|
||||||
|
} else {
|
||||||
|
wrapper.addClass('d-none');
|
||||||
|
unitSelect.val(null).trigger('change');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function setOldSelect2Value(selector, id, text) {
|
function setOldSelect2Value(selector, id, text) {
|
||||||
@ -151,6 +214,16 @@ function setOldSelect2Value(selector, id, text) {
|
|||||||
$(selector).append(option).trigger('change')
|
$(selector).append(option).trigger('change')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setOldSelect2Values(selector, items) {
|
||||||
|
if (!Array.isArray(items) || items.length === 0) return;
|
||||||
|
items.forEach(item => {
|
||||||
|
if (!item?.id || !item?.text) return;
|
||||||
|
let option = new Option(item.text, item.id, true, true);
|
||||||
|
$(selector).append(option);
|
||||||
|
});
|
||||||
|
$(selector).trigger('change')
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
formEditAkses.on('submit', function(e){
|
formEditAkses.on('submit', function(e){
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|||||||
@ -25,15 +25,13 @@
|
|||||||
<i class="fa-solid fa-trash"></i>
|
<i class="fa-solid fa-trash"></i>
|
||||||
</button>
|
</button>
|
||||||
`
|
`
|
||||||
|
|
||||||
buttons += `
|
buttons += `
|
||||||
<button class="btn btn-sm btn-primary me-2" onclick="editAkses(this)"
|
<button class="btn btn-sm btn-primary me-2" onclick="editAkses(this)"
|
||||||
data-akses_file_id="${row.akses_file_id}" data-akses="${row?.all_akses ? 1 : row?.unit_akses}"
|
data-akses_file_id="${row.akses_file_id}" data-akses="${row?.all_akses ? 1 : row?.unit_akses}"
|
||||||
data-pegawai_id="${row?.pegawai_id}"
|
data-pegawai_id="${row?.pegawai_id}"
|
||||||
data-pegawai_nama="${row?.pegawai?.namalengkap}"
|
data-pegawai_nama="${row?.pegawai?.namalengkap}"
|
||||||
data-unit_id="${row?.unit_akses}"
|
data-unit_id="${row?.unit_akses}"
|
||||||
data-unit_nama="${row?.akses?.name}"
|
data-unit_nama="${row?.akses?.name}">
|
||||||
>
|
|
||||||
<i class="fa-solid fa-pencil"></i>
|
<i class="fa-solid fa-pencil"></i>
|
||||||
</button>`
|
</button>`
|
||||||
return `
|
return `
|
||||||
@ -50,7 +48,13 @@
|
|||||||
{
|
{
|
||||||
title:"Akses",
|
title:"Akses",
|
||||||
formatter:function(value, row){
|
formatter:function(value, row){
|
||||||
return row?.all_akses ? 'Semua Akses' : row?.akses?.name;
|
if (row?.all_akses) return 'Semua Unit';
|
||||||
|
const units = (row?.details || [])
|
||||||
|
.filter(detail => detail?.statusenabled)
|
||||||
|
.map(detail => detail?.unit?.name)
|
||||||
|
.filter(Boolean);
|
||||||
|
if (units.length > 0) return units.join(', ');
|
||||||
|
return row?.akses?.name || '-';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
selectOptionPegawai(0)
|
selectOptionPegawai(0)
|
||||||
|
selectOptionUnitKerja(0)
|
||||||
});
|
});
|
||||||
|
|
||||||
function selectOptionPegawai(colCount) {
|
function selectOptionPegawai(colCount) {
|
||||||
@ -31,6 +32,46 @@ function selectOptionPegawai(colCount) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function selectOptionUnitKerja(colCount) {
|
||||||
|
let selectUnit = $(`#unit_akses_${colCount}`);
|
||||||
|
selectUnit.select2({
|
||||||
|
placeholder: '-- Pilih Unit Kerja --',
|
||||||
|
allowClear: true,
|
||||||
|
width: '100%',
|
||||||
|
dropdownParent: selectUnit.parent(),
|
||||||
|
ajax:{
|
||||||
|
url : '/select-unit-kerja',
|
||||||
|
dataType: 'json',
|
||||||
|
delay: 250,
|
||||||
|
data: function(params){
|
||||||
|
return { q: params.term }
|
||||||
|
},
|
||||||
|
processResults: function(data){
|
||||||
|
return {
|
||||||
|
results : data?.data.map(item => ({
|
||||||
|
id: item.id,
|
||||||
|
text: item.name,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
cache: true,
|
||||||
|
},
|
||||||
|
minimumInputLength: 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleUnitAkses(colCount) {
|
||||||
|
const wrapper = $(`#unit_akses_wrapper_${colCount}`);
|
||||||
|
const unitSelect = $(`#unit_akses_${colCount}`);
|
||||||
|
const isUnit = $(`#akses_unit_${colCount}`).is(':checked');
|
||||||
|
if (isUnit) {
|
||||||
|
wrapper.removeClass('d-none');
|
||||||
|
} else {
|
||||||
|
wrapper.addClass('d-none');
|
||||||
|
unitSelect.val(null).trigger('change');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let colCount = 1;
|
let colCount = 1;
|
||||||
@ -42,18 +83,38 @@ function addForm(){
|
|||||||
html += `
|
html += `
|
||||||
<div class="row mt-3" id="col-${colCount}">
|
<div class="row mt-3" id="col-${colCount}">
|
||||||
<hr/>
|
<hr/>
|
||||||
<div class="col-md-6 mb-2">
|
<div class="col-md-4 mb-2">
|
||||||
<label>Nama</label>
|
<label>Nama</label>
|
||||||
<select class="form-control" name="data[${colCount}][pegawai_id]" id="pegawai_id_${colCount}" required>
|
<select class="form-control" name="data[${colCount}][pegawai_id]" id="pegawai_id_${colCount}" required>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-4 mb-2">
|
<div class="col-12 col-md-2">
|
||||||
<label>Akses</label>
|
<label class="form-label mb-1 d-block">Akses</label>
|
||||||
<select class="form-control" name="data[${colCount}][akses]" id="akses_id_${colCount}" required>
|
<div class="d-flex flex-wrap gap-3">
|
||||||
<option value="" disable>Select Choose</option>
|
<div class="form-check">
|
||||||
<option value="all">Semua Akses</option>
|
<input class="form-check-input" type="radio"
|
||||||
<option value="unit">By Unit Akses</option>
|
name="data[${colCount}][akses]" id="akses_all_${colCount}" value="all" checked
|
||||||
|
onchange="toggleUnitAkses(${colCount})">
|
||||||
|
<label class="form-check-label" for="akses_all_${colCount}">
|
||||||
|
Semua Akses
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="radio"
|
||||||
|
name="data[${colCount}][akses]" id="akses_unit_${colCount}" value="unit"
|
||||||
|
onchange="toggleUnitAkses(${colCount})">
|
||||||
|
<label class="form-check-label" for="akses_unit_${colCount}">
|
||||||
|
By Unit Akses
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<small class="text-muted">Pilih salah satu.</small>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4 mb-2 d-none" id="unit_akses_wrapper_${colCount}">
|
||||||
|
<label>Unit Kerja</label>
|
||||||
|
<select class="form-control" name="data[${colCount}][unit_akses][]" id="unit_akses_${colCount}" multiple>
|
||||||
</select>
|
</select>
|
||||||
|
<small class="text-muted">Bisa pilih lebih dari satu.</small>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-2">
|
<div class="col-md-2">
|
||||||
<button type="button" class="btn btn-danger mt-3 me-2" onclick="removeCol(${colCount})"><i class="fa-solid fa-trash"></i></button>
|
<button type="button" class="btn btn-danger mt-3 me-2" onclick="removeCol(${colCount})"><i class="fa-solid fa-trash"></i></button>
|
||||||
@ -63,6 +124,7 @@ function addForm(){
|
|||||||
`
|
`
|
||||||
col.append(html)
|
col.append(html)
|
||||||
selectOptionPegawai(colCount)
|
selectOptionPegawai(colCount)
|
||||||
|
selectOptionUnitKerja(colCount)
|
||||||
colCount++;
|
colCount++;
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -71,4 +133,3 @@ function addForm(){
|
|||||||
function removeCol(count){
|
function removeCol(count){
|
||||||
$(`#col-${count}`).remove()
|
$(`#col-${count}`).remove()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -37,10 +37,10 @@ $(document).ready(function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// --- isi default unit kerja ---
|
// --- isi default unit kerja ---
|
||||||
if(authUnitKerja){
|
// if(authUnitKerja){
|
||||||
let option = new Option(authUnitKerja.name, authUnitKerja.id, true, true);
|
// let option = new Option(authUnitKerja.name, authUnitKerja.id, true, true);
|
||||||
$('.unit_kerja').append(option).trigger('change');
|
// $('.unit_kerja').append(option).trigger('change');
|
||||||
}
|
// }
|
||||||
|
|
||||||
let initialUnit = $('.unit_kerja').val();
|
let initialUnit = $('.unit_kerja').val();
|
||||||
if(initialUnit){
|
if(initialUnit){
|
||||||
|
|||||||
@ -273,7 +273,7 @@ function downloadMultiple(){
|
|||||||
URL.revokeObjectURL(url);
|
URL.revokeObjectURL(url);
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
Swal.fire({ icon: 'error', title : 'Gagal mengunduh' })
|
Swal.fire({ icon: 'error', title : err.message })
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
307
public/js/pendingFile/index.js
Normal file
307
public/js/pendingFile/index.js
Normal file
@ -0,0 +1,307 @@
|
|||||||
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
const tableState = { data: [], page: 1, pageSize: 10, search: '', lastPage: 1, total: 0, startDate: '', endDate: '' };
|
||||||
|
const tbody = document.getElementById('tablePendingFile');
|
||||||
|
const paginationEl = document.getElementById('paginationControls');
|
||||||
|
const summaryEl = document.getElementById('tableSummary');
|
||||||
|
const pageSizeSelect = document.getElementById('tablePageSize');
|
||||||
|
const startDateInput = document.getElementById('startDate');
|
||||||
|
const endDateInput = document.getElementById('endDate');
|
||||||
|
const csrfToken = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content');
|
||||||
|
|
||||||
|
if (pageSizeSelect) {
|
||||||
|
const initialSize = parseInt(pageSizeSelect.value);
|
||||||
|
if (!isNaN(initialSize)) tableState.pageSize = initialSize;
|
||||||
|
pageSizeSelect.addEventListener('change', (e) => {
|
||||||
|
const val = parseInt(e.target.value);
|
||||||
|
if (!isNaN(val) && val > 0) {
|
||||||
|
tableState.pageSize = val;
|
||||||
|
tableState.page = 1;
|
||||||
|
fetchData();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
window.applyDateFilter = function(){
|
||||||
|
tableState.startDate = startDateInput.value || '';
|
||||||
|
tableState.endDate = endDateInput.value || '';
|
||||||
|
tableState.page = 1;
|
||||||
|
fetchData();
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatTanggal(dateString) {
|
||||||
|
if (!dateString) return '-';
|
||||||
|
const d = new Date(dateString);
|
||||||
|
return d.toLocaleDateString('id-ID', {
|
||||||
|
day: '2-digit',
|
||||||
|
month: 'short',
|
||||||
|
year: 'numeric',
|
||||||
|
hour: '2-digit',
|
||||||
|
minute: '2-digit'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildRow(item){
|
||||||
|
let tanggal = item.entry_at ? formatTanggal(item.entry_at) : '-';
|
||||||
|
const aksi = `
|
||||||
|
<div class="d-flex gap-1">
|
||||||
|
<button class="btn btn-sm btn-success" onclick="approvePending('${item.file_directory_id}', '${item.fileName || ''}')">
|
||||||
|
<i class="fa-solid fa-check"></i>
|
||||||
|
</button>
|
||||||
|
<button class="btn btn-sm btn-danger" onclick="rejectPending('${item.file_directory_id}', '${item.fileName || ''}')">
|
||||||
|
<i class="fa-solid fa-xmark"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
return `
|
||||||
|
<tr>
|
||||||
|
<td>${aksi}</td>
|
||||||
|
<td>${item.no_dokumen || '-'}</td>
|
||||||
|
<td><a href="#" class="file-link"
|
||||||
|
data-file="${item.file}"
|
||||||
|
data-fileName="${item.fileName}"
|
||||||
|
data-id="${item.file_directory_id}"
|
||||||
|
data-no_dokumen="${item.no_dokumen || '-'}"
|
||||||
|
data-tanggal_terbit="${item.tanggal_terbit || '-'}"
|
||||||
|
data-permission_file="${item.permission_file || '-'}">${item.fileName}</a></td>
|
||||||
|
<td>${item.folder || '-'}</td>
|
||||||
|
<td>${item.part || '-'}</td>
|
||||||
|
<td class="text-nowrap">${tanggal}</td>
|
||||||
|
</tr>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderPagination(totalPages){
|
||||||
|
if (!paginationEl) return;
|
||||||
|
if (totalPages <= 1) {
|
||||||
|
paginationEl.innerHTML = '';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const maxButtons = 5;
|
||||||
|
let start = Math.max(1, tableState.page - Math.floor(maxButtons/2));
|
||||||
|
let end = Math.min(totalPages, start + maxButtons - 1);
|
||||||
|
start = Math.max(1, end - maxButtons + 1);
|
||||||
|
|
||||||
|
let buttons = '';
|
||||||
|
buttons += `<button class="btn btn-outline-secondary btn-sm" data-page="prev" ${tableState.page === 1 ? 'disabled' : ''}>‹</button>`;
|
||||||
|
for (let i = start; i <= end; i++) {
|
||||||
|
buttons += `<button class="btn btn-sm ${i === tableState.page ? 'btn-primary' : 'btn-outline-secondary'}" data-page="${i}">${i}</button>`;
|
||||||
|
}
|
||||||
|
buttons += `<button class="btn btn-outline-secondary btn-sm" data-page="next" ${tableState.page === totalPages ? 'disabled' : ''}>›</button>`;
|
||||||
|
|
||||||
|
paginationEl.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 ${tableState.page} dari ${totalPages}</span>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (paginationEl) {
|
||||||
|
paginationEl.addEventListener('click', (e) => {
|
||||||
|
const page = e.target.getAttribute('data-page');
|
||||||
|
if (!page) return;
|
||||||
|
if (page === 'prev' && tableState.page > 1) tableState.page--;
|
||||||
|
else if (page === 'next') {
|
||||||
|
if (tableState.page < tableState.lastPage) tableState.page++;
|
||||||
|
} else {
|
||||||
|
tableState.page = parseInt(page);
|
||||||
|
}
|
||||||
|
fetchData();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderTable(){
|
||||||
|
const pageData = tableState.data || [];
|
||||||
|
if (pageData.length === 0) {
|
||||||
|
tbody.innerHTML = `
|
||||||
|
<tr>
|
||||||
|
<td colspan="4" class="text-center text-muted py-4">
|
||||||
|
Tidak ada data
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
`;
|
||||||
|
} else {
|
||||||
|
tbody.innerHTML = pageData.map(buildRow).join('');
|
||||||
|
}
|
||||||
|
|
||||||
|
const from = tableState.total === 0 ? 0 : ((tableState.page - 1) * tableState.pageSize) + 1;
|
||||||
|
const to = Math.min(((tableState.page - 1) * tableState.pageSize) + pageData.length, tableState.total);
|
||||||
|
if (summaryEl) {
|
||||||
|
summaryEl.textContent = tableState.total ? `Menampilkan ${from} - ${to} dari ${tableState.total} data` : 'Tidak ada data';
|
||||||
|
}
|
||||||
|
|
||||||
|
renderPagination(tableState.lastPage || 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
let searchDebounce;
|
||||||
|
window.debouncedTableSearch = function(value){
|
||||||
|
clearTimeout(searchDebounce);
|
||||||
|
searchDebounce = setTimeout(() => {
|
||||||
|
tableState.search = value.trim();
|
||||||
|
tableState.page = 1;
|
||||||
|
fetchData();
|
||||||
|
}, 250);
|
||||||
|
}
|
||||||
|
|
||||||
|
window.refreshLog = function(){
|
||||||
|
tableState.search = '';
|
||||||
|
tableState.startDate = '';
|
||||||
|
tableState.endDate = '';
|
||||||
|
document.getElementById('tableSearch').value = '';
|
||||||
|
startDateInput.value = '';
|
||||||
|
endDateInput.value = '';
|
||||||
|
tableState.page = 1;
|
||||||
|
fetchData();
|
||||||
|
}
|
||||||
|
|
||||||
|
function fetchData(){
|
||||||
|
if (summaryEl) summaryEl.textContent = 'Memuat data...';
|
||||||
|
const params = new URLSearchParams({
|
||||||
|
page: tableState.page,
|
||||||
|
per_page: tableState.pageSize,
|
||||||
|
keyword: tableState.search || '',
|
||||||
|
start_date: tableState.startDate || '',
|
||||||
|
end_date: tableState.endDate || ''
|
||||||
|
});
|
||||||
|
fetch(`/datatable/pending-file?${params.toString()}`)
|
||||||
|
.then(res => res.json())
|
||||||
|
.then(data => {
|
||||||
|
tableState.data = data?.data || [];
|
||||||
|
tableState.lastPage = data?.pagination?.last_page || 1;
|
||||||
|
tableState.total = data?.pagination?.total || 0;
|
||||||
|
renderTable();
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.error(err);
|
||||||
|
if (summaryEl) summaryEl.textContent = 'Gagal memuat data';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
window.approvePending = function(id, fileName){
|
||||||
|
Swal.fire({
|
||||||
|
title: 'Approve dokumen?',
|
||||||
|
text: fileName || 'Dokumen akan disetujui.',
|
||||||
|
icon: 'question',
|
||||||
|
showCancelButton: true,
|
||||||
|
confirmButtonText: 'Approve',
|
||||||
|
cancelButtonText: 'Batal',
|
||||||
|
}).then((result) => {
|
||||||
|
if (!result.isConfirmed) return;
|
||||||
|
fetch(`/pending-file/${id}/approve`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'X-CSRF-TOKEN': csrfToken,
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
}).then(async(res) => {
|
||||||
|
const data = await res.json();
|
||||||
|
if (!res.ok || !data?.status) {
|
||||||
|
throw new Error(data?.message || 'Gagal approve.');
|
||||||
|
}
|
||||||
|
Swal.fire({
|
||||||
|
icon: 'success',
|
||||||
|
title: 'Berhasil',
|
||||||
|
text: data.message || 'Dokumen disetujui.',
|
||||||
|
timer: 1500,
|
||||||
|
showConfirmButton: false
|
||||||
|
});
|
||||||
|
countData()
|
||||||
|
fetchData();
|
||||||
|
}).catch((err) => {
|
||||||
|
Swal.fire({
|
||||||
|
icon: 'error',
|
||||||
|
title: 'Gagal',
|
||||||
|
text: err.message || 'Terjadi kesalahan.'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
window.rejectPending = function(id, fileName){
|
||||||
|
Swal.fire({
|
||||||
|
title: 'Reject dokumen?',
|
||||||
|
text: fileName || 'Dokumen akan ditolak.',
|
||||||
|
icon: 'warning',
|
||||||
|
showCancelButton: true,
|
||||||
|
confirmButtonText: 'Reject',
|
||||||
|
cancelButtonText: 'Batal',
|
||||||
|
}).then((result) => {
|
||||||
|
if (!result.isConfirmed) return;
|
||||||
|
fetch(`/pending-file/${id}/reject`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'X-CSRF-TOKEN': csrfToken,
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
}).then(async(res) => {
|
||||||
|
const data = await res.json();
|
||||||
|
if (!res.ok || !data?.status) {
|
||||||
|
throw new Error(data?.message || 'Gagal reject.');
|
||||||
|
}
|
||||||
|
Swal.fire({
|
||||||
|
icon: 'success',
|
||||||
|
title: 'Berhasil',
|
||||||
|
text: data.message || 'Dokumen ditolak.',
|
||||||
|
timer: 1500,
|
||||||
|
showConfirmButton: false
|
||||||
|
});
|
||||||
|
countData()
|
||||||
|
fetchData();
|
||||||
|
}).catch((err) => {
|
||||||
|
Swal.fire({
|
||||||
|
icon: 'error',
|
||||||
|
title: 'Gagal',
|
||||||
|
text: err.message || 'Terjadi kesalahan.'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchData();
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
document.addEventListener('click', function(e){
|
||||||
|
if(e.target.matches('.file-link')){
|
||||||
|
e.preventDefault();
|
||||||
|
let fileUrl = e.target.getAttribute('data-file');
|
||||||
|
let noDokumen = e.target.getAttribute('data-no_dokumen')
|
||||||
|
let tanggalTerbit = e.target.getAttribute('data-tanggal_terbit')
|
||||||
|
let permissionFile = e.target.getAttribute('data-permission_file')
|
||||||
|
let fileName = e.target.getAttribute('data-fileName')
|
||||||
|
currentFile = fileUrl;
|
||||||
|
idDirectory = e.target.getAttribute('data-id');
|
||||||
|
|
||||||
|
|
||||||
|
const titleEl = document.getElementById('confirm_preview_file');
|
||||||
|
if (titleEl) titleEl.textContent = fileName;
|
||||||
|
|
||||||
|
// set footer info
|
||||||
|
const noEl = document.getElementById('confirm-upload-dokumen');
|
||||||
|
if (noEl) noEl.textContent = noDokumen;
|
||||||
|
|
||||||
|
const tglEl = document.getElementById('confirm-time-dokumen');
|
||||||
|
|
||||||
|
if (tglEl) tglEl.textContent = tanggalTerbit;
|
||||||
|
|
||||||
|
const permEl = document.getElementById('confirm-permission');
|
||||||
|
if (permEl) {
|
||||||
|
const publicDoc = isPublic(permissionFile);
|
||||||
|
permEl.textContent = publicDoc ? 'Bisa dilihat unit lain' : 'Hanya unit ini';
|
||||||
|
permEl.className = 'badge ' + (publicDoc ? 'bg-success' : 'bg-secondary');
|
||||||
|
}
|
||||||
|
let previewBox = document.getElementById('file-preview');
|
||||||
|
previewBox.innerHTML = `<iframe src="/file-preview/${idDirectory}" width="100%" height="500px" style="border:none;"></iframe>`;
|
||||||
|
$("#previewModal").modal('show')
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(e.target.matches('#btn-view-full')){
|
||||||
|
window.open(`/file-preview/${idDirectory}`, '_blank');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
function isPublic(permissionVal){
|
||||||
|
if(permissionVal === null || permissionVal === undefined) return false;
|
||||||
|
const val = String(permissionVal).toLowerCase();
|
||||||
|
return val === '1' || val === 'true' || val === 'iya' || val === 'yes';
|
||||||
|
}
|
||||||
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
<!-- Modal Header -->
|
<!-- Modal Header -->
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h1 class="modal-title fs-5">Aksi</h1>
|
<h1 class="modal-title fs-5">Tambah Akses</h1>
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -13,25 +13,51 @@
|
|||||||
@csrf
|
@csrf
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row">
|
<div class="border rounded-3 p-3 mb-2">
|
||||||
<div class="col-md-6 mb-2">
|
<div class="row g-3 align-items-end">
|
||||||
<label>Nama</label>
|
<div class="col-md-4 mb-2">
|
||||||
|
<label class="form-label">Nama</label>
|
||||||
<select class="form-control" name="data[0][pegawai_id]" id="pegawai_id_0" required>
|
<select class="form-control" name="data[0][pegawai_id]" id="pegawai_id_0" required>
|
||||||
</select>
|
</select>
|
||||||
|
<small class="text-muted">Cari nama pegawai.</small>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6 mb-2">
|
<div class="col-12 col-md-4">
|
||||||
<label>Akses</label>
|
<label class="form-label mb-1 d-block">Akses</label>
|
||||||
<select class="form-control" name="data[0][akses]" id="akses_id_0" required>
|
|
||||||
<option value="" disable>Select Choose</option>
|
<div class="d-flex flex-wrap gap-3">
|
||||||
<option value="all">Semua Akses</option>
|
<div class="form-check">
|
||||||
<option value="unit">By Unit Akses</option>
|
<input class="form-check-input" type="radio"
|
||||||
|
name="data[0][akses]" id="akses_all_0" value="all" checked
|
||||||
|
onchange="toggleUnitAkses(0)">
|
||||||
|
<label class="form-check-label" for="akses_all_0">
|
||||||
|
Semua Akses
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="radio"
|
||||||
|
name="data[0][akses]" id="akses_unit_0" value="unit"
|
||||||
|
onchange="toggleUnitAkses(0)">
|
||||||
|
<label class="form-check-label" for="akses_unit_0">
|
||||||
|
By Unit Akses
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<small class="text-muted">Pilih salah satu.</small>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4 mb-2 d-none" id="unit_akses_wrapper_0">
|
||||||
|
<label class="form-label">Unit Kerja</label>
|
||||||
|
<select class="form-control" name="data[0][unit_akses][]" id="unit_akses_0" multiple>
|
||||||
</select>
|
</select>
|
||||||
|
<small class="text-muted">Bisa pilih lebih dari satu.</small>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="col_add_akses"></div>
|
<div id="col_add_akses"></div>
|
||||||
<button type="button" class="btn btn-outline-primary btn-sm mt-2" onclick="addForm()">
|
<button type="button" class="btn btn-outline-primary btn-sm mt-2" onclick="addForm()">
|
||||||
+ Tambah Form
|
+ Tambah Form
|
||||||
</button>
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
<!-- Modal Header -->
|
<!-- Modal Header -->
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h1 class="modal-title fs-5">Aksi</h1>
|
<h1 class="modal-title fs-5">Edit Akses</h1>
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -14,20 +14,43 @@
|
|||||||
@method('PUT')
|
@method('PUT')
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row">
|
<div class="border rounded-3 p-3">
|
||||||
<div class="col-md-6 mb-2">
|
<div class="row g-3 align-items-end">
|
||||||
<label>Nama</label>
|
<div class="col-md-4 mb-2">
|
||||||
<select class="form-control" name="pegawai_id" id="pegawai_id_edit" required>
|
<label class="form-label">Nama</label>
|
||||||
</select>
|
<select class="form-control" name="pegawai_id" id="pegawai_id_edit" required>
|
||||||
</div>
|
</select>
|
||||||
<div class="col-md-6 mb-2">
|
<small class="text-muted">Cari nama pegawai.</small>
|
||||||
<label>Akses</label>
|
</div>
|
||||||
<select class="form-control" name="akses" id="akses_id_edit" required>
|
<div class="col-12 col-md-2">
|
||||||
<option value="" disable>Select Choose</option>
|
<label class="form-label mb-1 d-block">Akses</label>
|
||||||
<option value="all">Semua Akses</option>
|
<div class="d-flex flex-wrap gap-3">
|
||||||
<option value="unit">By Unit Akses</option>
|
<div class="form-check">
|
||||||
</select>
|
<input class="form-check-input" type="radio"
|
||||||
</div>
|
name="akses" id="akses_all_edit" value="all"
|
||||||
|
onchange="toggleUnitAksesEdit()">
|
||||||
|
<label class="form-check-label" for="akses_all_edit">
|
||||||
|
Semua Akses
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="radio"
|
||||||
|
name="akses" id="akses_unit_edit" value="unit"
|
||||||
|
onchange="toggleUnitAksesEdit()">
|
||||||
|
<label class="form-check-label" for="akses_unit_edit">
|
||||||
|
By Unit Akses
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<small class="text-muted">Pilih salah satu.</small>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-md-6 d-none" id="unit_akses_wrapper_edit">
|
||||||
|
<label class="form-label">Unit Kerja</label>
|
||||||
|
<select class="form-control" name="unit_akses[]" id="unit_akses_edit" multiple>
|
||||||
|
</select>
|
||||||
|
<small class="text-muted">Bisa pilih lebih dari satu.</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -67,13 +67,13 @@
|
|||||||
<div class="row g-3 align-items-end">
|
<div class="row g-3 align-items-end">
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<label for="unit_kerja" class="form-label fw-semibold text-muted small">Unit Kerja</label>
|
<label for="unit_kerja" class="form-label fw-semibold text-muted small">Unit Kerja</label>
|
||||||
<select class="form-control unit_kerja" id="unit_kerja"{{ ($allAkses && ($allAkses->all_akses || $allAkses->unit_akses)) ? '' : 'disabled' }}>
|
<select class="form-control unit_kerja" id="unit_kerja">
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<label for="sub_unit_kerja" class="form-label fw-semibold text-muted small">Sub Unit Kerja</label>
|
<label for="sub_unit_kerja" class="form-label fw-semibold text-muted small">Sub Unit Kerja</label>
|
||||||
<select class="form-control sub_unit_kerja" id="sub_unit_kerja" @if($allAkses && ($allAkses->all_akses || $allAkses->unit_akses)) multiple="multiple" @else disabled @endif>
|
<select class="form-control sub_unit_kerja" id="sub_unit_kerja" multiple="multiple">
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -265,19 +265,6 @@
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// $("#download-file").off('click').on('click', function(){
|
|
||||||
// if(currentFile){
|
|
||||||
// let link = document.createElement('a');
|
|
||||||
// link.href = 'file/' + currentFile; // alamat file
|
|
||||||
// link.download = currentFile.split('/').pop(); // nama file otomatis
|
|
||||||
// document.body.appendChild(link);
|
|
||||||
// link.click();
|
|
||||||
// document.body.removeChild(link);
|
|
||||||
// }else{
|
|
||||||
// console.error('error');
|
|
||||||
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -38,7 +38,8 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<th style="width:5%;" class="text-center">#</th>
|
<th style="width:5%;" class="text-center">#</th>
|
||||||
<th style="width:30%;">Unit</th>
|
<th style="width:30%;">Unit</th>
|
||||||
<th style="width:50%;">Folder</th>
|
<th style="width:30%;">Sub Unit</th>
|
||||||
|
<th style="width:20%;">Folder</th>
|
||||||
<th style="width:15%;" class="text-center">Jumlah</th>
|
<th style="width:15%;" class="text-center">Jumlah</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
@ -102,6 +103,7 @@ function fetchRecap(){
|
|||||||
<tr>
|
<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="text-center align-middle fw-semibold">${idx+1}</td>` : ''}
|
||||||
${i === 0 ? `<td rowspan="${row.data.length}" class="fw-semibold">${row.unit || '-'}</td>` : ''}
|
${i === 0 ? `<td rowspan="${row.data.length}" class="fw-semibold">${row.unit || '-'}</td>` : ''}
|
||||||
|
<td>${f.subUnit || '-'}</td>
|
||||||
<td>${f.folder || '-'}</td>
|
<td>${f.folder || '-'}</td>
|
||||||
<td class="text-center fw-bold">${f.count || 0}</td>
|
<td class="text-center fw-bold">${f.count || 0}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@ -272,11 +272,11 @@
|
|||||||
width: '100%',
|
width: '100%',
|
||||||
});
|
});
|
||||||
|
|
||||||
// --- isi default unit kerja ---
|
// // --- isi default unit kerja ---
|
||||||
if(authUnitKerja){
|
// if(authUnitKerja){
|
||||||
let option = new Option(authUnitKerja.name, authUnitKerja.id, true, true);
|
// let option = new Option(authUnitKerja.name, authUnitKerja.id, true, true);
|
||||||
$('.unit_kerja').append(option).trigger('change');
|
// $('.unit_kerja').append(option).trigger('change');
|
||||||
}
|
// }
|
||||||
|
|
||||||
let initialUnit = $('.unit_kerja').val();
|
let initialUnit = $('.unit_kerja').val();
|
||||||
if(initialUnit){
|
if(initialUnit){
|
||||||
|
|||||||
@ -18,13 +18,13 @@
|
|||||||
</li>
|
</li>
|
||||||
<li class="sidebar-item">
|
<li class="sidebar-item">
|
||||||
<a class="sidebar-link" href="/" aria-expanded="false">
|
<a class="sidebar-link" href="/" aria-expanded="false">
|
||||||
<i class="ti ti-atom"></i>
|
<i class="ti ti-dashboard"></i>
|
||||||
<span class="hide-menu">Dashboard</span>
|
<span class="hide-menu">Dashboard</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="sidebar-item">
|
<li class="sidebar-item">
|
||||||
<a class="sidebar-link" href="/new" aria-expanded="false">
|
<a class="sidebar-link" href="/new" aria-expanded="false">
|
||||||
<i class="ti ti-atom"></i>
|
<i class="ti ti-layout-dashboard"></i>
|
||||||
<span class="hide-menu">Dashboard V2</span>
|
<span class="hide-menu">Dashboard V2</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
@ -59,7 +59,7 @@
|
|||||||
href="/akses" aria-expanded="false">
|
href="/akses" aria-expanded="false">
|
||||||
<div class="d-flex align-items-center gap-3">
|
<div class="d-flex align-items-center gap-3">
|
||||||
<span class="d-flex">
|
<span class="d-flex">
|
||||||
<i class="ti ti-layout-grid"></i>
|
<i class="ti ti-lock-access"></i>
|
||||||
</span>
|
</span>
|
||||||
<span class="hide-menu">Akses</span>
|
<span class="hide-menu">Akses</span>
|
||||||
</div>
|
</div>
|
||||||
@ -71,9 +71,9 @@
|
|||||||
href="/log-activity" aria-expanded="false">
|
href="/log-activity" aria-expanded="false">
|
||||||
<div class="d-flex align-items-center gap-3">
|
<div class="d-flex align-items-center gap-3">
|
||||||
<span class="d-flex">
|
<span class="d-flex">
|
||||||
<i class="ti ti-layout-grid"></i>
|
<i class="ti ti-activity"></i>
|
||||||
</span>
|
</span>
|
||||||
<span class="hide-menu">Log Aktivity</span>
|
<span class="hide-menu">Log Aktivitas</span>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
@ -83,15 +83,54 @@
|
|||||||
href="/recap" aria-expanded="false">
|
href="/recap" aria-expanded="false">
|
||||||
<div class="d-flex align-items-center gap-3">
|
<div class="d-flex align-items-center gap-3">
|
||||||
<span class="d-flex">
|
<span class="d-flex">
|
||||||
<i class="ti ti-layout-grid"></i>
|
<i class="ti ti-report-analytics"></i>
|
||||||
</span>
|
</span>
|
||||||
<span class="hide-menu">Data Rekap</span>
|
<span class="hide-menu">Data Rekap</span>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li class="sidebar-item">
|
||||||
|
<a class="sidebar-link d-flex align-items-center justify-content-between"
|
||||||
|
href="/pending-file" aria-expanded="false">
|
||||||
|
|
||||||
|
<!-- Left -->
|
||||||
|
<div class="d-flex align-items-center gap-3">
|
||||||
|
<i class="ti ti-clock sidebar-icon"></i>
|
||||||
|
<span class="hide-menu">Persetujuan</span>
|
||||||
|
</div>
|
||||||
|
<!-- Right Badge -->
|
||||||
|
<span class="badge bg-danger rounded-pill sidebar-badge" id="pendingCountBadge">
|
||||||
|
0
|
||||||
|
</span>
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
<!-- End Sidebar navigation -->
|
<!-- End Sidebar navigation -->
|
||||||
</div>
|
</div>
|
||||||
<!-- End Sidebar scroll-->
|
<!-- End Sidebar scroll-->
|
||||||
</aside>
|
</aside>
|
||||||
|
<script>
|
||||||
|
function countData(){
|
||||||
|
const badge = document.getElementById('pendingCountBadge');
|
||||||
|
if (!badge) return;
|
||||||
|
fetch('/data/count-pending')
|
||||||
|
.then(res => res.json())
|
||||||
|
.then(data => {
|
||||||
|
const count = data?.count ?? 0;
|
||||||
|
badge.textContent = count;
|
||||||
|
if (count <= 0) {
|
||||||
|
badge.classList.add('d-none');
|
||||||
|
} else {
|
||||||
|
badge.classList.remove('d-none');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
badge.classList.add('d-none');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
countData();
|
||||||
|
</script>
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header d-flex align-items-center justify-content-between">
|
<div class="card-header d-flex align-items-center justify-content-between">
|
||||||
<h4 class="mb-0">Log Activity</h4>
|
<h4 class="mb-0">Log Aktivitas</h4>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body p-3">
|
<div class="card-body p-3">
|
||||||
<div class="d-flex flex-column flex-md-row align-items-md-center gap-2 mb-3 flex-wrap">
|
<div class="d-flex flex-column flex-md-row align-items-md-center gap-2 mb-3 flex-wrap">
|
||||||
|
|||||||
68
resources/views/pendingFile/index.blade.php
Normal file
68
resources/views/pendingFile/index.blade.php
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
@extends('layout.main')
|
||||||
|
@section('body_main')
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header d-flex align-items-center justify-content-between">
|
||||||
|
<h4 class="mb-0">Data Pending</h4>
|
||||||
|
</div>
|
||||||
|
<div class="card-body p-3">
|
||||||
|
<div class="d-flex flex-column flex-md-row align-items-md-center gap-2 mb-3 flex-wrap">
|
||||||
|
<div class="input-group input-group-sm flex-grow-1" 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="tableSearch"
|
||||||
|
class="form-control border-start-0"
|
||||||
|
placeholder="Cari nama file / nomor dokumen"
|
||||||
|
oninput="debouncedTableSearch(this.value)">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex align-items-center gap-2">
|
||||||
|
<label class="small mb-0 text-muted">Mulai</label>
|
||||||
|
<input type="date" id="startDate" class="form-control form-control-sm" onchange="applyDateFilter()">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex align-items-center gap-2">
|
||||||
|
<label class="small mb-0 text-muted">Selesai</label>
|
||||||
|
<input type="date" id="endDate" class="form-control form-control-sm" onchange="applyDateFilter()">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex align-items-center gap-2">
|
||||||
|
<select id="tablePageSize" class="form-select form-select-sm" style="width: auto;">
|
||||||
|
<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>
|
||||||
|
</div>
|
||||||
|
<button class="btn btn-outline-secondary btn-sm" onclick="refreshLog()">
|
||||||
|
<i class="fa fa-rotate"></i> Refresh
|
||||||
|
</button>
|
||||||
|
<div class="small text-muted ms-md-auto" id="tableSummary"></div>
|
||||||
|
</div>
|
||||||
|
<div class="table-responsive" style="max-height: 55vh; overflow-y:auto;">
|
||||||
|
<table class="table table-sm table-hover align-middle mb-0" id="lastUpdatedTable">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Aksi</th>
|
||||||
|
<th>No Dokumen</th>
|
||||||
|
<th>File</th>
|
||||||
|
<th>Folder</th>
|
||||||
|
<th>Unit/Sub Unit</th>
|
||||||
|
<th>Tanggal</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody id="tablePendingFile">
|
||||||
|
<!-- data dari fetch masuk sini -->
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex flex-column flex-md-row align-items-md-center justify-content-between gap-2 mt-3" id="paginationControls"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@include('pendingFile.modal.view')
|
||||||
|
<script src="{{ ver('/js/pendingFile/index.js') }}"></script>
|
||||||
|
@endsection
|
||||||
58
resources/views/pendingFile/modal/view.blade.php
Normal file
58
resources/views/pendingFile/modal/view.blade.php
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
<!-- Modal Preview -->
|
||||||
|
<div class="modal fade" id="previewModal" tabindex="-1" aria-labelledby="previewModalLabel" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-xl modal-dialog-centered modal-dialog-scrollable">
|
||||||
|
<div class="modal-content">
|
||||||
|
|
||||||
|
<!-- Header -->
|
||||||
|
<div class="modal-header">
|
||||||
|
<h6 class="modal-title" id="previewModalLabel">
|
||||||
|
📄 Preview <strong id="confirm_preview_file"></strong>
|
||||||
|
</h6>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Body -->
|
||||||
|
<div class="modal-body p-2" style="min-height:250px; max-height:70vh; overflow:auto;">
|
||||||
|
<div id="file-preview"
|
||||||
|
class="text-center text-muted d-flex justify-content-center align-items-center"
|
||||||
|
style="height:100%;">
|
||||||
|
<p>📂 Pilih file untuk melihat preview</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Footer -->
|
||||||
|
<div class="modal-footer d-flex justify-content-between align-items-center">
|
||||||
|
|
||||||
|
<div class="small text-muted">
|
||||||
|
<span class="me-3">
|
||||||
|
Nomor Dokumen:
|
||||||
|
<strong id="confirm-upload-dokumen" class="text-dark">-</strong>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<span class="me-3">
|
||||||
|
Tanggal Terbit:
|
||||||
|
<strong id="confirm-time-dokumen" class="text-dark">-</strong>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<span>
|
||||||
|
Akses Dokumen:
|
||||||
|
<span id="confirm-permission" class="badge bg-secondary">-</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<!-- Button -->
|
||||||
|
<div class="d-flex gap-2">
|
||||||
|
<button type="button" class="btn btn-sm btn-outline-primary" id="btn-view-full">
|
||||||
|
Lihat Full
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button type="button" class="btn btn-sm btn-secondary" data-bs-dismiss="modal">
|
||||||
|
Tutup
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@ -40,6 +40,12 @@ Route::middleware(['auth'])->group(function(){
|
|||||||
|
|
||||||
Route::get('/recap', [DashboardController::class, 'recapView']);
|
Route::get('/recap', [DashboardController::class, 'recapView']);
|
||||||
Route::get('/data/recap', [DashboardController::class, 'recapData']);
|
Route::get('/data/recap', [DashboardController::class, 'recapData']);
|
||||||
|
|
||||||
|
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/{id}/reject', [DashboardController::class, 'rejectPendingFile']);
|
||||||
|
Route::get('/data/count-pending', [DashboardController::class, 'countDataPending']);
|
||||||
});
|
});
|
||||||
|
|
||||||
Route::get('/login', [AuthController::class, 'index'])->name('login');
|
Route::get('/login', [AuthController::class, 'index'])->name('login');
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user