From 08a80f2b7e3d2785be0ef9eced79ecb80cfa2ec1 Mon Sep 17 00:00:00 2001 From: Moe Date: Sat, 7 Jul 2018 10:33:23 -0700 Subject: [PATCH 01/16] sql time query cleanup --- camera.js | 133 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 68 insertions(+), 65 deletions(-) diff --git a/camera.js b/camera.js index 2f5be48c..c3e670db 100644 --- a/camera.js +++ b/camera.js @@ -116,7 +116,6 @@ if(config.databaseType===undefined){config.databaseType='mysql'} if(config.pluginKeys===undefined)config.pluginKeys={}; if(config.databaseLogs===undefined){config.databaseLogs=false} if(config.useUTC===undefined){config.useUTC=false} -if(config.strictDatabase===undefined){config.strictDatabase=false} if(config.pipeAddition===undefined){config.pipeAddition=7}else{config.pipeAddition=parseInt(config.pipeAddition)} //Web Paths if(config.webPaths===undefined){config.webPaths={}} @@ -241,21 +240,20 @@ s.mergeQueryValues = function(query,values){ if(!values){values=[]} var valuesNotFunction = true; if(typeof values === 'function'){ - var onMoveOn = values; var values = []; valuesNotFunction = false; } - if(!onMoveOn){onMoveOn=function(){}} if(values&&valuesNotFunction){ var splitQuery = query.split('?') var newQuery = '' splitQuery.forEach(function(v,n){ newQuery += v - if(values[n]){ - if(isNaN(values[n])){ - newQuery += "'"+values[n]+"'" + var value = values[n] + if(value){ + if(isNaN(value) || value instanceof Date){ + newQuery += "'"+value+"'" }else{ - newQuery += values[n] + newQuery += value } } }) @@ -264,7 +262,11 @@ s.mergeQueryValues = function(query,values){ } return newQuery } -s.sqlQuery = function(query,values,onMoveOn,hideLog){ +s.stringToSqlTime = function(value){ + newValue = new Date(value.replace('T',' ')) + return newValue +} +s.sqlQuery = function(query,values,onMoveOn){ if(!values){values=[]} if(typeof values === 'function'){ var onMoveOn = values; @@ -272,11 +274,13 @@ s.sqlQuery = function(query,values,onMoveOn,hideLog){ } if(!onMoveOn){onMoveOn=function(){}} var mergedQuery = s.mergeQueryValues(query,values) - return s.databaseEngine.raw(query,values) + s.debugLog('s.sqlQuery QUERY',mergedQuery) + return s.databaseEngine + .raw(query,values) .asCallback(function(err,r){ - if(err&&config.databaseLogs){ - s.systemLog('s.sqlQuery QUERY',query) - s.systemLog('s.sqlQuery ERROR',err) + if(err){ + console.log('s.sqlQuery QUERY ERRORED',query) + console.log('s.sqlQuery ERROR',err) } if(onMoveOn && typeof onMoveOn === 'function'){ switch(databaseOptions.client){ @@ -291,6 +295,7 @@ s.sqlQuery = function(query,values,onMoveOn,hideLog){ } }) } + //kill any ffmpeg running s.ffmpegKill=function(){ var cmd='' @@ -549,7 +554,7 @@ s.log=function(e,x){ // s.systemLog('s.log : ',{f:'log',ke:e.ke,mid:e.mid,log:x,time:s.timeObject()},'GRP_'+e.ke) } //system log -s.systemLog=function(q,w,e){ +s.systemLog = function(q,w,e){ if(!w){w=''} if(!e){e=''} if(config.systemLog===true){ @@ -560,6 +565,17 @@ s.systemLog=function(q,w,e){ return console.log(s.timeObject().format(),q,w,e) } } +//system log +s.debugLog = function(q,w,e){ + if(!w){w = ''} + if(!e){e = ''} + if(config.debugLog === true){ + console.log(s.timeObject().format(),q,w,e) + if(config.debugLogVerbose === true){ + console.log(new Error()) + } + } +} //SSL options if(config.ssl&&config.ssl.key&&config.ssl.cert){ config.ssl.key=fs.readFileSync(s.checkRelativePath(config.ssl.key),'utf8') @@ -918,15 +934,12 @@ s.video=function(x,e,k){ time = e.time } time = new Date(time) - if(config.databaseType !== 'sqlite'){ - time = moment(time).format('YYYY-MM-DD HH:mm:ss') - } e.save=[e.id,e.ke,time]; - s.sqlQuery('SELECT * FROM Videos WHERE `mid`=? AND `ke`=? AND `time`=? LIMIT 1',e.save,function(err,r){ + s.sqlQuery('SELECT * FROM Videos WHERE `mid`=? AND `ke`=? AND `time`=?',e.save,function(err,r){ if(r&&r[0]){ r=r[0] var dir=s.video('getDir',r) - s.sqlQuery('DELETE FROM Videos WHERE `mid`=? AND `ke`=? AND `time`=? LIMIT 1',e.save,function(){ + s.sqlQuery('DELETE FROM Videos WHERE `mid`=? AND `ke`=? AND `time`=?',e.save,function(){ fs.stat(dir+filename,function(err,file){ if(err){ s.systemLog('File Delete Error : '+e.ke+' : '+' : '+e.mid,err) @@ -1093,7 +1106,7 @@ s.video=function(x,e,k){ if(!evs)return console.log(err) evs.forEach(function(ev){ ev.dir=s.video('getDir',ev)+s.formattedTime(ev.time)+'.'+ev.ext; - k.del.push('(mid=? AND time=?)'); + k.del.push('(mid=? AND `time`=?)'); k.ar.push(ev.mid),k.ar.push(ev.time); s.file('delete',ev.dir); s.init('diskUsedSet',e,-(ev.size/1000000)) @@ -1238,10 +1251,6 @@ s.video=function(x,e,k){ k.details.dir = e.details.dir } if(config.useUTC === true)k.details.isUTC = config.useUTC; - if(config.strictDatabase === true){ - e.startTime = s.formattedTime(e.startTime) - e.endTime = s.formattedTime(e.endTime) - } var save = [ e.mid, e.ke, @@ -2442,9 +2451,7 @@ s.camera=function(x,e,cn,tx){ e.details.fatal_max = parseFloat(e.details.fatal_max) } var errorFatal = function(errorMessage){ - if(config.debugSystem === true){ - console.log(errorMessage,(new Error()).stack) - } + s.debugLog(errorMessage) clearTimeout(s.group[e.ke].mon[e.id].err_fatal_timeout); ++errorFatalCount; if(s.group[e.ke].mon[e.id].started===1){ @@ -2518,7 +2525,7 @@ s.camera=function(x,e,cn,tx){ cutoff *= 100 } s.group[e.ke].mon[e.id].checker=setTimeout(function(){ - if(s.group[e.ke].mon[e.id].started === 1){ + if(s.group[e.ke].mon[e.id].started === 1 && s.group[e.ke].mon_conf[e.id].mode === 'record'){ launchMonitorProcesses(); s.init('monitorStatus',{id:e.id,ke:e.ke,status:lang.Restarting}); s.log(e,{type:lang['Camera is not recording'],msg:{msg:lang['Restarting Process']}}); @@ -3901,15 +3908,15 @@ var tx; switch(d.fff){ case'videos&events': if(!d.eventLimit){ - d.eventLimit=500 + d.eventLimit = 500 }else{ d.eventLimit = parseInt(d.eventLimit); } if(!d.eventStartDate&&d.startDate){ - d.eventStartDate=d.startDate + d.eventStartDate = s.stringToSqlTime(d.startDate) } if(!d.eventEndDate&&d.endDate){ - d.eventEndDate=d.endDate + d.eventEndDate = s.stringToSqlTime(d.endDate) } var monitorQuery = '' var monitorValues = [] @@ -3932,15 +3939,13 @@ var tx; var eventQuery = 'SELECT * FROM Events WHERE ke=?'; var eventQueryValues = [cn.ke]; if(d.eventStartDate&&d.eventStartDate!==''){ - d.eventStartDate=d.eventStartDate.replace('T',' ') if(d.eventEndDate&&d.eventEndDate!==''){ - d.eventEndDate=d.eventEndDate.replace('T',' ') eventQuery+=' AND `time` >= ? AND `time` <= ?'; - eventQueryValues.push(decodeURIComponent(d.eventStartDate)) - eventQueryValues.push(decodeURIComponent(d.eventEndDate)) + eventQueryValues.push(d.eventStartDate) + eventQueryValues.push(d.eventEndDate) }else{ eventQuery+=' AND `time` >= ?'; - eventQueryValues.push(decodeURIComponent(d.eventStartDate)) + eventQueryValues.push(d.eventStartDate) } } if(monitorValues.length>0){ @@ -3969,10 +3974,10 @@ var tx; eventQuery.push() } if(!d.videoStartDate&&d.startDate){ - d.videoStartDate=d.startDate + d.videoStartDate = s.stringToSqlTime(d.startDate) } if(!d.videoEndDate&&d.endDate){ - d.videoEndDate=d.endDate + d.videoEndDate = s.stringToSqlTime(d.endDate) } var getVideos = function(callback){ var videoQuery='SELECT * FROM Videos WHERE ke=?'; @@ -3986,19 +3991,15 @@ var tx; } switch(true){ case(d.videoStartDate&&d.videoStartDate!==''&&d.videoEndDate&&d.videoEndDate!==''): - d.videoStartDate=d.videoStartDate.replace('T',' ') - d.videoEndDate=d.videoEndDate.replace('T',' ') videoQuery+=' AND `time` '+d.videoStartDateOperator+' ? AND `end` '+d.videoEndDateOperator+' ?'; videoQueryValues.push(d.videoStartDate) videoQueryValues.push(d.videoEndDate) break; case(d.videoStartDate&&d.videoStartDate!==''): - d.videoStartDate=d.videoStartDate.replace('T',' ') videoQuery+=' AND `time` '+d.videoStartDateOperator+' ?'; videoQueryValues.push(d.videoStartDate) break; case(d.videoEndDate&&d.videoEndDate!==''): - d.videoEndDate=d.videoEndDate.replace('T',' ') videoQuery+=' AND `end` '+d.videoEndDateOperator+' ?'; videoQueryValues.push(d.videoEndDate) break; @@ -4569,7 +4570,7 @@ var tx; } s.log({ke:cn.ke,mid:'$USER'},{type:lang['Websocket Disconnected'],msg:{mail:s.group[cn.ke].users[cn.auth].mail,id:cn.uid,ip:cn.ip}}) delete(s.group[cn.ke].users[cn.auth]); - delete(s.group[cn.ke].dashcamUsers[cn.auth]); + if(s.group[cn.ke].dashcamUsers && s.group[cn.ke].dashcamUsers[cn.auth])delete(s.group[cn.ke].dashcamUsers[cn.auth]); } } if(cn.pluginEngine){ @@ -5667,6 +5668,12 @@ app.get(['/:auth/videos/:ke','/:auth/videos/:ke/:id'], function (req,res){ } } if(req.query.start||req.query.end){ + if(req.query.start && req.query.start !== ''){ + req.query.start = s.stringToSqlTime(req.query.start) + } + if(req.query.end && req.query.end !== ''){ + req.query.end = s.stringToSqlTime(req.query.end) + } if(!req.query.startOperator||req.query.startOperator==''){ req.query.startOperator='>=' } @@ -5675,8 +5682,6 @@ app.get(['/:auth/videos/:ke','/:auth/videos/:ke/:id'], function (req,res){ } switch(true){ case(req.query.start&&req.query.start!==''&&req.query.end&&req.query.end!==''): - req.query.start=req.query.start.replace('T',' ') - req.query.end=req.query.end.replace('T',' ') req.sql+=' AND `time` '+req.query.startOperator+' ? AND `end` '+req.query.endOperator+' ?'; req.count_sql+=' AND `time` '+req.query.startOperator+' ? AND `end` '+req.query.endOperator+' ?'; req.ar.push(req.query.start) @@ -5685,14 +5690,12 @@ app.get(['/:auth/videos/:ke','/:auth/videos/:ke/:id'], function (req,res){ req.count_ar.push(req.query.end) break; case(req.query.start&&req.query.start!==''): - req.query.start=req.query.start.replace('T',' ') req.sql+=' AND `time` '+req.query.startOperator+' ?'; req.count_sql+=' AND `time` '+req.query.startOperator+' ?'; req.ar.push(req.query.start) req.count_ar.push(req.query.start) break; case(req.query.end&&req.query.end!==''): - req.query.end=req.query.end.replace('T',' ') req.sql+=' AND `end` '+req.query.endOperator+' ?'; req.count_sql+=' AND `end` '+req.query.endOperator+' ?'; req.ar.push(req.query.end) @@ -5712,17 +5715,17 @@ app.get(['/:auth/videos/:ke','/:auth/videos/:ke/:id'], function (req,res){ res.end(s.s({total:0,limit:req.query.limit,skip:0,videos:[]}, null, 3)); return } - s.sqlQuery(req.count_sql,req.count_ar,function(err,count){ - s.video('linkBuild',r,req.params.auth) - if(req.query.limit.indexOf(',')>-1){ - req.skip=parseInt(req.query.limit.split(',')[0]) - req.query.limit=parseInt(req.query.limit.split(',')[0]) - }else{ - req.skip=0 - req.query.limit=parseInt(req.query.limit) - } - res.end(s.s({isUTC:config.useUTC,total:count[0]['COUNT(*)'],limit:req.query.limit,skip:req.skip,videos:r}, null, 3)); - }) + s.sqlQuery(req.count_sql,req.count_ar,function(err,count){ + s.video('linkBuild',r,req.params.auth) + if(req.query.limit.indexOf(',')>-1){ + req.skip=parseInt(req.query.limit.split(',')[0]) + req.query.limit=parseInt(req.query.limit.split(',')[0]) + }else{ + req.skip=0 + req.query.limit=parseInt(req.query.limit) + } + res.end(s.s({isUTC:config.useUTC,total:count[0]['COUNT(*)'],limit:req.query.limit,skip:req.skip,videos:r}, null, 3)); + }) }) },res,req); }); @@ -5755,9 +5758,9 @@ app.get(['/:auth/events/:ke','/:auth/events/:ke/:id','/:auth/events/:ke/:id/:lim } } if(req.params.start&&req.params.start!==''){ - req.params.start=req.params.start.replace('T',' ') + req.params.start = s.stringToSqlTime(req.params.start) if(req.params.end&&req.params.end!==''){ - req.params.end=req.params.end.replace('T',' ') + req.params.end = s.stringToSqlTime(req.params.end) req.sql+=' AND `time` >= ? AND `time` <= ?'; req.ar.push(decodeURIComponent(req.params.start)) req.ar.push(decodeURIComponent(req.params.end)) @@ -5818,13 +5821,13 @@ app.get(['/:auth/logs/:ke','/:auth/logs/:ke/:id'], function (req,res){ req.query.endOperator='<=' } if(req.query.start && req.query.start !== '' && req.query.end && req.query.end !== ''){ - req.query.start=req.query.start.replace('T',' ') - req.query.end=req.query.end.replace('T',' ') + req.query.start = s.stringToSqlTime(req.query.start) + req.query.end = s.stringToSqlTime(req.query.end) req.sql+=' AND `time` '+req.query.startOperator+' ? AND `time` '+req.query.endOperator+' ?'; req.ar.push(req.query.start) req.ar.push(req.query.end) }else if(req.query.start && req.query.start !== ''){ - req.query.start=req.query.start.replace('T',' ') + req.query.start = s.stringToSqlTime(req.query.start) req.sql+=' AND `time` '+req.query.startOperator+' ?'; req.ar.push(req.query.start) } @@ -6160,7 +6163,7 @@ app.get('/:auth/videos/:ke/:id/:file', function (req,res){ time = s.utcToLocal(time) } time = new Date(time) - s.sqlQuery('SELECT * FROM Videos WHERE ke=? AND mid=? AND time=?',[req.params.ke,req.params.id,time],function(err,r){ + s.sqlQuery('SELECT * FROM Videos WHERE ke=? AND mid=? AND `time`=?',[req.params.ke,req.params.id,time],function(err,r){ if(r&&r[0]){ req.dir=s.video('getDir',r[0])+req.params.file if (fs.existsSync(req.dir)){ @@ -6256,7 +6259,7 @@ app.get(['/:auth/videos/:ke/:id/:file/:mode','/:auth/videos/:ke/:id/:file/:mode/ time = s.utcToLocal(time) } time = new Date(time) - req.sql='SELECT * FROM Videos WHERE ke=? AND mid=? AND time=?'; + req.sql='SELECT * FROM Videos WHERE ke=? AND mid=? AND `time`=?'; req.ar=[req.params.ke,req.params.id,time]; s.sqlQuery(req.sql,req.ar,function(err,r){ if(r&&r[0]){ @@ -6273,7 +6276,7 @@ app.get(['/:auth/videos/:ke/:id/:file/:mode','/:auth/videos/:ke/:id/:file/:mode/ req.ret.msg='Not a valid value.'; }else{ req.ret.ok=true; - s.sqlQuery('UPDATE Videos SET status=? WHERE ke=? AND mid=? AND time=?',[req.params.f,req.params.ke,req.params.id,time]) + s.sqlQuery('UPDATE Videos SET status=? WHERE ke=? AND mid=? AND `time`=?',[req.params.f,req.params.ke,req.params.id,time]) s.tx(r,'GRP_'+r.ke); } break; From 4f5da4ad7ae4a1e525be700940d4facd09842d7f Mon Sep 17 00:00:00 2001 From: Moe Date: Sat, 7 Jul 2018 10:41:09 -0700 Subject: [PATCH 02/16] allow multiple zip and download of videos - and cleanup in main.dash2.js --- LICENSE.md | 1 + camera.js | 89 ++++++++++++++++ languages/en_CA.json | 5 + web/libs/js/main.dash2.js | 184 ++++++++++++++++++++++++++++----- web/pages/blocks/videoview.ejs | 3 +- 5 files changed, 257 insertions(+), 25 deletions(-) diff --git a/LICENSE.md b/LICENSE.md index 9e331858..f6160f2d 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -102,6 +102,7 @@ Courthouse Vancouver Robson Square Node.js - https://nodejs.org/en/ MariaDB - https://mariadb.org/ FFmpeg - https://www.ffmpeg.org/ + request - https://www.npmjs.com/package/request Express (npm) - https://expressjs.com/ https://www.npmjs.com/package/express EJS (npm) - http://ejs.co/ https://www.npmjs.com/package/ejs pam-diff (npm) (Motion Detector) - https://github.com/kevinGodell/pam-diff diff --git a/camera.js b/camera.js index c3e670db..c398bf85 100644 --- a/camera.js +++ b/camera.js @@ -6151,6 +6151,95 @@ app.get('/:auth/fileBin/:ke/:id/:year/:month/:day/:file', function (req,res){ } s.auth(req.params,req.fn,res,req); }); +//zip videos and get link from fileBin +app.get('/:auth/zipVideos/:ke', function (req,res){ + res.header("Access-Control-Allow-Origin",req.headers.origin); + var failed = function(resp){ + res.setHeader('Content-Type', 'application/json'); + res.end(s.s(resp)) + } + if(req.query.videos && req.query.videos !== ''){ + s.auth(req.params,function(user){ + var videosSelected = JSON.parse(req.query.videos) + var where = [] + var values = [] + videosSelected.forEach(function(video){ + where.push("(ke=? AND mid=? AND `time`=?)") + if(!video.ke)video.ke = req.params.ke + values.push(video.ke) + values.push(video.mid) + var time = s.nameToTime(video.filename) + if(req.query.isUTC === 'true'){ + time = s.utcToLocal(time) + } + time = new Date(time) + values.push(time) + }) + s.sqlQuery('SELECT * FROM Videos WHERE '+where.join(' OR '),values,function(err,r){ + var resp = {ok:false} + if(r && r[0]){ + resp.ok = true + var zipDownload = null + var tempFiles = [] + var fileId = s.gid() + var fileBinDir = s.dir.fileBin+req.params.ke+'/' + var tempScript = s.dir.streams+req.params.ke+'/'+fileId+'.sh' + var zippedFilename = s.formattedTime()+'-'+fileId+'-Shinobi_Recordings.zip' + var zippedFile = fileBinDir+zippedFilename + var script = 'cd '+fileBinDir+' && zip -9 -r '+zippedFile + res.on('close', () => { + if(zipDownload && zipDownload.destroy){ + zipDownload.destroy() + } + fs.unlink(zippedFile); + }) + if(!fs.existsSync(fileBinDir)){ + fs.mkdirSync(fileBinDir); + } + r.forEach(function(video){ + timeFormatted = s.formattedTime(video.time) + video.filename = timeFormatted+'.'+video.ext + var dir = s.video('getDir',video)+video.filename + var tempVideoFile = timeFormatted+' - '+video.mid+'.'+video.ext + fs.writeFileSync(fileBinDir+tempVideoFile, fs.readFileSync(dir)) + tempFiles.push(fileBinDir+tempVideoFile) + script += ' "'+tempVideoFile+'"' + }) + console.log(script) + fs.writeFileSync(tempScript,script,'utf8') + var zipCreate = spawn('sh',(tempScript).split(' '),{detached: true}) + zipCreate.stderr.on('data',function(data){ + s.log({ke:req.params.ke,mid:'$USER'},{title:'Zip Create Error',msg:data.toString()}) + }) + zipCreate.on('exit',function(data){ + fs.unlinkSync(tempScript) + tempFiles.forEach(function(file){ + fs.unlink(file,function(){}) + }) + res.setHeader('Content-Disposition', 'attachment; filename="'+zippedFilename+'"') + var zipDownload = fs.createReadStream(zippedFile) + zipDownload.pipe(res) + zipDownload.on('error', function (error) { + s.log({ke:req.params.ke,mid:'$USER'},{title:'Zip Download Error',msg:error.toString()}) + if(zipDownload && zipDownload.destroy){ + zipDownload.destroy() + } + }); + zipDownload.on('close', function () { + res.end() + zipDownload.destroy(); + fs.unlinkSync(zippedFile); + }); + }) + }else{ + failed({ok:false,msg:'No Videos Found'}) + } + }) + },res,req); + }else{ + failed({ok:false,msg:'"videos" query variable is missing from request.'}) + } +}); // Get video file app.get('/:auth/videos/:ke/:id/:file', function (req,res){ s.auth(req.params,function(user){ diff --git a/languages/en_CA.json b/languages/en_CA.json index fac04d2f..967b91a8 100644 --- a/languages/en_CA.json +++ b/languages/en_CA.json @@ -211,9 +211,13 @@ "Set to Watch Only": "Set to Watch Only", "Save as": "Save as", "Add New": "Add New", + "Zip and Download": "Zip and Download", + "Export Selected Videos": "Export Selected Videos", "Delete Selected Videos": "Delete Selected Videos", "DeleteSelectedVideosMsg": "Do you want to delete these videos? You cannot recover them.", + "ExportSelectedVideosMsg": "Do you want to export these videos? It may take some time to zip and download.", "clientStreamFailedattemptingReconnect": "Client side ctream check failed, attempting reconnect.", + "Export Video": "Export Video", "Delete Filter": "Delete Filter", "confirmDeleteFilter": "Do you want to delete this filter? You cannot recover it.", "Fix Video": "Fix Video", @@ -249,6 +253,7 @@ "Unable to Launch": "Unable to Launch", "UnabletoLaunchText": "Please save new monitor first. Then attempt to launch the region editor.", "NoVideosFoundForDateRange": "No Videos found in this date range. Try setting the start date further back.", + "NoLogsFoundForDateRange": "No Logs found in this date range. Try widening the date range.", "monitorEditFailedMaxReached": "Your account has reached the maximum number of cameras that can be created. Speak to an administrator if you would like this changed.", "in": "in", "ago": "ago", diff --git a/web/libs/js/main.dash2.js b/web/libs/js/main.dash2.js index 926926eb..9b6fa26c 100644 --- a/web/libs/js/main.dash2.js +++ b/web/libs/js/main.dash2.js @@ -12,6 +12,20 @@ $.ccio={ fr:$('#files_recent'), mon:{} }; +$.ccio.permissionCheck = function(monitorId,toCheck){ + var details = $user.details + if(details.sub && details.allmonitors === '0'){ + var chosenValue = details[toCheck] + if(details[toCheck] instanceof Array && chosenValue.indexOf(monitorId) > -1){ + return true + }else if(chosenValue === '1'){ + return true + } + }else{ + return true + } + return false +} $.ccio.downloadJSON = function(jsonToDownload,filename,errorResponse){ var arr = jsonToDownload; if(arr.length===0 && errorResponse){ @@ -922,23 +936,90 @@ switch($user.details.lang){ tmp+='
'+d.name+', <%-cleanLang(lang['Recording FPS'])%> : '+d.fps+'
'; tmp+=''; tmp+='
'//start of btn list - $.each([ - {label:"<%-cleanLang(lang.Snapshot)%>",attr:'monitor="snapshot"',class:'primary',icon:'camera'}, - {label:"<%-cleanLang(lang['Show Logs'])%>",attr:'monitor="show_data"',class:'warning',icon:'exclamation-triangle'}, -// {label:"<%-cleanLang(lang['Show Logs'])%>",attr:'class_toggle="show_data" data-target="'+dataTarget+'"',class:'warning',icon:'exclamation-triangle'}, - {label:"<%-cleanLang(lang.Control)%>",attr:'monitor="control_toggle"',class:'default arrows',icon:'arrows'}, - {label:"<%-cleanLang(lang['Status Indicator'])%>",attr:'monitor="watch_on"',class:'success signal',icon:'plug'}, - {label:"<%-cleanLang(lang['Detector'])%>",attr:'monitor="motion"',class:'warning',icon:'grav'}, - {label:"<%-cleanLang(lang.Pop)%>",attr:'monitor="pop"',class:'default',icon:'external-link'}, -// {label:"<%-cleanLang(lang.Magnify)%>",attr:'monitor="magnify"',class:'default',icon:'search-plus'}, - {label:"<%-cleanLang(lang.Calendar)%>",attr:'monitor="calendar"',class:'default',icon:'calendar'}, - {label:"<%-cleanLang(lang['Power Viewer'])%>",attr:'monitor="powerview"',class:'default',icon:'map-marker'}, - {label:"<%-cleanLang(lang['Time-lapse'])%>",attr:'monitor="timelapse"',class:'default',icon:'angle-double-right'}, - {label:"<%-cleanLang(lang['Videos List'])%>",attr:'monitor="videos_table"',class:'default',icon:'film'}, - {label:"<%-cleanLang(lang['Monitor Settings'])%>",attr:'monitor="edit"',class:'default permission_monitor_edit',icon:'wrench'}, - {label:"<%-cleanLang(lang.Fullscreen)%>",attr:'monitor="fullscreen"',class:'default',icon:'arrows-alt'}, - {label:"<%-cleanLang(lang.Close)%>",attr:'monitor="watch_off"',class:'danger',icon:'times'}, - ],function(n,v){ + var buttons = { + "Snapshot": { + "label": "Snapshot", + "attr": "monitor=\"snapshot\"", + "class": "primary", + "icon": "camera" + }, + "Show Logs": { + "label": "Show Logs", + "attr": "monitor=\"show_data\"", + "class": "warning", + "icon": "exclamation-triangle" + }, + "Control": { + "label": "Control", + "attr": "monitor=\"control_toggle\"", + "class": "default arrows", + "icon": "arrows" + }, + "Status Indicator": { + "label": "Status Indicator", + "attr": "monitor=\"watch_on\"", + "class": "success signal", + "icon": "plug" + }, + "Detector": { + "label": "Detector", + "attr": "monitor=\"motion\"", + "class": "warning", + "icon": "grav" + }, + "Pop": { + "label": "Pop", + "attr": "monitor=\"pop\"", + "class": "default", + "icon": "external-link" + }, + "Calendar": { + "label": "Calendar", + "attr": "monitor=\"calendar\"", + "class": "default ", + "icon": "calendar" + }, + "Power Viewer": { + "label": "Power Viewer", + "attr": "monitor=\"powerview\"", + "class": "default", + "icon": "map-marker" + }, + "Time-lapse": { + "label": "Time-lapse", + "attr": "monitor=\"timelapse\"", + "class": "default", + "icon": "angle-double-right" + }, + "Videos List": { + "label": "Videos List", + "attr": "monitor=\"videos_table\"", + "class": "default", + "icon": "film" + }, + "Monitor Settings": { + "label": "Monitor Settings", + "attr": "monitor=\"edit\"", + "class": "default permission_monitor_edit", + "icon": "wrench" + }, + "Fullscreen": { + "label": "Fullscreen", + "attr": "monitor=\"fullscreen\"", + "class": "default", + "icon": "arrows-alt" + }, + "Close": { + "label": "Close", + "attr": "monitor=\"watch_off\"", + "class": "danger", + "icon": "times" + } + } +// if($.ccio.permissionCheck(d.mid,'video_view')){ +// +// } + $.each(buttons,function(n,v){ tmp+='' }) tmp+='
';//end of btn list @@ -1802,6 +1883,7 @@ $.ccio.globalWebsocket=function(d,user){ delete($.timelapse.currentVideosArray.videos[$.timelapse.currentVideos[d.filename].position]) $.timelapse.drawTimeline(false) } + if($.vidview.loadedVideos && $.vidview.loadedVideos[d.filename])delete($.vidview.loadedVideos[d.filename]) break; case'video_build_success': if(!d.mid){d.mid=d.id;};d.status=1; @@ -4068,27 +4150,78 @@ $.vidview.f.submit(function(e){ $('#videos_viewer_limit,#videos_viewer_daterange').change(function(){ $.vidview.f.submit() }) -$.vidview.e.find('.delete_selected').click(function(e){ - e.s={} +$.vidview.getSelected = function(getArray){ + var arr = {} + if(getArray){ + arr = [] + } $.vidview.f.find('[data-ke] input:checked').each(function(n,v){ v=$(v).parents('tr') - e.s[v.attr('data-file')]={mid:v.attr('data-mid'),auth:v.attr('data-auth')} + if(getArray){ + arr.push({filename:v.attr('data-file'),mid:v.attr('data-mid'),auth:v.attr('data-auth')}) + }else{ + arr[v.attr('data-file')]={mid:v.attr('data-mid'),auth:v.attr('data-auth')} + } }) + return arr +} +$.vidview.e.find('.delete_selected').click(function(){ + e = {} + e.s = $.vidview.getSelected() + if(Object.keys(e.s).length === 0){ + $.ccio.init('note',{ + title:'No Videos Selected', + text:'You must choose at least one video.', + type:'error' + },$user); + return + } $.confirm.e.modal('show'); $.confirm.title.text('<%-cleanLang(lang['Delete Selected Videos'])%>') e.html='<%-cleanLang(lang.DeleteSelectedVideosMsg)%>
' + var deleteLinks = [] $.each(e.s,function(n,v){ e.html+=n+'
'; + if($.vidview.loadedVideos[n])deleteLinks.push($.vidview.loadedVideos[n].links.deleteVideo) }) $.confirm.body.html(e.html) $.confirm.click({title:'Delete Video',class:'btn-danger'},function(){ - $.each(e.s,function(n,v){ - $.getJSON($.ccio.init('location',$.users[v.auth])+v.auth+'/videos/'+$user.ke+'/'+v.mid+'/'+n+'/delete',function(d){ + $.each(deleteLinks,function(n,link){ + $.getJSON(link,function(d){ $.ccio.log(d) }) }) }); }) +$.vidview.e.find('.export_selected').click(function(){ + e = {} + var videos = $.vidview.getSelected(true) + if(videos.length === 0){ + $.ccio.init('note',{ + title:'No Videos Selected', + text:'You must choose at least one video.', + type:'error' + },$user); + return + } + $.confirm.e.modal('show'); + $.confirm.title.text('<%-cleanLang(lang['Export Selected Videos'])%>') + var html = '<%-cleanLang(lang.ExportSelectedVideosMsg)%>
' + $.each(videos,function(n,v){ + html+=v.filename+'
'; + }) + $.confirm.body.html(html) + $.confirm.click({title:'Export Video',class:'btn-danger'},function(){ + var queryVariables = [] + queryVariables.push('videos='+JSON.stringify(videos)) + if(<%-config.useUTC%> === true){ + queryVariables.push('isUTC=true') + } + console.log(queryVariables) + var downloadZip = $.ccio.init('location',$user)+$user.auth_token+'/zipVideos/'+$user.ke+'?'+queryVariables.join('&') + $('#temp').html('').find('iframe').attr('src',downloadZip); + }); +}) $.vidview.pages.on('click','[page]',function(e){ e.limit=$.vidview.limit.val(); e.page=$(this).attr('page'); @@ -5161,6 +5294,7 @@ $('body') d.fn() $.vidview.pages.find('[page="'+$.vidview.current_page+'"]').addClass('active') e.v=$.vidview.e; + $.vidview.loadedVideos = {} e.b=e.v.modal('show').find('.modal-body .contents'); e.t=e.v.find('.modal-title i'); switch(e.a){ @@ -5169,7 +5303,8 @@ $('body') e.ar=[]; if(d.videos[0]){ $.each(d.videos,function(n,v){ - if(v.status!==0){ + if(v.status !== 0){ + $.vidview.loadedVideos[v.filename] = Object.assign(v,{}) var n=$.ccio.mon[v.ke+v.mid+user.auth_token]; if(n){v.title=n.name+' - '+(parseInt(v.size)/1000000).toFixed(2)+'mb';} v.start=v.time; @@ -5221,13 +5356,14 @@ $('body') e.tmp+=''; $.each(d.videos,function(n,v){ if(v.status!==0){ + $.vidview.loadedVideos[v.filename] = Object.assign(v,{}) var href = $.ccio.init('videoUrlBuild',v) v.mon=$.ccio.mon[v.ke+v.mid+user.auth_token]; v.start=v.time; // v.filename=$.ccio.init('tf',v.time)+'.'+v.ext; e.tmp+=''; e.tmp+='
'; - e.tmp+=''; + e.tmp+=''; e.tmp+=''+$.ccio.timeObject(v.end).format('h:mm:ss A, MMMM Do YYYY')+''; e.tmp+=''+$.ccio.timeObject(v.time).format('h:mm:ss A, MMMM Do YYYY')+''; e.tmp+=''+v.mon.name+''; diff --git a/web/pages/blocks/videoview.ejs b/web/pages/blocks/videoview.ejs index 1c21253d..b950bdae 100644 --- a/web/pages/blocks/videoview.ejs +++ b/web/pages/blocks/videoview.ejs @@ -31,7 +31,8 @@