Enhance dashboard UX, fix logout, and localize all external libraries
- Make all dashboard cards clickable (13 cards total) for better UX - Fix logout confirmation for kaur level with robust jQuery handler - Download all external libraries locally for offline capability: * Ionicons CSS + fonts * Cropper.js v1.5.13 (CSS + JS) * Chart.js v3.9.1 (fixed chart display) * jscanify library * Google Fonts - Source Sans Pro (CSS + TTF) * OpenCV.js v4.7.0 (8.75MB) - Update all CDN references to local paths in index.php and login.php - Add vendor directory exception to .gitignore - Improve session destruction in logout.php - Add console debugging for chart initialization
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -13,6 +13,7 @@ Thumbs.db
|
||||
# Dependencies (if any in future)
|
||||
node_modules/
|
||||
vendor/
|
||||
!plugins/vendor/
|
||||
|
||||
# Uploads
|
||||
foto/
|
||||
|
||||
149
home/admin.php
149
home/admin.php
@@ -304,52 +304,105 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
// Data from PHP
|
||||
var donutChartCanvas = $('#donutChart').get(0).getContext('2d')
|
||||
var donutData = {
|
||||
labels: [
|
||||
'Balita',
|
||||
'Anak-anak',
|
||||
'Remaja',
|
||||
'Dewasa',
|
||||
'Lansia'
|
||||
],
|
||||
datasets: [
|
||||
{
|
||||
data: [
|
||||
<?php echo $balita; ?>,
|
||||
<?php echo $anak; ?>,
|
||||
<?php echo $remaja; ?>,
|
||||
<?php echo $dewasa; ?>,
|
||||
<?php echo $lansia; ?>
|
||||
],
|
||||
backgroundColor : ['#17a2b8', '#28a745', '#6f42c1', '#007bff', '#6c757d'],
|
||||
}
|
||||
]
|
||||
}
|
||||
var donutOptions = {
|
||||
maintainAspectRatio : false,
|
||||
responsive : true,
|
||||
plugins: {
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Komposisi Penduduk Berdasarkan Usia',
|
||||
font: {
|
||||
size: 16
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
display: true,
|
||||
position: 'right'
|
||||
}
|
||||
}
|
||||
}
|
||||
new Chart(donutChartCanvas, {
|
||||
type: 'doughnut',
|
||||
data: donutData,
|
||||
options: donutOptions
|
||||
})
|
||||
});
|
||||
<script>
|
||||
window.addEventListener('load', function() {
|
||||
console.log('Page fully loaded - Checking libraries...');
|
||||
console.log('jQuery available?', typeof $);
|
||||
console.log('Chart.js available?', typeof Chart);
|
||||
|
||||
// Check if jQuery is loaded
|
||||
if (typeof $ === 'undefined') {
|
||||
console.error('jQuery is not loaded. Chart cannot be initialized.');
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if Chart.js is loaded
|
||||
if (typeof Chart === 'undefined') {
|
||||
console.error('Chart.js is not loaded. Check if the script is loaded correctly.');
|
||||
// Try to load Chart.js dynamically as fallback
|
||||
var script = document.createElement('script');
|
||||
script.src = 'plugins/vendor/chartjs/chart-3.9.1.min.js';
|
||||
script.onload = function() {
|
||||
console.log('Chart.js loaded dynamically, initializing chart...');
|
||||
initializeChart();
|
||||
};
|
||||
document.head.appendChild(script);
|
||||
} else {
|
||||
initializeChart();
|
||||
}
|
||||
|
||||
function initializeChart() {
|
||||
console.log('Initializing chart...');
|
||||
|
||||
// Check if canvas exists
|
||||
var canvas = document.getElementById('donutChart');
|
||||
if (!canvas) {
|
||||
console.error('Canvas element with id "donutChart" not found');
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if jQuery can get the canvas
|
||||
var $canvas = $('#donutChart');
|
||||
if ($canvas.length === 0) {
|
||||
console.error('jQuery cannot find canvas with id "donutChart"');
|
||||
return;
|
||||
}
|
||||
|
||||
// Get context
|
||||
var donutChartCanvas = $canvas.get(0).getContext('2d');
|
||||
if (!donutChartCanvas) {
|
||||
console.error('Could not get 2d context from canvas');
|
||||
return;
|
||||
}
|
||||
|
||||
// Data from PHP
|
||||
var donutData = {
|
||||
labels: [
|
||||
'Balita',
|
||||
'Anak-anak',
|
||||
'Remaja',
|
||||
'Dewasa',
|
||||
'Lansia'
|
||||
],
|
||||
datasets: [{
|
||||
data: [
|
||||
<?php echo $balita; ?>,
|
||||
<?php echo $anak; ?>,
|
||||
<?php echo $remaja; ?>,
|
||||
<?php echo $dewasa; ?>,
|
||||
<?php echo $lansia; ?>
|
||||
],
|
||||
backgroundColor: ['#17a2b8', '#28a745', '#6f42c1', '#007bff', '#6c757d']
|
||||
}]
|
||||
};
|
||||
|
||||
var donutOptions = {
|
||||
maintainAspectRatio: false,
|
||||
responsive: true,
|
||||
plugins: {
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Komposisi Penduduk Berdasarkan Usia',
|
||||
font: { size: 16 }
|
||||
},
|
||||
legend: {
|
||||
display: true,
|
||||
position: 'right'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
new Chart(donutChartCanvas, {
|
||||
type: 'doughnut',
|
||||
data: donutData,
|
||||
options: donutOptions
|
||||
});
|
||||
console.log('Chart initialized successfully');
|
||||
} catch (error) {
|
||||
console.error('Error initializing chart:', error);
|
||||
console.error('Error details:', error.message, error.stack);
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
121
home/kaur.php
121
home/kaur.php
@@ -304,52 +304,77 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
// Data from PHP
|
||||
var donutChartCanvas = $('#donutChart').get(0).getContext('2d')
|
||||
var donutData = {
|
||||
labels: [
|
||||
'Balita',
|
||||
'Anak-anak',
|
||||
'Remaja',
|
||||
'Dewasa',
|
||||
'Lansia'
|
||||
],
|
||||
datasets: [
|
||||
{
|
||||
data: [
|
||||
<?php echo $balita; ?>,
|
||||
<?php echo $anak; ?>,
|
||||
<?php echo $remaja; ?>,
|
||||
<?php echo $dewasa; ?>,
|
||||
<?php echo $lansia; ?>
|
||||
],
|
||||
backgroundColor : ['#17a2b8', '#28a745', '#6f42c1', '#007bff', '#6c757d'],
|
||||
}
|
||||
]
|
||||
}
|
||||
var donutOptions = {
|
||||
maintainAspectRatio : false,
|
||||
responsive : true,
|
||||
plugins: {
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Komposisi Penduduk Berdasarkan Usia',
|
||||
font: {
|
||||
size: 16
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
display: true,
|
||||
position: 'right'
|
||||
}
|
||||
}
|
||||
}
|
||||
new Chart(donutChartCanvas, {
|
||||
type: 'doughnut',
|
||||
data: donutData,
|
||||
options: donutOptions
|
||||
})
|
||||
});
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
console.log('DOMContentLoaded - Chart.js available?', typeof Chart);
|
||||
|
||||
// Check if Chart.js is loaded
|
||||
if (typeof Chart === 'undefined') {
|
||||
console.error('Chart.js is not loaded. Check if the script is loaded correctly.');
|
||||
// Try to load Chart.js dynamically as fallback
|
||||
var script = document.createElement('script');
|
||||
script.src = 'plugins/vendor/chartjs/chart.min.js';
|
||||
script.onload = function() {
|
||||
console.log('Chart.js loaded dynamically, initializing chart...');
|
||||
initializeChart();
|
||||
};
|
||||
document.head.appendChild(script);
|
||||
} else {
|
||||
initializeChart();
|
||||
}
|
||||
|
||||
function initializeChart() {
|
||||
console.log('Initializing chart...');
|
||||
// Data from PHP
|
||||
var donutChartCanvas = $('#donutChart').get(0).getContext('2d')
|
||||
var donutData = {
|
||||
labels: [
|
||||
'Balita',
|
||||
'Anak-anak',
|
||||
'Remaja',
|
||||
'Dewasa',
|
||||
'Lansia'
|
||||
],
|
||||
datasets: [
|
||||
{
|
||||
data: [
|
||||
<?php echo $balita; ?>,
|
||||
<?php echo $anak; ?>,
|
||||
<?php echo $remaja; ?>,
|
||||
<?php echo $dewasa; ?>,
|
||||
<?php echo $lansia; ?>
|
||||
],
|
||||
backgroundColor : ['#17a2b8', '#28a745', '#6f42c1', '#007bff', '#6c757d'],
|
||||
}
|
||||
]
|
||||
}
|
||||
var donutOptions = {
|
||||
maintainAspectRatio : false,
|
||||
responsive : true,
|
||||
plugins: {
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Komposisi Penduduk Berdasarkan Usia',
|
||||
font: {
|
||||
size: 16
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
display: true,
|
||||
position: 'right'
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
new Chart(donutChartCanvas, {
|
||||
type: 'doughnut',
|
||||
data: donutData,
|
||||
options: donutOptions
|
||||
});
|
||||
console.log('Chart initialized successfully');
|
||||
} catch (error) {
|
||||
console.error('Error initializing chart:', error);
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
112
index.php
112
index.php
@@ -35,7 +35,7 @@
|
||||
<!-- Font Awesome -->
|
||||
<link rel="stylesheet" href="plugins/fontawesome-free/css/all.min.css">
|
||||
<!-- Ionicons -->
|
||||
<link rel="stylesheet" href="https://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css">
|
||||
<link rel="stylesheet" href="plugins/vendor/ionicons/css/ionicons.min.css">
|
||||
<!-- DataTables -->
|
||||
<link rel="stylesheet" href="plugins/datatables-bs4/css/dataTables.bootstrap4.css">
|
||||
<!-- overlayScrollbars -->
|
||||
@@ -44,9 +44,9 @@
|
||||
<link rel="stylesheet" href="plugins/select2/css/select2.min.css">
|
||||
<link rel="stylesheet" href="plugins/select2-bootstrap4-theme/select2-bootstrap4.min.css">
|
||||
<!-- Cropper.js -->
|
||||
<link href="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.5.13/cropper.min.css" rel="stylesheet">
|
||||
<link href="plugins/vendor/cropperjs/css/cropper.min.css" rel="stylesheet">
|
||||
<!-- Google Font: Source Sans Pro -->
|
||||
<link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,400i,700" rel="stylesheet">
|
||||
<link href="plugins/vendor/google-fonts/source-sans-pro/css/fonts-local.css" rel="stylesheet">
|
||||
<!-- Modern CSS -->
|
||||
<link rel="stylesheet" href="dist/css/modern.css">
|
||||
<!-- Alert -->
|
||||
@@ -483,7 +483,7 @@
|
||||
?>
|
||||
|
||||
<li class="nav-item">
|
||||
<a onclick="confirmLogout(event)" href="logout.php" class="nav-link">
|
||||
<a href="logout.php" class="nav-link logout-link">
|
||||
<i class="nav-icon fas fa-arrow-circle-right"></i>
|
||||
<p>
|
||||
Logout
|
||||
@@ -724,16 +724,18 @@
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="plugins/jquery/jquery.min.js"></script>
|
||||
<!-- ChartJS -->
|
||||
<script src="plugins/vendor/chartjs/chart-3.9.1.min.js"></script>
|
||||
<!-- Bootstrap 4 -->
|
||||
<script src="plugins/bootstrap/js/bootstrap.bundle.min.js"></script>
|
||||
<!-- Select2 -->
|
||||
<script src="plugins/select2/js/select2.full.min.js"></script>
|
||||
<!-- Cropper.js -->
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.5.13/cropper.min.js"></script>
|
||||
<script src="plugins/vendor/cropperjs/js/cropper.min.js"></script>
|
||||
<!-- OpenCV.js (Required for jscanify) -->
|
||||
<script src="https://docs.opencv.org/4.7.0/opencv.js" async></script>
|
||||
<script src="plugins/vendor/opencv/opencv.js" async></script>
|
||||
<!-- jscanify -->
|
||||
<script src="https://cdn.jsdelivr.net/gh/ColonelParrot/jscanify@master/src/jscanify.min.js"></script>
|
||||
<script src="plugins/vendor/jscanify/jscanify.min.js"></script>
|
||||
<!-- DataTables -->
|
||||
<script src="plugins/datatables/jquery.dataTables.js"></script>
|
||||
<script src="plugins/datatables-bs4/js/dataTables.bootstrap4.js"></script>
|
||||
@@ -799,32 +801,47 @@
|
||||
$('#imageModal').modal('show');
|
||||
}
|
||||
|
||||
function confirmLogout(event) {
|
||||
event.preventDefault();
|
||||
var logoutUrl = event.currentTarget.href;
|
||||
|
||||
// Check if SweetAlert2 is available
|
||||
if (typeof Swal !== 'undefined' && Swal.fire) {
|
||||
Swal.fire({
|
||||
title: 'Konfirmasi Logout',
|
||||
text: 'Apakah Anda yakin akan keluar dari sistem?',
|
||||
icon: 'question',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#3085d6',
|
||||
cancelButtonColor: '#d33',
|
||||
confirmButtonText: 'Ya, Keluar',
|
||||
cancelButtonText: 'Batal'
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
window.location.href = logoutUrl;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// Fallback to standard confirm dialog
|
||||
if (confirm('Apakah Anda yakin akan keluar dari sistem?')) {
|
||||
window.location.href = logoutUrl;
|
||||
function confirmLogout(element, event) {
|
||||
try {
|
||||
console.log('Logout function called for element:', element);
|
||||
|
||||
// Always prevent default behavior
|
||||
if (event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
// Prevent multiple clicks
|
||||
if (element.getAttribute('data-logging-out') === 'true') {
|
||||
console.log('Already logging out, ignoring');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Mark as logging out
|
||||
element.setAttribute('data-logging-out', 'true');
|
||||
|
||||
var logoutUrl = element.href;
|
||||
console.log('Logout URL:', logoutUrl);
|
||||
|
||||
// Debug SweetAlert2 availability
|
||||
console.log('Swal exists:', typeof Swal, 'Swal.fire:', Swal && Swal.fire);
|
||||
|
||||
// Use simple confirm for now to ensure it works
|
||||
if (confirm('Apakah Anda yakin akan keluar dari sistem?')) {
|
||||
console.log('User confirmed logout, redirecting...');
|
||||
window.location.href = logoutUrl;
|
||||
} else {
|
||||
console.log('User cancelled logout');
|
||||
element.removeAttribute('data-logging-out');
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('Logout error:', error);
|
||||
// As last resort, go directly to logout
|
||||
window.location.href = element.href;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function zoomIn() {
|
||||
@@ -882,10 +899,39 @@
|
||||
(delta > 0) ? zoomIn() : zoomOut();
|
||||
}
|
||||
}
|
||||
|
||||
// Handle logout link clicks
|
||||
$(document).ready(function() {
|
||||
console.log('Document ready, attaching logout handler');
|
||||
$(document).on('click', '.logout-link', function(event) {
|
||||
console.log('Logout link clicked');
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
var element = this;
|
||||
var logoutUrl = element.href;
|
||||
|
||||
// Prevent multiple clicks
|
||||
if ($(element).attr('data-logging-out') === 'true') {
|
||||
console.log('Already logging out');
|
||||
return false;
|
||||
}
|
||||
$(element).attr('data-logging-out', 'true');
|
||||
|
||||
// Show confirmation
|
||||
if (confirm('Apakah Anda yakin akan keluar dari sistem?')) {
|
||||
console.log('User confirmed logout');
|
||||
window.location.href = logoutUrl;
|
||||
} else {
|
||||
console.log('User cancelled logout');
|
||||
$(element).removeAttr('data-logging-out');
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- ChartJS -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -19,7 +19,7 @@
|
||||
<!-- Font Awesome -->
|
||||
<link rel="stylesheet" href="plugins/fontawesome-free/css/all.min.css">
|
||||
<!-- Ionicons -->
|
||||
<link rel="stylesheet" href="https://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css">
|
||||
<link rel="stylesheet" href="plugins/vendor/ionicons/css/ionicons.min.css">
|
||||
<!-- icheck bootstrap -->
|
||||
<link rel="stylesheet" href="plugins/icheck-bootstrap/icheck-bootstrap.min.css">
|
||||
<!-- Theme style -->
|
||||
@@ -27,7 +27,7 @@
|
||||
<!-- Modern CSS -->
|
||||
<link rel="stylesheet" href="dist/css/modern.css">
|
||||
<!-- Google Font: Source Sans Pro -->
|
||||
<link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,400i,700" rel="stylesheet">
|
||||
<link href="plugins/vendor/google-fonts/source-sans-pro/css/fonts-local.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body class="hold-transition login-page">
|
||||
|
||||
61
logout.php
61
logout.php
@@ -1,25 +1,38 @@
|
||||
<?php
|
||||
// Start session if not already started
|
||||
if (session_status() === PHP_SESSION_NONE) {
|
||||
session_start();
|
||||
}
|
||||
|
||||
// Clear all session variables
|
||||
$_SESSION = array();
|
||||
|
||||
// If it's desired to kill the session, also delete the session cookie
|
||||
if (ini_get("session.use_cookies")) {
|
||||
$params = session_get_cookie_params();
|
||||
setcookie(session_name(), '', time() - 42000,
|
||||
$params["path"], $params["domain"],
|
||||
$params["secure"], $params["httponly"]
|
||||
);
|
||||
}
|
||||
|
||||
// Finally, destroy the session
|
||||
session_destroy();
|
||||
|
||||
// Redirect to login page using PHP header first
|
||||
header("Location: login.php");
|
||||
exit();
|
||||
?>
|
||||
// Turn off error reporting to prevent warnings
|
||||
error_reporting(0);
|
||||
|
||||
// Prevent any output
|
||||
ob_start();
|
||||
|
||||
// Start session if not already started
|
||||
if (session_status() === PHP_SESSION_NONE) {
|
||||
@session_start();
|
||||
}
|
||||
|
||||
// Clear session data
|
||||
$_SESSION = [];
|
||||
|
||||
// Delete session cookie
|
||||
if (ini_get("session.use_cookies")) {
|
||||
$params = session_get_cookie_params();
|
||||
setcookie(session_name(), '', time() - 3600,
|
||||
$params["path"], $params["domain"],
|
||||
$params["secure"], $params["httponly"]
|
||||
);
|
||||
}
|
||||
|
||||
// Destroy session if active
|
||||
if (session_status() === PHP_SESSION_ACTIVE) {
|
||||
@session_destroy();
|
||||
}
|
||||
|
||||
// Clear output buffer
|
||||
ob_end_clean();
|
||||
|
||||
// Set headers
|
||||
header("Cache-Control: no-cache, no-store, must-revalidate");
|
||||
header("Pragma: no-cache");
|
||||
header("Expires: 0");
|
||||
header("Location: login.php");
|
||||
exit();
|
||||
13
plugins/vendor/chartjs/chart-3.9.1.min.js
vendored
Normal file
13
plugins/vendor/chartjs/chart-3.9.1.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
14
plugins/vendor/chartjs/chart.min.js
vendored
Normal file
14
plugins/vendor/chartjs/chart.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
9
plugins/vendor/cropperjs/css/cropper.min.css
vendored
Normal file
9
plugins/vendor/cropperjs/css/cropper.min.css
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
/*!
|
||||
* Cropper.js v1.5.13
|
||||
* https://fengyuanchen.github.io/cropperjs
|
||||
*
|
||||
* Copyright 2015-present Chen Fengyuan
|
||||
* Released under the MIT license
|
||||
*
|
||||
* Date: 2022-11-20T05:30:43.444Z
|
||||
*/.cropper-container{direction:ltr;font-size:0;line-height:0;position:relative;-ms-touch-action:none;touch-action:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.cropper-container img{-webkit-backface-visibility:hidden;backface-visibility:hidden;display:block;height:100%;image-orientation:0deg;max-height:none!important;max-width:none!important;min-height:0!important;min-width:0!important;width:100%}.cropper-canvas,.cropper-crop-box,.cropper-drag-box,.cropper-modal,.cropper-wrap-box{bottom:0;left:0;position:absolute;right:0;top:0}.cropper-canvas,.cropper-wrap-box{overflow:hidden}.cropper-drag-box{background-color:#fff;opacity:0}.cropper-modal{background-color:#000;opacity:.5}.cropper-view-box{display:block;height:100%;outline:1px solid #39f;outline-color:rgba(51,153,255,.75);overflow:hidden;width:100%}.cropper-dashed{border:0 dashed #eee;display:block;opacity:.5;position:absolute}.cropper-dashed.dashed-h{border-bottom-width:1px;border-top-width:1px;height:33.33333%;left:0;top:33.33333%;width:100%}.cropper-dashed.dashed-v{border-left-width:1px;border-right-width:1px;height:100%;left:33.33333%;top:0;width:33.33333%}.cropper-center{display:block;height:0;left:50%;opacity:.75;position:absolute;top:50%;width:0}.cropper-center:after,.cropper-center:before{background-color:#eee;content:" ";display:block;position:absolute}.cropper-center:before{height:1px;left:-3px;top:0;width:7px}.cropper-center:after{height:7px;left:0;top:-3px;width:1px}.cropper-face,.cropper-line,.cropper-point{display:block;height:100%;opacity:.1;position:absolute;width:100%}.cropper-face{background-color:#fff;left:0;top:0}.cropper-line{background-color:#39f}.cropper-line.line-e{cursor:ew-resize;right:-3px;top:0;width:5px}.cropper-line.line-n{cursor:ns-resize;height:5px;left:0;top:-3px}.cropper-line.line-w{cursor:ew-resize;left:-3px;top:0;width:5px}.cropper-line.line-s{bottom:-3px;cursor:ns-resize;height:5px;left:0}.cropper-point{background-color:#39f;height:5px;opacity:.75;width:5px}.cropper-point.point-e{cursor:ew-resize;margin-top:-3px;right:-3px;top:50%}.cropper-point.point-n{cursor:ns-resize;left:50%;margin-left:-3px;top:-3px}.cropper-point.point-w{cursor:ew-resize;left:-3px;margin-top:-3px;top:50%}.cropper-point.point-s{bottom:-3px;cursor:s-resize;left:50%;margin-left:-3px}.cropper-point.point-ne{cursor:nesw-resize;right:-3px;top:-3px}.cropper-point.point-nw{cursor:nwse-resize;left:-3px;top:-3px}.cropper-point.point-sw{bottom:-3px;cursor:nesw-resize;left:-3px}.cropper-point.point-se{bottom:-3px;cursor:nwse-resize;height:20px;opacity:1;right:-3px;width:20px}@media (min-width:768px){.cropper-point.point-se{height:15px;width:15px}}@media (min-width:992px){.cropper-point.point-se{height:10px;width:10px}}@media (min-width:1200px){.cropper-point.point-se{height:5px;opacity:.75;width:5px}}.cropper-point.point-se:before{background-color:#39f;bottom:-50%;content:" ";display:block;height:200%;opacity:0;position:absolute;right:-50%;width:200%}.cropper-invisible{opacity:0}.cropper-bg{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMz////TjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC")}.cropper-hide{display:block;height:0;position:absolute;width:0}.cropper-hidden{display:none!important}.cropper-move{cursor:move}.cropper-crop{cursor:crosshair}.cropper-disabled .cropper-drag-box,.cropper-disabled .cropper-face,.cropper-disabled .cropper-line,.cropper-disabled .cropper-point{cursor:not-allowed}
|
||||
10
plugins/vendor/cropperjs/js/cropper.min.js
vendored
Normal file
10
plugins/vendor/cropperjs/js/cropper.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
24
plugins/vendor/google-fonts/source-sans-pro/css/fonts-local.css
vendored
Normal file
24
plugins/vendor/google-fonts/source-sans-pro/css/fonts-local.css
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
src: url(../fonts/source-sans-pro-italic-400.ttf) format('truetype');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
src: url(../fonts/source-sans-pro-light-300.ttf) format('truetype');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: url(../fonts/source-sans-pro-regular-400.ttf) format('truetype');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: url(../fonts/source-sans-pro-bold-700.ttf) format('truetype');
|
||||
}
|
||||
24
plugins/vendor/google-fonts/source-sans-pro/css/fonts.css
vendored
Normal file
24
plugins/vendor/google-fonts/source-sans-pro/css/fonts.css
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
src: url(https://fonts.gstatic.com/s/sourcesanspro/v23/6xK1dSBYKcSV-LCoeQqfX1RYOo3qPZ7nsDc.ttf) format('truetype');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
src: url(https://fonts.gstatic.com/s/sourcesanspro/v23/6xKydSBYKcSV-LCoeQqfX1RYOo3ik4zwlxdr.ttf) format('truetype');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: url(https://fonts.gstatic.com/s/sourcesanspro/v23/6xK3dSBYKcSV-LCoeQqfX1RYOo3qOK7g.ttf) format('truetype');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: url(https://fonts.gstatic.com/s/sourcesanspro/v23/6xKydSBYKcSV-LCoeQqfX1RYOo3ig4vwlxdr.ttf) format('truetype');
|
||||
}
|
||||
BIN
plugins/vendor/google-fonts/source-sans-pro/fonts/source-sans-pro-bold-700.ttf
vendored
Normal file
BIN
plugins/vendor/google-fonts/source-sans-pro/fonts/source-sans-pro-bold-700.ttf
vendored
Normal file
Binary file not shown.
BIN
plugins/vendor/google-fonts/source-sans-pro/fonts/source-sans-pro-italic-400.ttf
vendored
Normal file
BIN
plugins/vendor/google-fonts/source-sans-pro/fonts/source-sans-pro-italic-400.ttf
vendored
Normal file
Binary file not shown.
BIN
plugins/vendor/google-fonts/source-sans-pro/fonts/source-sans-pro-light-300.ttf
vendored
Normal file
BIN
plugins/vendor/google-fonts/source-sans-pro/fonts/source-sans-pro-light-300.ttf
vendored
Normal file
Binary file not shown.
BIN
plugins/vendor/google-fonts/source-sans-pro/fonts/source-sans-pro-regular-400.ttf
vendored
Normal file
BIN
plugins/vendor/google-fonts/source-sans-pro/fonts/source-sans-pro-regular-400.ttf
vendored
Normal file
Binary file not shown.
11
plugins/vendor/ionicons/css/ionicons.min.css
vendored
Normal file
11
plugins/vendor/ionicons/css/ionicons.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
plugins/vendor/ionicons/fonts/ionicons.eot
vendored
Normal file
BIN
plugins/vendor/ionicons/fonts/ionicons.eot
vendored
Normal file
Binary file not shown.
2230
plugins/vendor/ionicons/fonts/ionicons.svg
vendored
Normal file
2230
plugins/vendor/ionicons/fonts/ionicons.svg
vendored
Normal file
File diff suppressed because it is too large
Load Diff
|
After Width: | Height: | Size: 326 KiB |
BIN
plugins/vendor/ionicons/fonts/ionicons.ttf
vendored
Normal file
BIN
plugins/vendor/ionicons/fonts/ionicons.ttf
vendored
Normal file
Binary file not shown.
BIN
plugins/vendor/ionicons/fonts/ionicons.woff
vendored
Normal file
BIN
plugins/vendor/ionicons/fonts/ionicons.woff
vendored
Normal file
Binary file not shown.
9
plugins/vendor/jscanify/jscanify.min.js
vendored
Normal file
9
plugins/vendor/jscanify/jscanify.min.js
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
/**
|
||||
* Minified by jsDelivr using Terser v5.39.0.
|
||||
* Original file: /gh/ColonelParrot/jscanify@master/src/jscanify.js
|
||||
*
|
||||
* Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files
|
||||
*/
|
||||
/*! jscanify v1.4.0 | (c) ColonelParrot and other contributors | MIT License */
|
||||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.jscanify=t()}(this,(function(){"use strict";return class{constructor(){}findPaperContour(e){const t=new cv.Mat;cv.Canny(e,t,50,200);const o=new cv.Mat;cv.GaussianBlur(t,o,new cv.Size(3,3),0,0,cv.BORDER_DEFAULT);const n=new cv.Mat;cv.threshold(o,n,0,255,cv.THRESH_OTSU);let r=new cv.MatVector,c=new cv.Mat;cv.findContours(n,r,c,cv.RETR_CCOMP,cv.CHAIN_APPROX_SIMPLE);let i=0,a=-1;for(let e=0;e<r.size();++e){let t=cv.contourArea(r.get(e));t>i&&(i=t,a=e)}const s=a>=0?r.get(a):null;return t.delete(),o.delete(),n.delete(),r.delete(),c.delete(),s}highlightPaper(e,t){(t=t||{}).color=t.color||"orange",t.thickness=t.thickness||10;const o=document.createElement("canvas"),n=o.getContext("2d"),r=cv.imread(e),c=this.findPaperContour(r);if(cv.imshow(o,r),c){const{topLeftCorner:e,topRightCorner:o,bottomLeftCorner:i,bottomRightCorner:a}=this.getCornerPoints(c,r);e&&o&&i&&a&&(n.strokeStyle=t.color,n.lineWidth=t.thickness,n.beginPath(),n.moveTo(...Object.values(e)),n.lineTo(...Object.values(o)),n.lineTo(...Object.values(a)),n.lineTo(...Object.values(i)),n.lineTo(...Object.values(e)),n.stroke())}return r.delete(),o}extractPaper(e,t,o,n){const r=document.createElement("canvas"),c=cv.imread(e),i=n?null:this.findPaperContour(c);if(null==i&&void 0===n)return null;const{topLeftCorner:a,topRightCorner:s,bottomLeftCorner:l,bottomRightCorner:v}=n||this.getCornerPoints(i,c);let u=new cv.Mat,d=new cv.Size(t,o),C=cv.matFromArray(4,1,cv.CV_32FC2,[a.x,a.y,s.x,s.y,l.x,l.y,v.x,v.y]),f=cv.matFromArray(4,1,cv.CV_32FC2,[0,0,t,0,0,o,t,o]),h=cv.getPerspectiveTransform(C,f);return cv.warpPerspective(c,u,h,d,cv.INTER_LINEAR,cv.BORDER_CONSTANT,new cv.Scalar),cv.imshow(r,u),c.delete(),u.delete(),r}getCornerPoints(e){const t=cv.minAreaRect(e).center;let o,n,r,c,i=0,a=0,s=0,l=0;for(let d=0;d<e.data32S.length;d+=2){const C={x:e.data32S[d],y:e.data32S[d+1]},f=(v=C,u=t,Math.hypot(v.x-u.x,v.y-u.y));C.x<t.x&&C.y<t.y?f>i&&(o=C,i=f):C.x>t.x&&C.y<t.y?f>a&&(n=C,a=f):C.x<t.x&&C.y>t.y?f>s&&(r=C,s=f):C.x>t.x&&C.y>t.y&&f>l&&(c=C,l=f)}var v,u;return{topLeftCorner:o,topRightCorner:n,bottomLeftCorner:r,bottomRightCorner:c}}}}));
|
||||
//# sourceMappingURL=/sm/f4b0fbf42a9b611deea75f2299eea9ad053e3664950195e6d617ef82058d69b3.map
|
||||
48
plugins/vendor/opencv/opencv.js
vendored
Normal file
48
plugins/vendor/opencv/opencv.js
vendored
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user