add listing of saved reports
parent
7fb6a974fd
commit
a142063c64
|
@ -9117,6 +9117,7 @@ module.exports = function(s,config,lang){
|
|||
"Created Reports": {
|
||||
"name": lang["Created Reports"],
|
||||
"color": "green",
|
||||
"section-pre-class": "col-md-3",
|
||||
"info": [
|
||||
{
|
||||
"field": lang.Monitor,
|
||||
|
@ -9139,12 +9140,16 @@ module.exports = function(s,config,lang){
|
|||
"attribute": `href="javascript:openTab('reportManagerForm')"`,
|
||||
"btnContent": `<i class="fa fa-refresh"></i> ${lang['Submission Form']}`,
|
||||
},
|
||||
{
|
||||
"fieldType": "div",
|
||||
"id": "report-manager-list",
|
||||
}
|
||||
]
|
||||
},
|
||||
"Report Display": {
|
||||
"color": "green",
|
||||
"noHeader": true,
|
||||
"noDefaultSectionClasses": true,
|
||||
"section-pre-class": "col-md-9",
|
||||
"info": [
|
||||
{
|
||||
"fieldType": "div",
|
||||
|
|
|
@ -38,7 +38,10 @@ module.exports = function(s,config,lang,app,io){
|
|||
table: "Reports",
|
||||
where: whereQuery,
|
||||
})
|
||||
return selectResponse
|
||||
selectResponse.rows.forEach((row) => {
|
||||
row.details = JSON.parse(row.details)
|
||||
})
|
||||
return selectResponse.rows
|
||||
}
|
||||
async function getNewReportId(groupKey, monitorId){
|
||||
const newReportId = s.gid(25)
|
||||
|
@ -109,6 +112,7 @@ module.exports = function(s,config,lang,app,io){
|
|||
s.debugLog(`Copied Files!`)
|
||||
const outputZipPath = `${tempDirectory}.zip`
|
||||
const moveZipToPath = `${moveZipToDirectory}.zip`
|
||||
s.debugLog(`Path to Zip`,tempDirectory)
|
||||
s.debugLog(`outputZipPath`,outputZipPath)
|
||||
s.debugLog(`Zipping...`,moveZipToPath)
|
||||
// save files to zip
|
||||
|
@ -244,7 +248,7 @@ module.exports = function(s,config,lang,app,io){
|
|||
var videoSnapLegend = {}
|
||||
videos.forEach((video) => {
|
||||
var videoPath = s.getVideoDirectory(video) + video.filename
|
||||
var frames = video.timelapseFrames || []
|
||||
var frames = video.frames || []
|
||||
videoPaths.push(videoPath)
|
||||
videoSnapLegend[`${videoPath}`] = []
|
||||
frames.forEach((frame) => {
|
||||
|
@ -265,27 +269,20 @@ module.exports = function(s,config,lang,app,io){
|
|||
*/
|
||||
app.get([
|
||||
config.webPaths.apiPrefix+':auth/reports/:ke',
|
||||
config.webPaths.apiPrefix+':auth/reports/:ke/:id',
|
||||
config.webPaths.apiPrefix+':auth/reports/:ke/:id/:reportId',
|
||||
config.webPaths.apiPrefix+':auth/reports/:ke/:reportId',
|
||||
], function (req,res){
|
||||
res.setHeader('Content-Type', 'application/json');
|
||||
s.auth(req.params, async function(user){
|
||||
const response = {ok: true}
|
||||
const monitorId = req.params.id
|
||||
const monitorId = req.query.id || '_USER'
|
||||
const groupKey = req.params.ke
|
||||
const reportId = req.params.reportId
|
||||
const canDoAction = hasApiPermission(user,groupKey,monitorId)
|
||||
if(canDoAction){
|
||||
try{
|
||||
const reports = await getReports(groupKey,monitorId,reportId)
|
||||
response.reports = reports
|
||||
}catch(err){
|
||||
response.ok = false
|
||||
response.err = err
|
||||
}
|
||||
}else{
|
||||
try{
|
||||
const reports = await getReports(groupKey,monitorId,reportId)
|
||||
response.reports = reports
|
||||
}catch(err){
|
||||
response.ok = false
|
||||
response.msg = lang['Not Authorized']
|
||||
response.err = err
|
||||
}
|
||||
s.closeJsonResponse(res,response)
|
||||
},res,req);
|
||||
|
|
|
@ -0,0 +1,172 @@
|
|||
$(document).ready(function(){
|
||||
var theTab = $('#tab-reportManagerForm')
|
||||
var theForm = theTab.find('form')
|
||||
var videoSelectContainer = $('#report-manager-video-select')
|
||||
var selectedContainer = $('#report-manager-video-selected')
|
||||
var monitorsList = theTab.find('.monitors_list')
|
||||
var dateSelector = theTab.find('.date_selector')
|
||||
var searchField = $('#report-manager-search-tag')
|
||||
function getFormDetails(form){
|
||||
var theObject = {}
|
||||
form.find('[detail]').each(function(n,v){
|
||||
var el = $(this)
|
||||
var key = el.attr('detail')
|
||||
var value = el.val()
|
||||
theObject[key] = value
|
||||
})
|
||||
return theObject
|
||||
}
|
||||
function saveReport(){
|
||||
var form = theForm.serializeObject()
|
||||
var videos = getAllSelectedVideos()
|
||||
var details = getFormDetails(theForm)
|
||||
var postData = Object.assign({
|
||||
videos,
|
||||
details,
|
||||
},form);
|
||||
$.post(getApiPrefix('reports'),postData,function(data){
|
||||
console.log('reports response',data)
|
||||
})
|
||||
}
|
||||
function emailReport(){}
|
||||
function uploadReport(){}
|
||||
function createVideoCard(video,classOverride){
|
||||
var monitorId = video.mid
|
||||
var startTime = video.time
|
||||
var endTime = video.end
|
||||
var {
|
||||
day,
|
||||
month,
|
||||
year,
|
||||
} = getDayPartsFromTime(startTime)
|
||||
var firstFrame = video.timelapseFrames && video.timelapseFrames[0] ? video.timelapseFrames[0] : {href:''}
|
||||
console.log(firstFrame,video.timelapseFrames)
|
||||
var eventMatrixHtml = ``
|
||||
eventMatrixHtml += `<div class="video-day-slice" data-mid="${video.mid}" data-time="${video.time}" style="width:100%;position:relative">`
|
||||
if(video.events && video.events.length > 0){
|
||||
$.each(video.events,function(n,theEvent){
|
||||
var leftPercent = getPercentOfTimePositionFromVideo(video,theEvent)
|
||||
eventMatrixHtml += `<div class="video-time-needle video-time-needle-event" style="margin-left:${leftPercent}%"></div>`
|
||||
})
|
||||
}
|
||||
eventMatrixHtml += `</div>`
|
||||
eventMatrixHtml += `<div class="video-day-slice-spacer"></div>`
|
||||
|
||||
var html = `
|
||||
<div class="video-row video-time-card-container ${classOverride ? classOverride : `col-md-12 col-lg-6 mb-3`} search-row">
|
||||
<div data-ke="${video.ke}" data-mid="${video.mid}" data-time="${video.time}" class="video-time-card shadow-sm px-0 ${definitions.Theme.isDark ? 'bg-dark' : 'bg-light'}">
|
||||
<div class="video-time-header">
|
||||
<div class="d-flex flex-row vertical-center ${definitions.Theme.isDark ? 'text-white' : ''}">
|
||||
<div class="flex-grow-1 p-3">
|
||||
<b>${loadedMonitors[monitorId] ? loadedMonitors[monitorId].name : monitorId}</b>
|
||||
<div class="${definitions.Theme.isDark ? 'text-white' : ''}">
|
||||
<span class="video-time-label">${formattedTime(startTime)} to ${formattedTime(endTime)}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-right p-3" style="background:rgba(0,0,0,0.5)">
|
||||
<div class="text-center" style="font-size:20pt;font-weight:bold">${day}</div>
|
||||
<div>${month}, ${year}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="px-3 pb-3">
|
||||
<a class="btn btn-sm btn-success play-video" title="${lang.Play}"><i class=" fa fa-play-circle"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-center video-card-playback-view" style="position:relative">
|
||||
<img class="video-time-img" src="${firstFrame.href}">
|
||||
</div>
|
||||
<div class="video-time-strip card-footer p-0">
|
||||
<div class="flex-row d-flex" style="height:30px">${eventMatrixHtml}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>`
|
||||
return html
|
||||
}
|
||||
function loadVideoCards(videos){
|
||||
var dateRange = getSelectedTime(dateSelector)
|
||||
var startDate = dateRange.startDate
|
||||
var endDate = dateRange.endDate
|
||||
var monitorId = monitorsList.val()
|
||||
var searchQuery = searchField.val()
|
||||
getVideos({
|
||||
monitorId,
|
||||
startDate,
|
||||
endDate,
|
||||
searchQuery,
|
||||
archived: false,
|
||||
},function(data){
|
||||
var html = ''
|
||||
var videos = data.videos
|
||||
loadedReportVideos = {}
|
||||
$.each(videos,function(n,video){
|
||||
loadedReportVideos[`${video.ke}${video.mid}${video.time}`] = video;
|
||||
html += createVideoCard(video)
|
||||
})
|
||||
videoSelectContainer.html(html)
|
||||
})
|
||||
}
|
||||
function getAllSelectedVideos(){
|
||||
var selected = []
|
||||
videoSelectContainer.find('.video-time-card.selected').each(function(){
|
||||
var el = $(this)
|
||||
var ke = el.attr('data-ke')
|
||||
var mid = el.attr('data-mid')
|
||||
var time = el.attr('data-time')
|
||||
var video = loadedReportVideos[`${ke}${mid}${time}`]
|
||||
selected.push({
|
||||
ke,
|
||||
mid,
|
||||
time: video.time,
|
||||
filename: video.filename,
|
||||
details: video.details,
|
||||
frames: video.timelapseFrames.map(item => {
|
||||
return {
|
||||
ke: item.ke,
|
||||
mid: item.mid,
|
||||
time: item.time,
|
||||
filename: item.filename,
|
||||
}
|
||||
}),
|
||||
events: video.events,
|
||||
})
|
||||
})
|
||||
return selected
|
||||
}
|
||||
function loadVideoIntoVideoCard(playButton){
|
||||
var timeCard = playButton.parents('.video-time-card')
|
||||
var playBackContainer = timeCard.find('.video-card-playback-view')
|
||||
var groupKey = timeCard.attr('data-ke')
|
||||
var monitorId = timeCard.attr('data-mid')
|
||||
var time = timeCard.attr('data-time')
|
||||
var video = loadedReportVideos[`${groupKey}${monitorId}${time}`]
|
||||
playBackContainer.html(`<video controls autoplay src="${video.href}"></video>`)
|
||||
}
|
||||
addOnTabOpen('reportManagerForm', function () {
|
||||
loadVideoCards()
|
||||
})
|
||||
addOnTabAway('reportManagerForm', function () {
|
||||
|
||||
})
|
||||
loadDateRangePicker(dateSelector,{
|
||||
onChange: function(start, end, label) {
|
||||
loadVideoCards()
|
||||
}
|
||||
})
|
||||
loadDateRangePicker(theForm.find('[name="incidentTime"]'),{
|
||||
singleDatePicker: true,
|
||||
})
|
||||
drawMonitorListToSelector(monitorsList.find('optgroup'))
|
||||
videoSelectContainer.on('click','.video-time-card',function(){
|
||||
var el = $(this)
|
||||
el.toggleClass('selected')
|
||||
})
|
||||
videoSelectContainer.on('click','.play-video',function(){
|
||||
var el = $(this)
|
||||
loadVideoIntoVideoCard(el)
|
||||
})
|
||||
theForm.submit(function(e){
|
||||
e.preventDefault()
|
||||
saveReport()
|
||||
return false;
|
||||
})
|
||||
})
|
|
@ -1,172 +1,44 @@
|
|||
$(document).ready(function(){
|
||||
var theTab = $('#tab-reportManagerForm')
|
||||
var theForm = theTab.find('form')
|
||||
var videoSelectContainer = $('#report-manager-video-select')
|
||||
var selectedContainer = $('#report-manager-video-selected')
|
||||
var monitorsList = theTab.find('.monitors_list')
|
||||
var dateSelector = theTab.find('.date_selector')
|
||||
var searchField = $('#report-manager-search-tag')
|
||||
function getFormDetails(form){
|
||||
var theObject = {}
|
||||
form.find('[detail]').each(function(n,v){
|
||||
var el = $(this)
|
||||
var key = el.attr('detail')
|
||||
var value = el.val()
|
||||
theObject[key] = value
|
||||
})
|
||||
return theObject
|
||||
}
|
||||
function saveReport(){
|
||||
var form = theForm.serializeObject()
|
||||
var videos = getAllSelectedVideos()
|
||||
var details = getFormDetails(theForm)
|
||||
var postData = Object.assign({
|
||||
videos,
|
||||
details,
|
||||
},form);
|
||||
$.post(getApiPrefix('reports'),postData,function(data){
|
||||
console.log('reports response',data)
|
||||
})
|
||||
}
|
||||
function emailReport(){}
|
||||
function uploadReport(){}
|
||||
function createVideoCard(video,classOverride){
|
||||
var monitorId = video.mid
|
||||
var startTime = video.time
|
||||
var endTime = video.end
|
||||
var {
|
||||
day,
|
||||
month,
|
||||
year,
|
||||
} = getDayPartsFromTime(startTime)
|
||||
var firstFrame = video.timelapseFrames && video.timelapseFrames[0] ? video.timelapseFrames[0] : {href:''}
|
||||
console.log(firstFrame,video.timelapseFrames)
|
||||
var eventMatrixHtml = ``
|
||||
eventMatrixHtml += `<div class="video-day-slice" data-mid="${video.mid}" data-time="${video.time}" style="width:100%;position:relative">`
|
||||
if(video.events && video.events.length > 0){
|
||||
$.each(video.events,function(n,theEvent){
|
||||
var leftPercent = getPercentOfTimePositionFromVideo(video,theEvent)
|
||||
eventMatrixHtml += `<div class="video-time-needle video-time-needle-event" style="margin-left:${leftPercent}%"></div>`
|
||||
var theTab = $('#tab-reportManager')
|
||||
var theList = $('#report-manager-list')
|
||||
function getReports(reportId){
|
||||
return new Promise((resolve) => {
|
||||
$.getJSON(`${getApiPrefix(`reports`)}${reportId ? `/${reportId}` : ''}`,function(response){
|
||||
resolve(response.reports)
|
||||
})
|
||||
}
|
||||
eventMatrixHtml += `</div>`
|
||||
eventMatrixHtml += `<div class="video-day-slice-spacer"></div>`
|
||||
|
||||
var html = `
|
||||
<div class="video-row video-time-card-container ${classOverride ? classOverride : `col-md-12 col-lg-6 mb-3`} search-row">
|
||||
<div data-ke="${video.ke}" data-mid="${video.mid}" data-time="${video.time}" class="video-time-card shadow-sm px-0 ${definitions.Theme.isDark ? 'bg-dark' : 'bg-light'}">
|
||||
<div class="video-time-header">
|
||||
<div class="d-flex flex-row vertical-center ${definitions.Theme.isDark ? 'text-white' : ''}">
|
||||
<div class="flex-grow-1 p-3">
|
||||
<b>${loadedMonitors[monitorId] ? loadedMonitors[monitorId].name : monitorId}</b>
|
||||
<div class="${definitions.Theme.isDark ? 'text-white' : ''}">
|
||||
<span class="video-time-label">${formattedTime(startTime)} to ${formattedTime(endTime)}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-right p-3" style="background:rgba(0,0,0,0.5)">
|
||||
<div class="text-center" style="font-size:20pt;font-weight:bold">${day}</div>
|
||||
<div>${month}, ${year}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="px-3 pb-3">
|
||||
<a class="btn btn-sm btn-success play-video" title="${lang.Play}"><i class=" fa fa-play-circle"></i></a>
|
||||
})
|
||||
}
|
||||
async function drawReports(){
|
||||
var html = ''
|
||||
var reports = await getReports()
|
||||
console.log(reports)
|
||||
$.each(reports,function(n,report){
|
||||
console.log(report)
|
||||
html += `<div class="card bg-darker mt-2">
|
||||
<div class="card-header">
|
||||
${report.name}
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div>
|
||||
${report.name}
|
||||
</div>
|
||||
<small class="d-block">
|
||||
<b>${lang['Submitted By']} :</b> ${report.details.submittedBy}
|
||||
</small>
|
||||
<small class="d-block">
|
||||
<b>${lang['Location of Incident']} :</b> ${report.details.locationOfIncident}
|
||||
</small>
|
||||
</div>
|
||||
<div class="text-center video-card-playback-view" style="position:relative">
|
||||
<img class="video-time-img" src="${firstFrame.href}">
|
||||
</div>
|
||||
<div class="video-time-strip card-footer p-0">
|
||||
<div class="flex-row d-flex" style="height:30px">${eventMatrixHtml}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>`
|
||||
return html
|
||||
}
|
||||
function loadVideoCards(videos){
|
||||
var dateRange = getSelectedTime(dateSelector)
|
||||
var startDate = dateRange.startDate
|
||||
var endDate = dateRange.endDate
|
||||
var monitorId = monitorsList.val()
|
||||
var searchQuery = searchField.val()
|
||||
getVideos({
|
||||
monitorId,
|
||||
startDate,
|
||||
endDate,
|
||||
searchQuery,
|
||||
archived: false,
|
||||
},function(data){
|
||||
var html = ''
|
||||
var videos = data.videos
|
||||
loadedReportVideos = {}
|
||||
$.each(videos,function(n,video){
|
||||
loadedReportVideos[`${video.ke}${video.mid}${video.time}`] = video;
|
||||
html += createVideoCard(video)
|
||||
})
|
||||
videoSelectContainer.html(html)
|
||||
</div>`
|
||||
})
|
||||
theList.html(html)
|
||||
}
|
||||
function getAllSelectedVideos(){
|
||||
var selected = []
|
||||
videoSelectContainer.find('.video-time-card.selected').each(function(){
|
||||
var el = $(this)
|
||||
var ke = el.attr('data-ke')
|
||||
var mid = el.attr('data-mid')
|
||||
var time = el.attr('data-time')
|
||||
var video = loadedReportVideos[`${ke}${mid}${time}`]
|
||||
selected.push({
|
||||
ke,
|
||||
mid,
|
||||
time: video.time,
|
||||
filename: video.filename,
|
||||
details: video.details,
|
||||
frames: video.timelapseFrames.map(item => {
|
||||
return {
|
||||
ke: item.ke,
|
||||
mid: item.mid,
|
||||
time: item.time,
|
||||
filename: item.filename,
|
||||
}
|
||||
}),
|
||||
events: video.events,
|
||||
})
|
||||
})
|
||||
return selected
|
||||
}
|
||||
function loadVideoIntoVideoCard(playButton){
|
||||
var timeCard = playButton.parents('.video-time-card')
|
||||
var playBackContainer = timeCard.find('.video-card-playback-view')
|
||||
var groupKey = timeCard.attr('data-ke')
|
||||
var monitorId = timeCard.attr('data-mid')
|
||||
var time = timeCard.attr('data-time')
|
||||
var video = loadedReportVideos[`${groupKey}${monitorId}${time}`]
|
||||
playBackContainer.html(`<video controls autoplay src="${video.href}"></video>`)
|
||||
}
|
||||
addOnTabOpen('reportManagerForm', function () {
|
||||
loadVideoCards()
|
||||
addOnTabOpen('reportManager', function () {
|
||||
drawReports()
|
||||
})
|
||||
addOnTabAway('reportManagerForm', function () {
|
||||
|
||||
addOnTabReopen('reportManager', function () {
|
||||
drawReports()
|
||||
})
|
||||
loadDateRangePicker(dateSelector,{
|
||||
onChange: function(start, end, label) {
|
||||
loadVideoCards()
|
||||
}
|
||||
})
|
||||
loadDateRangePicker(theForm.find('[name="incidentTime"]'),{
|
||||
singleDatePicker: true,
|
||||
})
|
||||
drawMonitorListToSelector(monitorsList.find('optgroup'))
|
||||
videoSelectContainer.on('click','.video-time-card',function(){
|
||||
var el = $(this)
|
||||
el.toggleClass('selected')
|
||||
})
|
||||
videoSelectContainer.on('click','.play-video',function(){
|
||||
var el = $(this)
|
||||
loadVideoIntoVideoCard(el)
|
||||
})
|
||||
theForm.submit(function(e){
|
||||
e.preventDefault()
|
||||
saveReport()
|
||||
return false;
|
||||
addOnTabAway('reportManager', function () {
|
||||
})
|
||||
})
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
%>
|
||||
<!-- Report Manager (Main) -->
|
||||
<main class="page-tab pt-3" id="tab-reportManager">
|
||||
<form class="dark">
|
||||
<div class="dark row">
|
||||
<%
|
||||
var pageName = 'Report Manager';
|
||||
Object.keys(define[pageName].blocks).forEach(function(blockKey){
|
||||
|
@ -15,7 +15,7 @@
|
|||
drawBlock(pageLayout)
|
||||
})
|
||||
%>
|
||||
</form>
|
||||
</div>
|
||||
<link rel="stylesheet" href="<%-window.libURL%>assets/css/bs5.reportManager.css" />
|
||||
<script src="<%-window.libURL%>assets/js/bs5.reportManager.js"></script>
|
||||
</main>
|
||||
|
@ -33,4 +33,5 @@
|
|||
include stickySubmitBar.ejs
|
||||
%>
|
||||
</form>
|
||||
<script src="<%-window.libURL%>assets/js/bs5.reportManager.form.js"></script>
|
||||
</main>
|
||||
|
|
Loading…
Reference in New Issue