thay đổi quyền chia sẻ của user và quyền xem của các scene

This commit is contained in:
2026-06-09 18:18:34 +07:00
parent 18e1c3d76d
commit d243c67718
11 changed files with 204 additions and 22 deletions
+18
View File
@@ -8,6 +8,8 @@
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" crossorigin="" />
<!-- Pannellum (3D Viewer) CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/pannellum@2.5.6/build/pannellum.css"/>
<!-- Chart.js CSS (tùy chọn, có thể không cần nếu chỉ dùng JS) -->
<!-- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/chart.js@3.7.0/dist/chart.min.css"> -->
<!-- Leaflet MarkerCluster CSS -->
<link rel="stylesheet" href="https://unpkg.com/leaflet.markercluster@1.4.1/dist/MarkerCluster.css" />
<link rel="stylesheet" href="https://unpkg.com/leaflet.markercluster@1.4.1/dist/MarkerCluster.Default.css" />
@@ -192,6 +194,20 @@
</div>
</div>
<!-- View Stats Modal -->
<div id="view-stats-modal" class="modal-overlay">
<div class="modal-content logout-modal-dark" style="max-width: 700px;">
<h2 style="color: #fff; margin-bottom: 15px;" id="view-stats-modal-title">Thống kê lượt xem</h2>
<div style="width: 100%; height: 300px;">
<canvas id="view-stats-chart"></canvas>
</div>
<p style="color: #ccc; font-size: 12px; margin-top: 15px;">
Biểu đồ hiển thị số lượt xem theo ngày trong 30 ngày gần nhất.
</p>
<button onclick="closeViewStatsModal()" class="edit-btn-large" style="background: #444; width: 100%; margin-top: 20px; font-size: 14px;">Đóng</button>
</div>
</div>
<!-- Modal for Creating Scene -->
<div id="create-scene-modal" class="modal">
<div class="modal-content">
@@ -571,6 +587,8 @@
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js" integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin=""></script>
<!-- Pannellum JS -->
<script src="https://cdn.jsdelivr.net/npm/pannellum@2.5.6/build/pannellum.js"></script>
<!-- Chart.js -->
<script src="https://cdn.jsdelivr.net/npm/chart.js@3.7.0/dist/chart.min.js"></script>
<!-- Leaflet MarkerCluster JS -->
<script src="https://unpkg.com/leaflet.markercluster@1.4.1/dist/leaflet.markercluster.js"></script>
+86
View File
@@ -1528,12 +1528,14 @@ async function loadMyScenes() {
<span>🔒 ${scene.privacy}</span>
<span>👤 ${scene.createdBy?.username || 'Bạn'}</span>
<span>📅 ${formatSystemDate(scene.createdAt)}</span>
<span>👁️ ${scene.views || 0} lượt xem</span>
</div>
${statusBadge}
</div>
<div class="media-actions" style="border: none; padding: 0;">
<button class="edit-btn-small" id="edit-scene-${scene._id}" ${scene.status === 'processing' ? 'disabled style="opacity:0.5; cursor:not-allowed;"' : ''}>Sửa</button>
<button class="delete-btn-small" id="delete-scene-${scene._id}">Xóa</button>
<button class="edit-btn-small" id="view-stats-${scene._id}" style="background: #6f42c1;">Thống kê</button>
</div>
</div>
`;
@@ -1555,6 +1557,11 @@ async function loadMyScenes() {
closeDashboard();
deleteScene(scene._id);
};
// Xử lý nút Thống kê
document.getElementById(`view-stats-${scene._id}`).onclick = () => {
showViewStatsModal(scene._id, scene.name || scene.title);
};
});
} catch (e) {
listContainer.innerHTML = `<p style="color:#ff4d4d">Lỗi: ${e.message}</p>`;
@@ -2280,6 +2287,85 @@ async function updateSystemSettings(e) {
}
}
let viewStatsChartInstance = null; // Biến để lưu instance của Chart.js
/**
* Mở modal hiển thị biểu đồ thống kê lượt xem
*/
async function showViewStatsModal(sceneId, sceneTitle) {
const token = localStorage.getItem('jwt');
const modal = document.getElementById('view-stats-modal');
const titleElem = document.getElementById('view-stats-modal-title');
const chartCanvas = document.getElementById('view-stats-chart');
if (titleElem) titleElem.innerText = `Thống kê lượt xem: ${sceneTitle}`;
modal.style.display = 'flex';
try {
const res = await fetch(`${API_BASE_URL}/me/scenes/${sceneId}/view-stats`, {
headers: { 'Authorization': `Bearer ${token}` }
});
const viewHistory = await res.json();
if (!res.ok) throw new Error(viewHistory.message);
// Chuẩn bị dữ liệu cho biểu đồ
const labels = [];
const data = [];
const today = new Date();
today.setHours(0, 0, 0, 0);
// Lấy dữ liệu 30 ngày gần nhất
for (let i = 29; i >= 0; i--) {
const d = new Date(today);
d.setDate(today.getDate() - i);
labels.push(d.toLocaleDateString(systemSettings.language === 'vi' ? 'vi-VN' : 'en-US', { day: '2-digit', month: '2-digit' }));
const entry = viewHistory.find(vh => new Date(vh.date).setHours(0,0,0,0) === d.getTime());
data.push(entry ? entry.count : 0);
}
// Nếu có instance cũ, hủy nó đi trước khi tạo mới
if (viewStatsChartInstance) {
viewStatsChartInstance.destroy();
}
viewStatsChartInstance = new Chart(chartCanvas, {
type: 'line',
data: {
labels: labels,
datasets: [{
label: 'Lượt xem',
data: data,
borderColor: '#007bff',
backgroundColor: 'rgba(0, 123, 255, 0.2)',
fill: true,
tension: 0.3
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: { y: { beginAtZero: true } }
}
});
} catch (e) {
showNotification("Không thể tải thống kê lượt xem: " + e.message, 'error');
closeViewStatsModal();
}
}
/**
* Đóng modal thống kê lượt xem
*/
window.closeViewStatsModal = function() {
document.getElementById('view-stats-modal').style.display = 'none';
if (viewStatsChartInstance) {
viewStatsChartInstance.destroy(); // Hủy biểu đồ để giải phóng bộ nhớ
viewStatsChartInstance = null;
}
};
/**
* Opens a specific tab within the dashboard.
* @param {string} tabName - The ID of the tab pane to open (e.g., 'profile', 'my-scenes').