diff --git a/definitions/en_CA.js b/definitions/en_CA.js index d1dd1a60..738e49b2 100644 --- a/definitions/en_CA.js +++ b/definitions/en_CA.js @@ -7608,6 +7608,11 @@ module.exports = function(s,config,lang){ `, pageOpen: 'monitorsList', }, + { + icon: 'map-marker', + label: `${lang['Power Viewer']}`, + pageOpen: 'powerVideo', + }, { icon: 'wrench', label: `${lang['Monitor Settings']}`, @@ -7792,5 +7797,203 @@ module.exports = function(s,config,lang){ } } }, + "Power Viewer": { + "section": lang["Power Viewer"], + "blocks": { + "Search Settings": { + id: "powerVideoTabs", + "color": "blue", + noHeader: true, + attribute: `tab-chooser-parent`, + "section-pre-class": "col-md-4", + "info": [ + { + "color": "blue", + noHeader: true, + isSection: true, + isFormGroupGroup: true, + "info": [ + { + "fieldType": "btn-group", + "btns": [ + { + "fieldType": "btn", + "class": `btn-primary btn-sm`, + "attribute": `tab-chooser="monitors"`, + "btnContent": `${lang['Monitors']}`, + }, + { + "fieldType": "btn", + "class": `btn-primary btn-sm`, + "attribute": `tab-chooser="settings"`, + "btnContent": `${lang['Search Settings']}`, + }, + ], + }, + ] + }, + { + "name": lang["Monitors"], + "color": "blue", + noId: true, + isFormGroupGroup: true, + attribute: `tab-section="monitors"`, + "info": [ + { + "id": "powerVideoMonitorsList", + "fieldType": "div", + "class": "list-group", + }, + ] + }, + { + hidden: true, + "name": lang["Search Settings"], + "color": "blue", + noId: true, + isFormGroupGroup: true, + attribute: `tab-section="settings"`, + "info": [ + { + "id": "powerVideoDateRange", + "field": lang['Date Range'], + }, + { + "id": "powerVideoVideoLimit", + "field": lang['Video Limit'] + ` (${lang['Per Monitor']})`, + "placeholder": "0", + }, + { + "id": "powerVideoEventLimit", + "field": lang['Event Limit'] + ` (${lang['Per Monitor']})`, + "placeholder": "500", + }, + { + id:'powerVideoSet', + field: lang['Video Set'], + default:'h264', + "fieldType": "select", + possible:[ + { + "name": lang.Local, + "value": "local" + }, + { + "name": lang.Cloud, + "value": "cloud" + }, + ] + }, + ] + }, + ] + }, + "Video Playback": { + id: "powerVideoVideoPlayback", + noHeader: true, + "color": "green", + "section-pre-class": "col-md-8 search-parent", + "info": [ + { + "id": "powerVideoMonitorViews", + "fieldType": "div", + }, + { + "id": "powerVideoMonitorControls", + "color": "blue", + noHeader: true, + isSection: true, + isFormGroupGroup: true, + 'section-class': 'text-center', + "info": [ + { + "fieldType": "btn-group", + "btns": [ + { + "fieldType": "btn", + "class": `btn-default btn-sm`, + "attribute": `powerVideo-control="toggleZoom" title="${lang['Zoom In']}"`, + "btnContent": ``, + }, + ], + }, + { + "fieldType": "btn-group", + "btns": [ + { + "fieldType": "btn", + "class": `btn-default btn-sm`, + "attribute": `powerVideo-control="previousVideoAll" title="${lang['Previous Video']}"`, + "btnContent": ``, + }, + { + "fieldType": "btn", + "class": `btn-danger btn-sm`, + "attribute": `powerVideo-control="playAll" title="${lang['Play']}"`, + "btnContent": ``, + }, + { + "fieldType": "btn", + "class": `btn-default btn-sm`, + "attribute": `powerVideo-control="pauseAll" title="${lang['Pause']}"`, + "btnContent": ``, + }, + { + "fieldType": "btn", + "class": `btn-default btn-sm`, + "attribute": `powerVideo-control="nextVideoAll" title="${lang['Next Video']}"`, + "btnContent": ``, + }, + ], + }, + { + "fieldType": "btn-group", + "style": "font-family: monospace;", + "btns": [ + { + "fieldType": "btn", + "class": `btn-default btn-sm`, + "attribute": `powerVideo-control="playSpeedAll" data-speed="1"`, + "btnContent": `1`, + }, + { + "fieldType": "btn", + "class": `btn-default btn-sm`, + "attribute": `powerVideo-control="playSpeedAll" data-speed="5"`, + "btnContent": `5`, + }, + { + "fieldType": "btn", + "class": `btn-default btn-sm`, + "attribute": `powerVideo-control="playSpeedAll" data-speed="10"`, + "btnContent": `10`, + }, + { + "fieldType": "btn", + "class": `btn-default btn-sm`, + "attribute": `powerVideo-control="playSpeedAll" data-speed="15"`, + "btnContent": `15`, + }, + ], + }, + ] + }, + ] + }, + "Time Strip": { + id: "powerVideoTimelineStripsContainer", + noHeader: true, + "color": "green", + "section-pre-class": "col-md-12 mt-3", + "info": [ + { + "id": "powerVideoTimelineStrips", + "fieldType": "div", + "divContent": `
${lang['Select a Monitor']}
`, + }, + ] + } + } + }, }) } diff --git a/languages/en_CA.json b/languages/en_CA.json index b4a8dab1..4c1232b6 100644 --- a/languages/en_CA.json +++ b/languages/en_CA.json @@ -1241,5 +1241,6 @@ "Motion Threshold":"Motion Threshold", "Attach Snapshot": "Attach Snapshot", "Invalid Settings": "Invalid Settings", - "Detection": "Detection" + "Detection": "Detection", + "Cloud": "Cloud" } diff --git a/web/assets/css/bs5.powerVideo.css b/web/assets/css/bs5.powerVideo.css new file mode 100644 index 00000000..59973929 --- /dev/null +++ b/web/assets/css/bs5.powerVideo.css @@ -0,0 +1,177 @@ +#powerVideo .videoPlayer { + text-align: center; + display: inline-block; + position: relative; +} +#powerVideo .videoPlayer video{ + max-width: 100%; + height: 300px; + object-fit: fill; +} + +#powerVideo .videoPlayer:fullscreen video{ + height: 100%; + max-height: 100%; +} + +#powerVideoMonitorControls{ + border-radius: 0 0 5px 5px; + padding: 5px; + background: #222; + margin: 0; +} + +#powerVideoMonitorsList{ + margin: 0; +} + +#powerVideoMonitorsList .list-item{ + cursor: pointer; +} + +#powerVideoMonitorViews { + text-align: center; + min-height: 300px; + background: #444; + border-radius: 5px 5px 0 0; + overflow: hidden; +} + +#powerVideo .videoPlayer .videoPlayer-detection-info { + position: absolute; + padding: 20px 10px 20px 10px; + height: 100%; + width: 100%; + top: 0; + left: 0; + margin: auto; + z-index: 11; + opacity: 0; + background: rgba(0,0,0,0.7); + color: #fff; + font-family: monospace; + overflow: auto; + text-align: left; +} + +#powerVideo .videoPlayer:hover .videoPlayer-detection-info, +#powerVideo .videoPlayer.show-detection-info .videoPlayer-detection-info { + opacity: 1 +} + +#powerVideo .videoPlayer .videoPlayer-stream-objects { + position: absolute; + width: 100%; + height: 100%; + left: 0; + right: 0; + margin: auto; + z-index: 10; +} + +#powerVideo .videoPlayer .videoPlayer-detection-info-object div { + padding-left: 5px; +} + +#powerVideo .videoPlayer .videoPlayer-detection-info-object { + text-align: left +} + +.videoPlayer-stream-objects .tag { + position: absolute; + bottom: 100%; + left: 0; + background: red; + color: #fff; + font-family: monospace; + font-size: 80%; + border-radius: 5px 5px 0 0; + padding: 3px 5px; +} + +.videoPlayer-stream-objects .stream-detected-object { + position: absolute; + top: 0; + left: 0; + border: 3px solid red; + background: transparent; + border-radius: 5px +} + +.videoPlayer-stream-objects .stream-detected-point { + position: absolute; + top: 0; + left: 0; + border: 3px solid yellow; + background: transparent; + border-radius: 5px +} + +.videoPlayer-stream-objects .point { + position: absolute; + top: 0; + left: 0; + border: 3px solid red; + border-radius: 50% +} + +/* loading */ +#powerVideo .loading { + font-size: 20pt; + text-align: center; +} +#powerVideo .loading > div { + margin-top: 5px +} + +/* VIS.js */ + +#powerVideo video { + width: 100%; + padding: 6px 0 0 0 +} + +#powerVideo .videoAfter, +#powerVideo .videoBefore { + display: none; +} + +#powerVideo .vis-timeline { + font-family: monospace; + border-radius: 5px; + border-color: #172b4d; +} +#powerVideo .vis-item { + border-color: #347af1; + background-color: #4d87d0; + color: #fff; +} +#powerVideo .vis-item.vis-selected { + border-color: #f5365c; + background-color: #f5365c; + color: #fff; +} +#powerVideo .vis-panel.vis-bottom { + border: 1px #17294b; +} +#powerVideo .vis-time-axis .vis-grid.vis-minor{ + border-color: #1a539a; +} +#powerVideo .vis-time-axis .vis-grid.vis-major { + border-color: #4d87d0; +} +#powerVideo .vis-time-axis .vis-text { + color: #fff; +} + +[timeline-video-file] .progress{ + position: absolute; + bottom: 0; + left: 0; + width: 100%; + height: 3px; + opacity: 0; +} +.vis-selected [timeline-video-file] .progress{ + opacity: 1; +} diff --git a/web/assets/js/bs5.dashboard-base.js b/web/assets/js/bs5.dashboard-base.js index f78a800b..4540a71a 100644 --- a/web/assets/js/bs5.dashboard-base.js +++ b/web/assets/js/bs5.dashboard-base.js @@ -851,6 +851,17 @@ $(document).ready(function(){ else $(this).show(); }); + }) + .on('click','[tab-chooser]',function(){ + var el = $(this) + var parent = el.parents('[tab-chooser-parent]') + var tabName = el.attr('tab-chooser') + var allTabChoosersInParent = parent.find('[tab-chooser]') + var allTabsInParent = parent.find('[tab-section]') + allTabsInParent.hide() + allTabChoosersInParent.removeClass('active') + el.addClass('active') + parent.find(`[tab-section="${tabName}"]`).show() }); $('.logout').click(function(e){ $.get(getApiPrefix() + '/logout/' + $user.ke + '/' + $user.uid,function(data){ diff --git a/web/assets/js/bs5.monitorsUtils.js b/web/assets/js/bs5.monitorsUtils.js index a0d5d463..f834902f 100644 --- a/web/assets/js/bs5.monitorsUtils.js +++ b/web/assets/js/bs5.monitorsUtils.js @@ -553,6 +553,120 @@ function buildDefaultMonitorMenuItems(){
  • ${lang['Watch-Only']}
  • ${lang.Record}
  • ` } +function magnifyStream(options){ + if(!options.p && !options.parent){ + var el = $(this), + parent = el.parents('[mid]') + }else{ + parent = options.p || options.parent + } + if(!options.attribute){ + options.attribute = '' + } + if(options.animate === true){ + var zoomGlassAnimate = 'animate' + }else{ + var zoomGlassAnimate = 'css' + } + if(!options.magnifyOffsetElement){ + options.magnifyOffsetElement = '.stream-block' + } + if(!options.targetForZoom){ + options.targetForZoom = '.stream-element' + } + if(options.auto === true){ + var streamBlockOperator = 'position' + }else{ + var streamBlockOperator = 'offset' + } + var magnifiedElement + if(!options.videoUrl){ + if(options.useCanvas === true){ + magnifiedElement = 'canvas' + }else{ + magnifiedElement = 'iframe' + } + }else{ + magnifiedElement = 'video' + } + if(!options.mon && !options.monitor){ + var groupKey = parent.attr('ke')//group key + var monitorId = parent.attr('mid')//monitor id + var sessionKey = parent.attr('auth')//authkey + var monitor = $.ccio.mon[groupKey + monitorId + sessionKey]//monitor configuration + }else{ + var monitor = options.mon || options.monitor + var groupKey = monitor.ke//group key + var monitorId = monitor.mid//monitor id + var sessionKey = monitor.auth//authkey + } + if(options.zoomAmount)zoomAmount = 3 + if(!zoomAmount)zoomAmount = 3 + var realHeight = parent.attr('realHeight') + var realWidth = parent.attr('realWidth') + var height = parseFloat(realHeight) * zoomAmount//height of stream + var width = parseFloat(realWidth) * zoomAmount//width of stream + var targetForZoom = parent.find(options.targetForZoom) + zoomGlass = parent.find(".zoomGlass") + var zoomFrame = function(){ + var magnify_offset = parent.find(options.magnifyOffsetElement)[streamBlockOperator]() + var mx = options.pageX - magnify_offset.left + var my = options.pageY - magnify_offset.top + var rx = Math.round(mx/targetForZoom.width()*width - zoomGlass.width()/2)*-1 + var ry = Math.round(my/targetForZoom.height()*height - zoomGlass.height()/2)*-1 + var px = mx - zoomGlass.width()/2 + var py = my - zoomGlass.height()/2 + zoomGlass[zoomGlassAnimate]({left: px, top: py}).find(magnifiedElement)[zoomGlassAnimate]({left: rx, top: ry}) + } + var commit = function(height,width){ + zoomGlass.find(magnifiedElement).css({ + height: height, + width: width + }) + zoomFrame() + } + if(!height || !width || zoomGlass.length === 0){ + zoomGlass = parent.find(".zoomGlass") + var zoomGlassShell = function(contents){return `
    ${contents}
    `} + if(!options.videoUrl){ + $.ccio.snapshot(monitor,function(url,buffer,w,h){ + parent.attr('realWidth',w) + parent.attr('realHeight',h) + if(zoomGlass.length === 0){ + if(options.useCanvas === true){ + parent.append(zoomGlassShell('')) + }else{ + parent.append(zoomGlassShell('