Merge branch 'afiqhamzah-feat-add-capture-marhun-picture' into 'main'
Afiqhamzah feat add capture marhun picture See merge request online-sistem1/lelong!339
This commit is contained in:
@@ -298,3 +298,5 @@ PUSHER_APP_CLUSTER=mt1
|
||||
|
||||
MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
|
||||
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
|
||||
|
||||
MARHUN_CAMERAS = "Doccamera"
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
'marhun_cameras' => array_map(fn ($camera_label) => trim($camera_label), explode(',', env('MARHUN_CAMERAS'))) ?? 'Doccamera'
|
||||
|
||||
];
|
||||
Vendored
+1
-1
@@ -16805,4 +16805,4 @@ a.article:hover {
|
||||
|
||||
.user-info {
|
||||
/* display: flex; */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
body {
|
||||
padding-right: 0px !important
|
||||
}
|
||||
|
||||
.modal-open {
|
||||
overflow-y: auto;
|
||||
}
|
||||
Vendored
+9
File diff suppressed because one or more lines are too long
Vendored
+11
-1
File diff suppressed because one or more lines are too long
+42
@@ -0,0 +1,42 @@
|
||||
|
||||
function marhunPhotoCapturerDebugger() {
|
||||
|
||||
return {
|
||||
|
||||
scan: function () {
|
||||
if ('mediaDevices' in navigator && navigator.mediaDevices.getUserMedia) {
|
||||
|
||||
// let camera_label = "HP TrueVision HD Camera (05c8:03d2)";
|
||||
// let camera_label = "USB Camera (0c45:6366)";
|
||||
let camera_label = "Doccamera (2b19:0200)";
|
||||
|
||||
const generateCameraListing = (cameras) => {
|
||||
let title = "Available cameras: ";
|
||||
|
||||
let content = cameras.map((camera, index) => {
|
||||
index = index + 1;
|
||||
return `${index}. ${camera.label}\n`;
|
||||
});
|
||||
|
||||
return `${title}\n${content.join('')}`;
|
||||
};
|
||||
|
||||
navigator.mediaDevices.enumerateDevices()
|
||||
.then(devices => devices.filter(x => x.kind === 'videoinput'))
|
||||
.then(devices => devices.map(device => {
|
||||
let altered_label = device.label.split(" ");
|
||||
altered_label.splice(-1);
|
||||
altered_label = altered_label.join(" ");
|
||||
|
||||
return {
|
||||
label: altered_label,
|
||||
deviceId: device.deviceId,
|
||||
};
|
||||
}))
|
||||
.then(devices => alert(generateCameraListing(devices)))
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
}
|
||||
}
|
||||
Vendored
+127
-150
@@ -1,183 +1,160 @@
|
||||
|
||||
function marhunPhotoCapturerFactory(modal_selector) {
|
||||
|
||||
return {
|
||||
return {
|
||||
|
||||
constraints: {
|
||||
audio: false,
|
||||
video: {
|
||||
height: { ideal: 1080 }
|
||||
},
|
||||
facingMode: { exact: "environment" },
|
||||
},
|
||||
constraints: {
|
||||
audio: false,
|
||||
video: true,
|
||||
},
|
||||
|
||||
imageCapturer: null,
|
||||
imageCapturer: null,
|
||||
|
||||
start: function start() {
|
||||
navigator.mediaDevices.getUserMedia(this.constraints)
|
||||
.then(this.gotMedia)
|
||||
.catch(e => { console.error('getUserMedia() failed: ', e); });
|
||||
},
|
||||
captureMedia: function (mediastream) {
|
||||
|
||||
gotMedia: function (mediastream) {
|
||||
let videoTrack = mediastream.getVideoTracks()[0];
|
||||
let imageCapturer = new ImageCapture(videoTrack);
|
||||
|
||||
let modal = document.querySelector(modal_selector);
|
||||
let videoTag = modal.querySelector('.video-tag-overallmarhun');
|
||||
let modal = document.querySelector(modal_selector);
|
||||
let imageTag = modal.querySelector('.image-tag-overallmarhun');
|
||||
|
||||
videoTag.srcObject = mediastream;
|
||||
let setMarhunPhotoInputToCapturedPhoto = function (blob) {
|
||||
const modal = document.querySelector(modal_selector);
|
||||
const marhunPhotoInput = modal.querySelector('#inputGroupFile04');
|
||||
|
||||
let videoTrack = mediastream.getVideoTracks()[0];
|
||||
this.imageCapturer = new ImageCapture(videoTrack);
|
||||
const marhunPhotoFile = new File([blob], 'marhun_photo.png', {
|
||||
type: 'image/png',
|
||||
lastModified: new Date().getTime(),
|
||||
});
|
||||
|
||||
const dataTransfer = new DataTransfer();
|
||||
dataTransfer.items.add(marhunPhotoFile);
|
||||
marhunPhotoInput.files = dataTransfer.files;
|
||||
|
||||
};
|
||||
|
||||
imageCapturer.takePhoto()
|
||||
.then((blob) => {
|
||||
imageTag.src = URL.createObjectURL(blob);
|
||||
imageTag.classList.add('marhun-uploaded');
|
||||
|
||||
|
||||
// Timeout needed in Chrome, see https://crbug.com/711524
|
||||
setTimeout(() => {
|
||||
const capabilities = videoTrack.getCapabilities()
|
||||
console.log(capabilities)
|
||||
modal.querySelector('.video-tag-overallmarhun').classList.add('d-none');
|
||||
|
||||
// Check whether zoom is supported or not.
|
||||
if (!capabilities.zoom) {
|
||||
return;
|
||||
}
|
||||
modal.querySelector('.camera-shutter').classList.remove('d-none');
|
||||
modal.querySelector('.camera-shutter').classList.add('d-flex');
|
||||
|
||||
}, 500);
|
||||
window.setTimeout(() => {
|
||||
modal.querySelector('.image-tag-overallmarhun').classList.remove('d-none');
|
||||
modal.querySelector('.camera-shutter').classList.remove('d-flex');
|
||||
modal.querySelector('.camera-shutter').classList.add('d-none');
|
||||
modal.querySelector('.camera-button').classList.add('d-none')
|
||||
}, 1000);
|
||||
|
||||
},
|
||||
modal.querySelector('button[type="submit"]').disabled = false;
|
||||
|
||||
captureMedia: function (mediastream) {
|
||||
return blob;
|
||||
|
||||
let videoTrack = mediastream.getVideoTracks()[0];
|
||||
let imageCapturer = new ImageCapture(videoTrack);
|
||||
})
|
||||
.then(blob => setMarhunPhotoInputToCapturedPhoto(blob))
|
||||
.catch((err) => {
|
||||
console.error("takePhoto() failed: ", err);
|
||||
});
|
||||
|
||||
let modal = document.querySelector(modal_selector);
|
||||
let imageTag = modal.querySelector('.image-tag-overallmarhun');
|
||||
},
|
||||
|
||||
|
||||
takePhoto: function () {
|
||||
|
||||
let setMarhunPhotoInputToCapturedPhoto = function (blob) {
|
||||
const modal = document.querySelector(modal_selector);
|
||||
const marhunPhotoInput = modal.querySelector('#inputGroupFile04');
|
||||
if ('mediaDevices' in navigator && navigator.mediaDevices.getUserMedia) {
|
||||
this.getCamera()
|
||||
.then(this.captureMedia)
|
||||
.catch(e => { console.error('getUserMedia() failed: ', e); });
|
||||
}
|
||||
},
|
||||
|
||||
getCamera: function () {
|
||||
function getCameraList() {
|
||||
return navigator.mediaDevices.enumerateDevices()
|
||||
.then(devices => devices.filter(x => x.kind === 'videoinput'))
|
||||
}
|
||||
|
||||
function selectNearWorkingCamera(listOfCameras) {
|
||||
return listOfCameras.at(0);
|
||||
}
|
||||
|
||||
|
||||
const marhunPhotoFile = new File([blob], 'marhun_photo.png', {
|
||||
type: 'image/png',
|
||||
lastModified: new Date().getTime(),
|
||||
});
|
||||
function selectPriorityCameraIfExist(listOfCameras) {
|
||||
|
||||
const available_cameras = listOfCameras.map(camera => {
|
||||
let altered_label = camera.label.split(" ");
|
||||
altered_label.splice(-1);
|
||||
altered_label = altered_label.join(" ");
|
||||
|
||||
return {
|
||||
label: altered_label,
|
||||
deviceId: camera.deviceId,
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
const filtered = available_cameras.filter(camera => {
|
||||
return marhun_camera_config.includes(camera.label);
|
||||
})
|
||||
|
||||
// Get the first available priority referencing to env
|
||||
return filtered.at(-1);
|
||||
}
|
||||
|
||||
function selectCamera(listOfCameras) {
|
||||
let priorityCamera = selectPriorityCameraIfExist(listOfCameras);
|
||||
|
||||
if (!priorityCamera) {
|
||||
return selectNearWorkingCamera(listOfCameras)
|
||||
}
|
||||
|
||||
return priorityCamera;
|
||||
}
|
||||
|
||||
function composeConstraint(camera) {
|
||||
var constraints = { deviceId: { exact: camera.deviceId } };
|
||||
return navigator.mediaDevices.getUserMedia({ video: constraints });
|
||||
}
|
||||
|
||||
return getCameraList()
|
||||
.then(selectCamera)
|
||||
.then(composeConstraint);
|
||||
|
||||
},
|
||||
|
||||
initiateTakeMarhunPhoto: function () {
|
||||
if ('mediaDevices' in navigator && navigator.mediaDevices.getUserMedia) {
|
||||
|
||||
|
||||
const dataTransfer = new DataTransfer();
|
||||
dataTransfer.items.add(marhunPhotoFile);
|
||||
marhunPhotoInput.files = dataTransfer.files;
|
||||
function showCaptureMarhunModal() {
|
||||
let modal = document.querySelector(modal_selector);
|
||||
|
||||
};
|
||||
modal.querySelector('.video-tag-overallmarhun').classList.remove('d-none');
|
||||
modal.querySelector('.image-tag-overallmarhun').classList.add('d-none');
|
||||
modal.querySelector('.camera-shutter').classList.add('d-none');
|
||||
modal.querySelector('.camera-button').classList.remove('d-none');
|
||||
modal.querySelector('button[type="submit"]').disabled = true;
|
||||
|
||||
imageCapturer.takePhoto()
|
||||
.then((blob) => {
|
||||
imageTag.src = URL.createObjectURL(blob);
|
||||
imageTag.classList.add('marhun-uploaded');
|
||||
$(modal_selector).modal('show');
|
||||
}
|
||||
|
||||
function streamCameraView(stream) {
|
||||
let modal = document.querySelector(modal_selector);
|
||||
let videoTag = modal.querySelector('.video-tag-overallmarhun');
|
||||
|
||||
modal.querySelector('.video-tag-overallmarhun').classList.add('d-none');
|
||||
videoTag.srcObject = stream;
|
||||
}
|
||||
|
||||
modal.querySelector('.camera-shutter').classList.remove('d-none');
|
||||
modal.querySelector('.camera-shutter').classList.add('d-flex');
|
||||
|
||||
window.setTimeout(() => {
|
||||
modal.querySelector('.image-tag-overallmarhun').classList.remove('d-none');
|
||||
modal.querySelector('.camera-shutter').classList.remove('d-flex');
|
||||
modal.querySelector('.camera-shutter').classList.add('d-none');
|
||||
modal.querySelector('.camera-button').classList.add('d-none')
|
||||
}, 1500);
|
||||
|
||||
modal.querySelector('button[type="submit"]').disabled = false;
|
||||
|
||||
return blob;
|
||||
|
||||
})
|
||||
.then(blob => setMarhunPhotoInputToCapturedPhoto(blob))
|
||||
.catch((err) => {
|
||||
console.error("takePhoto() failed: ", err);
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
|
||||
takePhoto: function () {
|
||||
navigator.mediaDevices.getUserMedia(this.constraints)
|
||||
.then(this.captureMedia)
|
||||
.catch(e => { console.error('getUserMedia() failed: ', e); });
|
||||
},
|
||||
|
||||
viewCapturedPhoto: function () {
|
||||
|
||||
let imageTag = document.getElementById('image-tag');
|
||||
|
||||
if (!imageTag.classList.contains('marhun-uploaded')) {
|
||||
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Amaran!',
|
||||
text: 'Sila ambil gambar marhun'
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
displayInNewTab(imageTag.src);
|
||||
},
|
||||
|
||||
displayInNewTab: function (src) {
|
||||
let image = new Image();
|
||||
image.src = src;
|
||||
|
||||
let w = window.open("");
|
||||
w.document.write(image.outerHTML);
|
||||
},
|
||||
|
||||
initiateTakeMarhunPhoto: function () {
|
||||
|
||||
navigator.mediaDevices.getUserMedia(this.constraints)
|
||||
.then(this.gotMedia)
|
||||
.catch(e => { console.error('getUserMedia() failed: ', e); });
|
||||
|
||||
let modal = document.querySelector(modal_selector);
|
||||
|
||||
modal.querySelector('.video-tag-overallmarhun').classList.remove('d-none');
|
||||
modal.querySelector('.image-tag-overallmarhun').classList.add('d-none');
|
||||
modal.querySelector('.camera-shutter').classList.add('d-none');
|
||||
modal.querySelector('.camera-button').classList.remove('d-none');
|
||||
modal.querySelector('button[type="submit"]').disabled = true;
|
||||
|
||||
$(modal_selector).modal('show');
|
||||
},
|
||||
|
||||
|
||||
initiateUploadMarhunPhoto: function () {
|
||||
let file_marhun_photo = document.getElementById('marhun_photo');
|
||||
let image_tag = document.getElementById('image-tag');
|
||||
|
||||
let displayUploadFileToImageTag = (event) => {
|
||||
let selectedFile = event.target.files[0];
|
||||
let reader = new FileReader();
|
||||
|
||||
image_tag.title = selectedFile.name;
|
||||
|
||||
reader.onload = function (event) {
|
||||
image_tag.src = event.target.result;
|
||||
};
|
||||
|
||||
reader.readAsDataURL(selectedFile);
|
||||
|
||||
this.removeEventListener('change', displayUploadFileToImageTag);
|
||||
|
||||
};
|
||||
|
||||
file_marhun_photo.addEventListener('change', displayUploadFileToImageTag);
|
||||
|
||||
image_tag.classList.add('marhun-uploaded');
|
||||
|
||||
file_marhun_photo.click();
|
||||
this.getCamera()
|
||||
.then(streamCameraView)
|
||||
.then(showCaptureMarhunModal);
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Vendored
+52
@@ -0,0 +1,52 @@
|
||||
function marhunPhotoViewerFactory(button_selector) {
|
||||
|
||||
return {
|
||||
attachPhotoViewer: function () {
|
||||
|
||||
if(! document.querySelector(button_selector)){
|
||||
return;
|
||||
};
|
||||
|
||||
document.querySelector(button_selector).addEventListener('click', (event) => {
|
||||
event.preventDefault();
|
||||
|
||||
const image = new Image();
|
||||
image.src = event.target.href
|
||||
|
||||
const viewer = new Viewer(image, {
|
||||
hidden: function () {
|
||||
viewer.destroy();
|
||||
},
|
||||
navbar: false,
|
||||
title: false,
|
||||
toolbar: {
|
||||
zoomIn: {
|
||||
show: true,
|
||||
size: 'large',
|
||||
},
|
||||
oneToOne: {
|
||||
show: true,
|
||||
size: 'large',
|
||||
},
|
||||
zoomOut: {
|
||||
show: true,
|
||||
size: 'large',
|
||||
},
|
||||
},
|
||||
viewed() {
|
||||
// Zoom to 50% from the center of the window.
|
||||
viewer.zoomTo(1.25, {
|
||||
x: window.innerWidth / 2,
|
||||
y: viewer.innerHeight / 2,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
viewer.show();
|
||||
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
+2
-1
@@ -1,8 +1,9 @@
|
||||
try {
|
||||
window.Popper = require('popper.js').default;
|
||||
window.$ = window.jQuery = require('jquery');
|
||||
window.Viewer = require('viewerjs');
|
||||
|
||||
require('bootstrap');
|
||||
require('datatables.net-bs4');
|
||||
require('jquery-confirm');
|
||||
} catch (e) {}
|
||||
} catch (e) {}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
<head>
|
||||
@include('includes.head')
|
||||
|
||||
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
$('#sidebarCollapse').on('click', function() {
|
||||
@@ -64,6 +64,7 @@
|
||||
</script>
|
||||
|
||||
@stack('additional_scripts')
|
||||
@stack('additional_styles')
|
||||
</head>
|
||||
|
||||
<body onload="startTime()">
|
||||
@@ -78,4 +79,4 @@
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
</html>
|
||||
|
||||
@@ -3,17 +3,25 @@
|
||||
@push('additional_scripts')
|
||||
<script src="{{ asset('js/marhun-photo-capture.js') }}"></script>
|
||||
<script src="{{ asset('js/marhun-photo-capture-reload-https.js') }}"></script>
|
||||
<script src="{{ asset('js/marhun-photo-capture-debugger.js') }}"></script>
|
||||
<script src="{{ asset('js/marhun-photo-viewer.js') }}"></script>
|
||||
<script>
|
||||
var marhun_camera_config = @json(config('marhun_camera.marhun_cameras'));
|
||||
let modalOverallPhotoCapture = new marhunPhotoCapturerFactory('#modaloverallphoto-capture');
|
||||
let modalOverallPhotoCaptureUpdate = new marhunPhotoCapturerFactory('#modaloverallphoto-capture-update');
|
||||
let modalOverallPhotoCapturePerMarhun = new marhunPhotoCapturerFactory('#modalpermarhunphoto-capture');
|
||||
let modalOverallPhotoCapturePerMarhunUpdate = new marhunPhotoCapturerFactory('#modalpermarhunphoto-capture-update');
|
||||
let marhunPhotoCapturerReloadHttps = new marhunPhotoCapturerReloadHttpsFactory();
|
||||
let marhunPhotoCapturerDebuggerObj = new marhunPhotoCapturerDebugger();
|
||||
let marhunPhotoViewerOverall = new marhunPhotoViewerFactory('a.btn-view-overall-marhun-photo');
|
||||
let marhunPhotoViewerPerMarhun = new marhunPhotoViewerFactory('a.viewPhotoEachMarhunLink');
|
||||
</script>
|
||||
@endpush
|
||||
|
||||
@push('additional_styles')
|
||||
<link rel="stylesheet" href="{{ asset('css/marhun-registrations-webcam.css') }}">
|
||||
<link rel="stylesheet" href="{{ asset('css/viewer.min.css') }}">
|
||||
<link rel="stylesheet" href="{{ asset('css/fix-page-zoom-when-modal-load.css') }}">
|
||||
@endpush
|
||||
|
||||
@section('content')
|
||||
@@ -75,9 +83,15 @@
|
||||
<button
|
||||
data-dismiss="modal"
|
||||
onclick="modalOverallPhotoCapture.initiateTakeMarhunPhoto()" type="button"
|
||||
class="btn btn-primary btn-md text-white"
|
||||
>Ambil Gambar Marhun
|
||||
</button>
|
||||
<button type="button" data-toggle="modal" data-target="#modaloverallphoto">Muat Naik Gambar Marhun</button>
|
||||
<button
|
||||
type="button"
|
||||
data-toggle="modal"
|
||||
data-target="#modaloverallphoto"
|
||||
class="btn btn-primary btn-md text-white"
|
||||
>Muat Naik Gambar Marhun</button>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
@@ -107,26 +121,31 @@
|
||||
<td class="p-2 m-2" style="border: 1px solid black; width: 100px; height: 130px">
|
||||
@if (empty($item->eachmarhun_filename))
|
||||
<div class="btn-group" role="group" style="width: 100%;">
|
||||
<button data-toggle="modal" onclick="eachMarhunData(this)"
|
||||
class="btn btn-lg btn-light" data-lelongid="{{ $lelongbid['lelong_id'] }}"
|
||||
data-lelongbidid="{{ $lelongbid['id'] }}"
|
||||
data-loop="{{ $loop->iteration }}"
|
||||
data-fileid="{{ $item->eachmarhun_id }}"
|
||||
data-filename="{{ $item->eachmarhun_filename }}"
|
||||
data-marhun="{{ $item->marhun }}" data-marhunid="{{ $item->id }}"
|
||||
data-target="#modaleachphoto" style="border-radius: 0 !important">
|
||||
<i class="fas fa-upload"></i>
|
||||
</button>
|
||||
<button data-toggle="modal" onclick="eachMarhunDataCapturePhoto(this)"
|
||||
class="btn btn-lg btn-light" data-lelongid="{{ $lelongbid['lelong_id'] }}"
|
||||
data-lelongbidid="{{ $lelongbid['id'] }}"
|
||||
data-loop="{{ $loop->iteration }}"
|
||||
data-fileid="{{ $item->eachmarhun_id }}"
|
||||
data-filename="{{ $item->eachmarhun_filename }}"
|
||||
data-marhun="{{ $item->marhun }}" data-marhunid="{{ $item->id }}"
|
||||
style="border-radius: 0 !important">
|
||||
<i class="fas fa-camera"></i>
|
||||
</button>
|
||||
<span data-toggle="tooltip" data-placement="top" title="Muat naik gambar per marhun">
|
||||
<button data-toggle="modal" onclick="eachMarhunData(this)"
|
||||
class="btn btn-lg text-" data-lelongid="{{ $lelongbid['lelong_id'] }}"
|
||||
data-lelongbidid="{{ $lelongbid['id'] }}"
|
||||
data-loop="{{ $loop->iteration }}"
|
||||
data-fileid="{{ $item->eachmarhun_id }}"
|
||||
data-filename="{{ $item->eachmarhun_filename }}"
|
||||
data-marhun="{{ $item->marhun }}" data-marhunid="{{ $item->id }}"
|
||||
data-target="#modaleachphoto"
|
||||
style="border-radius: 0 !important">
|
||||
<i class="fas fa-upload"></i>
|
||||
</button>
|
||||
</span>
|
||||
<span data-toggle="tooltip" data-placement="top" title="Ambil gambar per marhun">
|
||||
<button data-toggle="modal" onclick="eachMarhunDataCapturePhoto(this)"
|
||||
class="btn btn-lg" data-lelongid="{{ $lelongbid['lelong_id'] }}"
|
||||
data-lelongbidid="{{ $lelongbid['id'] }}"
|
||||
data-loop="{{ $loop->iteration }}"
|
||||
data-fileid="{{ $item->eachmarhun_id }}"
|
||||
data-filename="{{ $item->eachmarhun_filename }}"
|
||||
data-marhun="{{ $item->marhun }}" data-marhunid="{{ $item->id }}"
|
||||
style="border-radius: 0 !important">
|
||||
<i class="fas fa-camera"></i>
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<img src="{{ asset('img/no-image.png') }}" alt="Tambah / Padam Gambar"
|
||||
@@ -432,7 +451,7 @@
|
||||
@php
|
||||
$imageLink = route('marhun.showphotomarhun', ['norujukan_sag' => $lelongbid['norujukan'], 'filemarhun_id' => $lelongbid['filemarhun_id']]);
|
||||
@endphp
|
||||
<a href="{{ $imageLink }}" target="_blank" class="btn m-2 btn-warning">Lihat gambar</a>
|
||||
<a href="{{ $imageLink }}" target="_blank" class="btn m-2 btn-warning btn-view-overall-marhun-photo">Lihat gambar</a>
|
||||
<button data-dismiss="modal" onclick="updatePhoto(1)" type="button"
|
||||
data-target="#modalupdatephoto" data-toggle="modal" class="btn m-2 btn-warning action-invalid-after-semak">Muat naik gambar baru</button>
|
||||
<button data-dismiss="modal"
|
||||
@@ -874,5 +893,8 @@
|
||||
$("#formkemaskini").submit();
|
||||
}
|
||||
|
||||
marhunPhotoViewerOverall.attachPhotoViewer();
|
||||
marhunPhotoViewerPerMarhun.attachPhotoViewer();
|
||||
|
||||
</script>
|
||||
@endsection
|
||||
|
||||
Reference in New Issue
Block a user