Merge branch 'master' of github.com:ZoneMinder/zoneminder
commit
c8aac87f74
|
@ -148,6 +148,9 @@ set(ZM_CACHEDIR "/var/cache/zoneminder" CACHE PATH
|
|||
"Location of the web server cache busting files, default: /var/cache/zoneminder")
|
||||
set(ZM_CONTENTDIR "/var/lib/zoneminder" CACHE PATH
|
||||
"Location of dynamic content (events and images), default: /var/lib/zoneminder")
|
||||
set(ZM_FONTDIR "${CMAKE_INSTALL_FULL_DATADIR}/zoneminder/fonts" CACHE PATH
|
||||
"Location of the font files used for timestamping, default: <prefix>/${CMAKE_INSTALL_DATADIR}/zoneminder/fonts")
|
||||
|
||||
set(ZM_DB_HOST "localhost" CACHE STRING
|
||||
"Hostname where ZoneMinder database located, default: localhost")
|
||||
set(ZM_DB_NAME "zm" CACHE STRING
|
||||
|
@ -911,6 +914,7 @@ set(BUILD_SHARED_LIBS "${BUILD_SHARED_LIBS_SAVED}")
|
|||
add_subdirectory(src)
|
||||
add_subdirectory(scripts)
|
||||
add_subdirectory(db)
|
||||
add_subdirectory(fonts)
|
||||
add_subdirectory(web)
|
||||
add_subdirectory(misc)
|
||||
add_subdirectory(onvif)
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
# Glob all database upgrade scripts
|
||||
file(GLOB fontfileslist RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "*.zmfnt")
|
||||
# Install the fonts
|
||||
install(FILES ${fontfileslist} DESTINATION "${ZM_FONTDIR}")
|
||||
|
Binary file not shown.
|
@ -3780,6 +3780,14 @@ our @options = (
|
|||
type => $types{boolean},
|
||||
category => 'logging',
|
||||
},
|
||||
{
|
||||
name => 'ZM_FONT_FILE_LOCATION',
|
||||
default => '@ZM_FONTDIR@/default.zmfnt',
|
||||
description => 'Font file location',
|
||||
help => 'This font is used for timestamp labels.',
|
||||
type => $types{string},
|
||||
category => 'config',
|
||||
},
|
||||
);
|
||||
|
||||
our %options_hash = map { ( $_->{name}, $_ ) } @options;
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
configure_file(zm_config_data.h.in "${CMAKE_CURRENT_BINARY_DIR}/zm_config_data.h" @ONLY)
|
||||
|
||||
# Group together all the source files that are used by all the binaries (zmc, zma, zmu, zms etc)
|
||||
set(ZM_BIN_SRC_FILES zm_box.cpp zm_buffer.cpp zm_camera.cpp zm_comms.cpp zm_config.cpp zm_coord.cpp zm_curl_camera.cpp zm.cpp zm_db.cpp zm_logger.cpp zm_event.cpp zm_frame.cpp zm_eventstream.cpp zm_exception.cpp zm_file_camera.cpp zm_ffmpeg_input.cpp zm_ffmpeg_camera.cpp zm_group.cpp zm_image.cpp zm_jpeg.cpp zm_libvlc_camera.cpp zm_libvnc_camera.cpp zm_local_camera.cpp zm_monitor.cpp zm_monitorstream.cpp zm_ffmpeg.cpp zm_mpeg.cpp zm_packet.cpp zm_packetqueue.cpp zm_poly.cpp zm_regexp.cpp zm_remote_camera.cpp zm_remote_camera_http.cpp zm_remote_camera_nvsocket.cpp zm_remote_camera_rtsp.cpp zm_rtp.cpp zm_rtp_ctrl.cpp zm_rtp_data.cpp zm_rtp_source.cpp zm_rtsp.cpp zm_rtsp_auth.cpp zm_sdp.cpp zm_signal.cpp zm_stream.cpp zm_swscale.cpp zm_thread.cpp zm_time.cpp zm_timer.cpp zm_user.cpp zm_utils.cpp zm_video.cpp zm_videostore.cpp zm_zone.cpp zm_storage.cpp zm_fifo.cpp zm_crypt.cpp)
|
||||
set(ZM_BIN_SRC_FILES zm_box.cpp zm_buffer.cpp zm_camera.cpp zm_comms.cpp zm_config.cpp zm_coord.cpp zm_curl_camera.cpp zm.cpp zm_db.cpp zm_logger.cpp zm_event.cpp zm_frame.cpp zm_eventstream.cpp zm_exception.cpp zm_file_camera.cpp zm_ffmpeg_input.cpp zm_ffmpeg_camera.cpp zm_group.cpp zm_image.cpp zm_jpeg.cpp zm_libvlc_camera.cpp zm_libvnc_camera.cpp zm_local_camera.cpp zm_monitor.cpp zm_monitorstream.cpp zm_ffmpeg.cpp zm_font.cpp zm_mpeg.cpp zm_packet.cpp zm_packetqueue.cpp zm_poly.cpp zm_regexp.cpp zm_remote_camera.cpp zm_remote_camera_http.cpp zm_remote_camera_nvsocket.cpp zm_remote_camera_rtsp.cpp zm_rtp.cpp zm_rtp_ctrl.cpp zm_rtp_data.cpp zm_rtp_source.cpp zm_rtsp.cpp zm_rtsp_auth.cpp zm_sdp.cpp zm_signal.cpp zm_stream.cpp zm_swscale.cpp zm_thread.cpp zm_time.cpp zm_timer.cpp zm_user.cpp zm_utils.cpp zm_video.cpp zm_videostore.cpp zm_zone.cpp zm_storage.cpp zm_fifo.cpp zm_crypt.cpp)
|
||||
|
||||
|
||||
# A fix for cmake recompiling the source files for every target.
|
||||
|
|
6155
src/zm_bigfont.h
6155
src/zm_bigfont.h
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,72 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "zm.h"
|
||||
#include "zm_font.h"
|
||||
#include "zm_utils.h"
|
||||
|
||||
int ZmFont::ReadFontFile(const std::string &loc) {
|
||||
FILE *f = fopen(loc.c_str(), "rb");
|
||||
if ( !f ) return -1; // FILE NOT FOUND
|
||||
|
||||
struct stat st;
|
||||
stat(loc.c_str(), &st);
|
||||
|
||||
font = new ZMFONT;
|
||||
|
||||
// MAGIC + pad + BitmapHeaders
|
||||
size_t readsize = fread(&font[0], 1, 8 + (sizeof(ZMFONT_BH) * 4), f);
|
||||
if ( readsize < 8 + (sizeof(ZMFONT_BH) * 4) ) {
|
||||
delete font;
|
||||
font = nullptr;
|
||||
return -2; // EOF reached, invalid file
|
||||
}
|
||||
|
||||
if ( memcmp(font->MAGIC, "ZMFNT", 5) != 0 ) // Check whether magic is correct
|
||||
return -3;
|
||||
|
||||
for ( int i = 0; i < 4; i++ ) {
|
||||
/* Character Width cannot be greater than 64 as a row is represented as a uint64_t,
|
||||
height cannot be greater than 200(arbitary number which i have chosen, shouldn't need more than this) and
|
||||
idx should not be more than filesize
|
||||
*/
|
||||
if ( (font->header[i].charWidth > 64 && font->header[i].charWidth == 0) || \
|
||||
(font->header[i].charHeight > 200 && font->header[i].charHeight == 0) || \
|
||||
(font->header[i].idx > st.st_size) ) {
|
||||
delete font;
|
||||
font = nullptr;
|
||||
return -4;
|
||||
}
|
||||
}
|
||||
|
||||
datasize = st.st_size - (8 + sizeof(ZMFONT_BH) * 4);
|
||||
|
||||
font->data = new uint64_t[datasize/sizeof(uint64_t)];
|
||||
readsize = fread(&font->data[0], 1, datasize, f);
|
||||
if( readsize < datasize) { // Shouldn't happen
|
||||
delete[] font->data;
|
||||
font->data = nullptr;
|
||||
delete font;
|
||||
font = nullptr;
|
||||
return -2;
|
||||
}
|
||||
fclose(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ZmFont::~ZmFont() {
|
||||
if ( font && font->data ) {
|
||||
delete[] font->data;
|
||||
font->data = nullptr;
|
||||
}
|
||||
|
||||
if ( font ) {
|
||||
delete font;
|
||||
font = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t *ZmFont::GetBitmapData() {
|
||||
return &font->data[font->header[size].idx];
|
||||
}
|
3373
src/zm_font.h
3373
src/zm_font.h
File diff suppressed because it is too large
Load Diff
148
src/zm_image.cpp
148
src/zm_image.cpp
|
@ -18,7 +18,6 @@
|
|||
//
|
||||
#include "zm.h"
|
||||
#include "zm_font.h"
|
||||
#include "zm_bigfont.h"
|
||||
#include "zm_image.h"
|
||||
#include "zm_utils.h"
|
||||
#include "zm_rgb.h"
|
||||
|
@ -78,6 +77,9 @@ static deinterlace_4field_fptr_t fptr_deinterlace_4field_gray8;
|
|||
/* Pointer to image buffer memory copy function */
|
||||
imgbufcpy_fptr_t fptr_imgbufcpy;
|
||||
|
||||
/* Font */
|
||||
static ZmFont font;
|
||||
|
||||
void Image::update_function_pointers() {
|
||||
/* Because many loops are unrolled and work on 16 colours/time or 4 pixels/time, we have to meet requirements */
|
||||
if ( pixels % 16 || pixels % 12 ) {
|
||||
|
@ -489,6 +491,12 @@ void Image::Initialise() {
|
|||
g_u_table = g_u_table_global;
|
||||
b_u_table = b_u_table_global;
|
||||
|
||||
int res = font.ReadFontFile(config.font_file_location);
|
||||
if( res == -1 ) {
|
||||
Panic("Invalid font location.");
|
||||
} else if( res == -2 || res == -3 || res == -4 ) {
|
||||
Panic("Invalid font file.");
|
||||
}
|
||||
initialised = true;
|
||||
}
|
||||
|
||||
|
@ -1873,8 +1881,12 @@ const Coord Image::centreCoord( const char *text, int size=1 ) const {
|
|||
line = text+index;
|
||||
line_no++;
|
||||
}
|
||||
int x = (width - (max_line_len * ZM_CHAR_WIDTH * size) ) / 2;
|
||||
int y = (height - (line_no * LINE_HEIGHT * size) ) / 2;
|
||||
|
||||
font.SetFontSize(size);
|
||||
uint16_t char_width = font.GetCharWidth();
|
||||
uint16_t char_height = font.GetCharHeight();
|
||||
int x = (width - (max_line_len * char_width )) / 2;
|
||||
int y = (height - (line_no * char_height) ) / 2;
|
||||
return Coord(x, y);
|
||||
}
|
||||
|
||||
|
@ -1920,8 +1932,10 @@ void Image::MaskPrivacy( const unsigned char *p_bitmask, const Rgb pixel_colour
|
|||
}
|
||||
|
||||
/* RGB32 compatible: complete */
|
||||
void Image::Annotate( const char *p_text, const Coord &coord, const unsigned int size, const Rgb fg_colour, const Rgb bg_colour )
|
||||
{
|
||||
/* Bitmap decoding trick has been adopted from here:
|
||||
https://lemire.me/blog/2018/02/21/iterating-over-set-bits-quickly/
|
||||
*/
|
||||
void Image::Annotate( const char *p_text, const Coord &coord, const unsigned int size, const Rgb fg_colour, const Rgb bg_colour ) {
|
||||
strncpy(text, p_text, sizeof(text)-1);
|
||||
|
||||
unsigned int index = 0;
|
||||
|
@ -1934,31 +1948,30 @@ void Image::Annotate( const char *p_text, const Coord &coord, const unsigned int
|
|||
const uint8_t fg_g_col = GREEN_VAL_RGBA(fg_colour);
|
||||
const uint8_t fg_b_col = BLUE_VAL_RGBA(fg_colour);
|
||||
const uint8_t fg_bw_col = fg_colour & 0xff;
|
||||
const Rgb fg_rgb_col = rgb_convert(fg_colour,subpixelorder);
|
||||
const bool fg_trans = (fg_colour == RGB_TRANSPARENT);
|
||||
const Rgb fg_rgb_col = rgb_convert(fg_colour, subpixelorder);
|
||||
|
||||
const uint8_t bg_r_col = RED_VAL_RGBA(bg_colour);
|
||||
const uint8_t bg_g_col = GREEN_VAL_RGBA(bg_colour);
|
||||
const uint8_t bg_b_col = BLUE_VAL_RGBA(bg_colour);
|
||||
const uint8_t bg_bw_col = bg_colour & 0xff;
|
||||
const Rgb bg_rgb_col = rgb_convert(bg_colour,subpixelorder);
|
||||
const Rgb bg_rgb_col = rgb_convert(bg_colour, subpixelorder);
|
||||
const bool bg_trans = (bg_colour == RGB_TRANSPARENT);
|
||||
|
||||
int zm_text_bitmask = 0x80;
|
||||
if ( size == 2 )
|
||||
zm_text_bitmask = 0x8000;
|
||||
font.SetFontSize(size);
|
||||
const uint16_t char_width = font.GetCharWidth();
|
||||
const uint16_t char_height = font.GetCharHeight();
|
||||
const uint64_t *font_bitmap = font.GetBitmapData();
|
||||
|
||||
while ( (index < text_len) && (line_len = strcspn(line, "\n")) ) {
|
||||
|
||||
unsigned int line_width = line_len * ZM_CHAR_WIDTH * size;
|
||||
unsigned int line_width = line_len * char_width;
|
||||
|
||||
unsigned int lo_line_x = coord.X();
|
||||
unsigned int lo_line_y = coord.Y() + (line_no * LINE_HEIGHT * size);
|
||||
unsigned int lo_line_y = coord.Y() + (line_no * char_height);
|
||||
|
||||
unsigned int min_line_x = 0;
|
||||
unsigned int max_line_x = width - line_width;
|
||||
unsigned int min_line_y = 0;
|
||||
unsigned int max_line_y = height - (LINE_HEIGHT * size);
|
||||
unsigned int max_line_y = height - char_height;
|
||||
|
||||
if ( lo_line_x > max_line_x )
|
||||
lo_line_x = max_line_x;
|
||||
|
@ -1970,7 +1983,7 @@ void Image::Annotate( const char *p_text, const Coord &coord, const unsigned int
|
|||
lo_line_y = min_line_y;
|
||||
|
||||
unsigned int hi_line_x = lo_line_x + line_width;
|
||||
unsigned int hi_line_y = lo_line_y + (LINE_HEIGHT * size);
|
||||
unsigned int hi_line_y = lo_line_y + char_height;
|
||||
|
||||
// Clip anything that runs off the right of the screen
|
||||
if ( hi_line_x > width )
|
||||
|
@ -1980,100 +1993,77 @@ void Image::Annotate( const char *p_text, const Coord &coord, const unsigned int
|
|||
|
||||
if ( colours == ZM_COLOUR_GRAY8 ) {
|
||||
unsigned char *ptr = &buffer[(lo_line_y*width)+lo_line_x];
|
||||
for ( unsigned int y = lo_line_y, r = 0; y < hi_line_y && r < (ZM_CHAR_HEIGHT * size); y++, r++, ptr += width ) {
|
||||
for ( unsigned int y = lo_line_y, r = 0; y < hi_line_y && r < char_height; y++, r++, ptr += width ) {
|
||||
unsigned char *temp_ptr = ptr;
|
||||
for ( unsigned int x = lo_line_x, c = 0; x < hi_line_x && c < line_len; c++ ) {
|
||||
int f;
|
||||
if ( size == 2 ) {
|
||||
if ( (line[c] * ZM_CHAR_HEIGHT * size) + r > sizeof(bigfontdata) ) {
|
||||
if ( line[c] > 0xFF ) {
|
||||
Warning("Unsupported character %c in %s", line[c], line);
|
||||
continue;
|
||||
}
|
||||
f = bigfontdata[(line[c] * ZM_CHAR_HEIGHT * size) + r];
|
||||
} else {
|
||||
if ( (line[c] * ZM_CHAR_HEIGHT) + r > sizeof(fontdata) ) {
|
||||
Warning("Unsupported character %c in %s", line[c], line);
|
||||
continue;
|
||||
}
|
||||
f = fontdata[(line[c] * ZM_CHAR_HEIGHT) + r];
|
||||
}
|
||||
for ( unsigned int i = 0; i < (ZM_CHAR_WIDTH * size) && x < hi_line_x; i++, x++, temp_ptr++ ) {
|
||||
if ( f & (zm_text_bitmask >> i) ) {
|
||||
if ( !fg_trans )
|
||||
*temp_ptr = fg_bw_col;
|
||||
} else if ( !bg_trans ) {
|
||||
*temp_ptr = bg_bw_col;
|
||||
}
|
||||
uint64_t f = font_bitmap[(line[c] * char_height) + r];
|
||||
if ( !bg_trans ) memset(temp_ptr, bg_bw_col, char_width);
|
||||
while ( f != 0 ) {
|
||||
uint64_t t = f & -f;
|
||||
int idx = char_width - __builtin_ctzll(f>>2);
|
||||
*(temp_ptr + idx) = fg_bw_col;
|
||||
f ^= t;
|
||||
}
|
||||
temp_ptr += char_width;
|
||||
}
|
||||
}
|
||||
} else if ( colours == ZM_COLOUR_RGB24 ) {
|
||||
unsigned int wc = width * colours;
|
||||
|
||||
unsigned char *ptr = &buffer[((lo_line_y*width)+lo_line_x)*colours];
|
||||
for ( unsigned int y = lo_line_y, r = 0; y < hi_line_y && r < (ZM_CHAR_HEIGHT * size); y++, r++, ptr += wc ) {
|
||||
for ( unsigned int y = lo_line_y, r = 0; y < hi_line_y && r < char_height; y++, r++, ptr += wc ) {
|
||||
unsigned char *temp_ptr = ptr;
|
||||
for ( unsigned int x = lo_line_x, c = 0; x < hi_line_x && c < line_len; c++ ) {
|
||||
int f;
|
||||
if ( size == 2 ) {
|
||||
if ( (line[c] * ZM_CHAR_HEIGHT * size) + r > sizeof(bigfontdata) ) {
|
||||
if ( line[c] > 0xFF ) {
|
||||
Warning("Unsupported character %c in %s", line[c], line);
|
||||
continue;
|
||||
}
|
||||
f = bigfontdata[(line[c] * ZM_CHAR_HEIGHT * size) + r];
|
||||
} else {
|
||||
if ( (line[c] * ZM_CHAR_HEIGHT) + r > sizeof(fontdata) ) {
|
||||
Warning("Unsupported character %c in %s", line[c], line);
|
||||
continue;
|
||||
}
|
||||
f = fontdata[(line[c] * ZM_CHAR_HEIGHT) + r];
|
||||
}
|
||||
for ( unsigned int i = 0; i < (ZM_CHAR_WIDTH * size) && x < hi_line_x; i++, x++, temp_ptr += colours ) {
|
||||
if ( f & (zm_text_bitmask >> i) ) {
|
||||
if ( !fg_trans ) {
|
||||
RED_PTR_RGBA(temp_ptr) = fg_r_col;
|
||||
GREEN_PTR_RGBA(temp_ptr) = fg_g_col;
|
||||
BLUE_PTR_RGBA(temp_ptr) = fg_b_col;
|
||||
uint64_t f = font_bitmap[(line[c] * char_height) + r];
|
||||
if ( !bg_trans ) {
|
||||
for( int i = 0; i < char_width; i++ ) { // We need to set individual r,g,b components
|
||||
RED_PTR_RGBA((temp_ptr + (i*3))) = bg_r_col;
|
||||
GREEN_PTR_RGBA((temp_ptr + (i*3))) = bg_g_col;
|
||||
BLUE_PTR_RGBA((temp_ptr + (i*3))) = bg_b_col;
|
||||
}
|
||||
} else if ( !bg_trans ) {
|
||||
RED_PTR_RGBA(temp_ptr) = bg_r_col;
|
||||
GREEN_PTR_RGBA(temp_ptr) = bg_g_col;
|
||||
BLUE_PTR_RGBA(temp_ptr) = bg_b_col;
|
||||
}
|
||||
}
|
||||
while ( f != 0 ) {
|
||||
uint64_t t = f & -f;
|
||||
int idx = char_width - __builtin_ctzll(f >> 2);
|
||||
RED_PTR_RGBA((temp_ptr + (idx*3))) = fg_r_col;
|
||||
GREEN_PTR_RGBA((temp_ptr + (idx*3))) = fg_g_col;
|
||||
BLUE_PTR_RGBA((temp_ptr + (idx*3))) = fg_b_col;
|
||||
f ^= t;
|
||||
}
|
||||
temp_ptr += char_width * colours;
|
||||
}
|
||||
}
|
||||
} else if ( colours == ZM_COLOUR_RGB32 ) {
|
||||
unsigned int wc = width * colours;
|
||||
|
||||
uint8_t *ptr = &buffer[((lo_line_y*width)+lo_line_x)<<2];
|
||||
for ( unsigned int y = lo_line_y, r = 0; y < hi_line_y && r < (ZM_CHAR_HEIGHT * size); y++, r++, ptr += wc ) {
|
||||
uint8_t *ptr = &buffer[((lo_line_y*width)+lo_line_x) << 2];
|
||||
for ( unsigned int y = lo_line_y, r = 0; y < hi_line_y && r < char_height; y++, r++, ptr += wc ) {
|
||||
Rgb* temp_ptr = (Rgb*)ptr;
|
||||
for ( unsigned int x = lo_line_x, c = 0; x < hi_line_x && c < line_len; c++ ) {
|
||||
int f;
|
||||
if ( size == 2 ) {
|
||||
if ( (line[c] * ZM_CHAR_HEIGHT * size) + r > sizeof(bigfontdata) ) {
|
||||
if ( line[c] > 0xFF ) {
|
||||
Warning("Unsupported character %c in %s", line[c], line);
|
||||
continue;
|
||||
}
|
||||
f = bigfontdata[(line[c] * ZM_CHAR_HEIGHT * size) + r];
|
||||
} else {
|
||||
if ( (line[c] * ZM_CHAR_HEIGHT) + r > sizeof(fontdata) ) {
|
||||
Warning("Unsupported character %c in %s", line[c], line);
|
||||
continue;
|
||||
uint64_t f = font_bitmap[(line[c] * char_height) + r];
|
||||
if ( !bg_trans ) {
|
||||
for( int i = 0; i < char_width; i++ )
|
||||
*(temp_ptr + i) = bg_rgb_col;
|
||||
}
|
||||
f = fontdata[(line[c] * ZM_CHAR_HEIGHT) + r];
|
||||
}
|
||||
for ( unsigned int i = 0; i < (ZM_CHAR_WIDTH * size) && x < hi_line_x; i++, x++, temp_ptr++ ) {
|
||||
if ( f & (zm_text_bitmask >> i) ) {
|
||||
if ( !fg_trans ) {
|
||||
*temp_ptr = fg_rgb_col;
|
||||
}
|
||||
} else if ( !bg_trans ) {
|
||||
*temp_ptr = bg_rgb_col;
|
||||
while ( f != 0 ) {
|
||||
uint64_t t = f & -f;
|
||||
int idx = char_width - __builtin_ctzll(f >> 2);
|
||||
*(temp_ptr + idx) = fg_rgb_col;
|
||||
f ^= t;
|
||||
}
|
||||
temp_ptr += char_width;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
if ( !canEdit('Events') ) return;
|
||||
|
||||
$eid = isset($_REQUEST['eid']) ? $_REQUEST['eid'] : '';
|
||||
$eid = validInt($eid);
|
||||
$Event = new ZM\Event($eid);
|
||||
|
||||
?>
|
||||
<div class="modal" id="eventRenameModal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title"><?php echo translate('Rename') .' '. translate('Event') ?></h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<input type="text" value="<?php echo validHtmlStr($Event->Name()) ?>"/>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary" id="eventRenameBtn"><?php echo translate('Save') ?></button>
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal"><?php echo translate('Cancel') ?></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -330,7 +330,7 @@ function collectData() {
|
|||
foreach ( $postFuncs as $element=>$func )
|
||||
$sqlData[$element] = eval('return( '.$func.'( $sqlData ) );');
|
||||
$data[] = $sqlData;
|
||||
if ( isset($limi) && ++$count >= $limit )
|
||||
if ( isset($limit) && ++$count >= $limit )
|
||||
break;
|
||||
} # end foreach
|
||||
} # end if have limit == 1
|
||||
|
@ -364,6 +364,7 @@ switch ( $_REQUEST['layout'] ) {
|
|||
$response = array( strtolower(validJsStr($_REQUEST['entity'])) => $data );
|
||||
if ( isset($_REQUEST['loopback']) )
|
||||
$response['loopback'] = validJsStr($_REQUEST['loopback']);
|
||||
#ZM\Warning(print_r($response, true));
|
||||
ajaxResponse($response);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -571,3 +571,6 @@ li.search-choice {
|
|||
}
|
||||
/* end chosen override */
|
||||
|
||||
modal-content {
|
||||
background-color: #222222;
|
||||
}
|
||||
|
|
|
@ -83,7 +83,7 @@ function exportEventDetail($event, $exportFrames, $exportImages) {
|
|||
<tr><th scope="row"><?php echo translate('Monitor') ?></th><td><?php echo validHtmlStr($event->Monitor()->Name()) ?> (<?php echo $event->MonitorId() ?>)</td></tr>
|
||||
<tr><th scope="row"><?php echo translate('Cause') ?></th><td><?php echo validHtmlStr($event->Cause()) ?></td></tr>
|
||||
<tr><th scope="row"><?php echo translate('Notes') ?></th><td><?php echo validHtmlStr($event->Notes()) ?></td></tr>
|
||||
<tr><th scope="row"><?php echo translate('Time') ?></th><td><?php echo strftime(STRF_FMT_DATETIME_SHORTER, strtotime($event->StartTime())) ?></td></tr>
|
||||
<tr><th scope="row"><?php echo translate('Time') ?></th><td><?php echo strftime(STRF_FMT_DATETIME_SHORTER, strtotime($event->StartDateTime())) ?></td></tr>
|
||||
<tr><th scope="row"><?php echo translate('Duration') ?></th><td><?php echo $event->Length() ?></td></tr>
|
||||
<tr><th scope="row"><?php echo translate('Frames') ?></th><td><?php echo $event->Frames() ?></td></tr>
|
||||
<tr><th scope="row"><?php echo translate('AttrAlarmFrames') ?></th><td><?php echo $event->AlarmFrames() ?></td></tr>
|
||||
|
@ -999,5 +999,5 @@ function exportEvents(
|
|||
unlink($monitorPath.'/'.$html_eventMaster);
|
||||
}
|
||||
|
||||
return '?view=archive%26type='.$exportFormat.'%26connkey='.$connkey;
|
||||
return '?view=archive&type='.$exportFormat.'&connkey='.$connkey;
|
||||
} // end function exportEvents
|
||||
|
|
|
@ -497,9 +497,9 @@ function getBandwidthHTML($bandwidth_options, $user) {
|
|||
}
|
||||
|
||||
$result = '<li id="getBandwidthHTML" class="nav-item dropdown mx-2">'.PHP_EOL;
|
||||
$result .= '<a class="dropdown-toggle mr-2" href="#" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" id="dropdown_bandwidth"><i class="material-icons md-18 mr-1">network_check</i>'.translate($bandwidth_options[$_COOKIE['zmBandwidth']]).'</a>'.PHP_EOL;
|
||||
$result .= '<a class="dropdown-toggle mr-2" href="#" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><i class="material-icons md-18 mr-1">network_check</i>'.translate($bandwidth_options[$_COOKIE['zmBandwidth']]).'</a>'.PHP_EOL;
|
||||
|
||||
$result .= '<div class="dropdown-menu" aria-labelledby="dropdown_bandwidth">'.PHP_EOL;
|
||||
$result .= '<div class="dropdown-menu" id="dropdown_bandwidth" aria-labelledby="dropdown_bandwidth">'.PHP_EOL;
|
||||
if ( count($bandwidth_options) > 1 ) {
|
||||
if ( isset($bandwidth_options['high']) )
|
||||
$result .= '<a data-pdsa-dropdown-val="high" class="dropdown-item" href="#">' .translate('High'). '</a>'.PHP_EOL;
|
||||
|
|
|
@ -830,10 +830,11 @@ function startDownload( exportFile ) {
|
|||
}
|
||||
|
||||
function exportResponse(data, responseText) {
|
||||
console.log(data);
|
||||
console.log('exportResponse data: ' + JSON.stringify(data));
|
||||
|
||||
var generated = (data.result=='Ok') ? 1 : 0;
|
||||
var exportFile = '?view=archive&type='+data.exportFormat+'&connkey='+data.connkey;
|
||||
//var exportFile = '?view=archive&type='+data.exportFormat+'&connkey='+data.connkey;
|
||||
var exportFile = data.exportFile;
|
||||
|
||||
$j('#exportProgress').removeClass( 'text-warning' );
|
||||
if ( generated ) {
|
||||
|
|
|
@ -42,7 +42,7 @@ xhtmlHeaders(__FILE__, translate('ControlCaps'));
|
|||
<button id="deleteBtn" class="btn btn-danger" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Delete') ?>" disabled><i class="fa fa-trash"></i></button>
|
||||
</div>
|
||||
|
||||
<div id="content">
|
||||
<div id="content" class="table-responsive-sm">
|
||||
<table
|
||||
id="controlTable"
|
||||
data-locale="<?php echo i18n() ?>"
|
||||
|
@ -54,7 +54,6 @@ xhtmlHeaders(__FILE__, translate('ControlCaps'));
|
|||
data-remember-order="true"
|
||||
data-click-to-select="true"
|
||||
data-maintain-meta-data="true"
|
||||
data-mobile-responsive="true"
|
||||
data-buttons-class="btn btn-normal"
|
||||
data-toolbar="#toolbar"
|
||||
data-show-columns="true"
|
||||
|
|
|
@ -46,7 +46,7 @@ xhtmlHeaders(__FILE__, translate('Devices') );
|
|||
<button id="deleteBtn" class="btn btn-danger" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Delete') ?>" disabled><i class="fa fa-trash"></i></button>
|
||||
</div>
|
||||
|
||||
<div id="content" class="row justify-content-center">
|
||||
<div id="content" class="row justify-content-center table-responsive-sm">
|
||||
<table
|
||||
id="devicesTable"
|
||||
data-locale="<?php echo i18n() ?>"
|
||||
|
@ -59,7 +59,6 @@ xhtmlHeaders(__FILE__, translate('Devices') );
|
|||
data-remember-order="true"
|
||||
data-click-to-select="true"
|
||||
data-maintain-meta-data="true"
|
||||
data-mobile-responsive="true"
|
||||
data-buttons-class="btn btn-normal"
|
||||
data-toolbar="#toolbar"
|
||||
data-show-columns="true"
|
||||
|
|
|
@ -120,86 +120,113 @@ $filterQuery = $filter->querystring();
|
|||
|
||||
$connkey = generateConnKey();
|
||||
|
||||
$focusWindow = true;
|
||||
|
||||
$popup = (isset($_REQUEST['popup']) && ($_REQUEST['popup'] == 1));
|
||||
|
||||
xhtmlHeaders(__FILE__, translate('Event'));
|
||||
xhtmlHeaders(__FILE__, translate('Event').' '.$Event->Id());
|
||||
?>
|
||||
<body>
|
||||
<div id="page">
|
||||
<?php if ( !$popup ) echo getNavBarHTML() ?>
|
||||
<div id="header">
|
||||
<?php echo getNavBarHTML() ?>
|
||||
<?php
|
||||
if ( !$Event->Id() ) {
|
||||
echo 'Event was not found.';
|
||||
} else {
|
||||
if ( !file_exists($Event->Path()) ) {
|
||||
if ( !file_exists($Event->Path()) )
|
||||
echo '<div class="error">Event was not found at '.$Event->Path().'. It is unlikely that playback will be possible.</div>';
|
||||
}
|
||||
|
||||
$storage = validHtmlStr($Event->Storage()->Name()).( $Event->SecondaryStorageId() ? ', '.validHtmlStr($Event->SecondaryStorage()->Name()) : '' );
|
||||
?>
|
||||
<div id="dataBar">
|
||||
<span id="dataId" title="<?php echo translate('Id') ?>"><?php echo $Event->Id() ?></span>
|
||||
<span id="dataMonitor" title="<?php echo translate('Monitor') ?>"><?php echo $Monitor->Id().' '.validHtmlStr($Monitor->Name()) ?></span>
|
||||
<span id="dataCause" title="<?php echo $Event->Notes()?validHtmlStr($Event->Notes()):translate('AttrCause') ?>"><?php echo validHtmlStr($Event->Cause()) ?></span>
|
||||
<span id="dataTime" title="<?php echo translate('Time') ?>"><?php echo strftime(STRF_FMT_DATETIME_SHORT, strtotime($Event->StartDateTime())) ?></span>
|
||||
<span id="dataDuration" title="<?php echo translate('Duration') ?>"><?php echo $Event->Length().'s' ?></span>
|
||||
<span id="dataFrames" title="<?php echo translate('AttrFrames').'/'.translate('AttrAlarmFrames') ?>"><?php echo $Event->Frames() ?>/<?php echo $Event->AlarmFrames() ?></span>
|
||||
<span id="dataScore" title="<?php echo translate('AttrTotalScore').'/'.translate('AttrAvgScore').'/'.translate('AttrMaxScore') ?>"><?php echo $Event->TotScore() ?>/<?php echo $Event->AvgScore() ?>/<?php echo $Event->MaxScore() ?></span>
|
||||
<span id="Storage">
|
||||
<?php echo
|
||||
human_filesize($Event->DiskSpace(null)) . ' on ' . validHtmlStr($Event->Storage()->Name()).
|
||||
( $Event->SecondaryStorageId() ? ', '.validHtmlStr($Event->SecondaryStorage()->Name()) : '' )
|
||||
?></span>
|
||||
<div id="closeWindow"><a href="#" data-on-click="<?php echo $popup ? 'closeWindow' : 'backWindow' ?>"><?php echo $popup ? translate('Close') : translate('Back') ?></a></div>
|
||||
|
||||
<!-- BEGIN HEADER -->
|
||||
<div class="d-flex flex-row justify-content-between px-3 py-1">
|
||||
<div id="toolbar" >
|
||||
<button id="backBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Back') ?>" disabled><i class="fa fa-arrow-left"></i></button>
|
||||
<button id="refreshBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Refresh') ?>" ><i class="fa fa-refresh"></i></button>
|
||||
<button id="renameBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Rename') ?>" disabled><i class="fa fa-font"></i></button>
|
||||
<button id="archiveBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Archive') ?>" disabled><i class="fa fa-archive"></i></button>
|
||||
<button id="unarchiveBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Unarchive') ?>" disabled><i class="fa fa-file-archive-o"></i></button>
|
||||
<button id="editBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Edit') ?>" disabled><i class="fa fa-pencil"></i></button>
|
||||
<button id="exportBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Export') ?>"><i class="fa fa-external-link"></i></button>
|
||||
<button id="downloadBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('DownloadVideo') ?>"><i class="fa fa-download"></i></button>
|
||||
<button id="statsBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Stats') ?>" ><i class="fa fa-info"></i></button>
|
||||
<button id="deleteBtn" class="btn btn-danger" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Delete') ?>"><i class="fa fa-trash"></i></button>
|
||||
</div>
|
||||
<div id="menuBar1">
|
||||
<div id="nameControl">
|
||||
<input type="text" id="eventName" name="eventName" value="<?php echo validHtmlStr($Event->Name()) ?>" />
|
||||
<button value="Rename" type="button" data-on-click="renameEvent"<?php if ( !canEdit('Events') ) { ?> disabled="disabled"<?php } ?>>
|
||||
<?php echo translate('Rename') ?></button>
|
||||
</div>
|
||||
<?php
|
||||
if ( canEdit('Events') ) {
|
||||
?>
|
||||
<div id="deleteEvent"><button type="button" data-on-click="deleteEvent" <?php echo $Event->can_delete() ? '' : ' disabled="disabled" title="'.$Event->cant_delete_reason().'"' ?>><?php echo translate('Delete') ?></button></div>
|
||||
<div id="editEvent"><button type="button" data-on-click="editEvent"><?php echo translate('Edit') ?></button></div>
|
||||
<div id="archiveEvent"<?php echo $Event->Archived() == 1 ? ' class="hidden"' : '' ?>><button type="button" data-on-click="archiveEvent"><?php echo translate('Archive') ?></button></div>
|
||||
<div id="unarchiveEvent"<?php echo $Event->Archived() == 0 ? ' class="hidden"' : '' ?>><button type="button" data-on-click="unarchiveEvent"><?php echo translate('Unarchive') ?></button></div>
|
||||
<?php
|
||||
} // end if can edit Events
|
||||
?>
|
||||
<div id="framesEvent"><button type="button" data-on-click="showEventFrames"><?php echo translate('Frames') ?></button></div>
|
||||
<div id="streamEvent" class="hidden"><button data-on-click="showStream"><?php echo translate('Stream') ?></button></div>
|
||||
<div id="stillsEvent"><button type="button" data-on-click="showStills"><?php echo translate('Stills') ?></button></div>
|
||||
<?php
|
||||
if ( $Event->DefaultVideo() ) {
|
||||
?>
|
||||
<div id="downloadEventFile"><a class="btn-primary" href="<?php echo $Event->getStreamSrc(array('mode'=>'mp4'),'&')?>" download>Download MP4</a></div>
|
||||
<?php
|
||||
} else {
|
||||
?>
|
||||
<div id="videoEvent"><button type="button" data-on-click="videoEvent"><?php echo translate('Video') ?></button></div>
|
||||
<?php
|
||||
} // end if Event->DefaultVideo
|
||||
?>
|
||||
<div id="exportEvent"><button type="button" data-on-click="exportEvent"><?php echo translate('Export') ?></button></div>
|
||||
<div id="replayControl">
|
||||
<label for="replayMode"><?php echo translate('Replay') ?></label>
|
||||
<?php echo htmlSelect('replayMode', $replayModes, $replayMode, array('data-on-change'=>'changeReplayMode','id'=>'replayMode')); ?>
|
||||
</div>
|
||||
<div id="scaleControl">
|
||||
<label for="scale"><?php echo translate('Scale') ?></label>
|
||||
<?php echo htmlSelect('scale', $scales, $scale, array('data-on-change'=>'changeScale','id'=>'scale')); ?>
|
||||
</div>
|
||||
<div id="codecControl">
|
||||
<label for="codec"><?php echo translate('Codec') ?></label>
|
||||
<?php echo htmlSelect('codec', $codecs, $codec, array('data-on-change'=>'changeCodec','id'=>'codec')); ?>
|
||||
</div>
|
||||
|
||||
<h2><?php echo translate('Event').' '.$Event->Id() ?></h2>
|
||||
|
||||
<div class="d-flex flex-row">
|
||||
<div id="replayControl"><label for="replayMode"><?php echo translate('Replay') ?></label><?php echo htmlSelect('replayMode', $replayModes, $replayMode, array('data-on-change'=>'changeReplayMode','id'=>'replayMode')); ?></div>
|
||||
<div id="scaleControl"><label for="scale"><?php echo translate('Scale') ?></label><?php echo htmlSelect('scale', $scales, $scale, array('data-on-change'=>'changeScale','id'=>'scale')); ?></div>
|
||||
<div id="codecControl"><label for="codec"><?php echo translate('Codec') ?></label><?php echo htmlSelect('codec', $codecs, $codec, array('data-on-change'=>'changeCodec','id'=>'codec')); ?></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="content">
|
||||
|
||||
<!-- BEGIN VIDEO CONTENT ROW -->
|
||||
<div id="content" class="d-flex flex-row justify-content-center">
|
||||
<div class="">
|
||||
<!-- VIDEO STATISTICS TABLE -->
|
||||
<table id="eventStatsTable" class="table-sm table-borderless">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th class="text-right"><?php echo translate('EventId') ?></th>
|
||||
<td id="dataEventId"><?php echo $Event->Id() ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="text-right"><?php echo translate('EventName') ?></th>
|
||||
<td id="dataEventName"><?php echo $Event->Name() ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="text-right"><?php echo translate('AttrMonitorId') ?></th>
|
||||
<td id="dataMonitorId"><?php echo $Monitor->Id() ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="text-right"><?php echo translate('AttrMonitorName') ?></th>
|
||||
<td id="dataMonitorName"><?php echo validHtmlStr($Monitor->Name()) ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="text-right"><?php echo translate('Cause') ?></th>
|
||||
<td id="dataCause"><?php echo validHtmlStr($Event->Cause()) ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="text-right"><?php echo translate('AttrStartTime') ?></th>
|
||||
<td id="dataStartTime"><?php echo strftime(STRF_FMT_DATETIME_SHORT, strtotime($Event->StartDateTime())) ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="text-right"><?php echo translate('Duration') ?></th>
|
||||
<td id="dataDuration"><?php echo $Event->Length().'s' ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="text-right"><?php echo translate('AttrFrames') ?></th>
|
||||
<td id="dataFrames"><?php echo $Event->Frames() ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="text-right"><?php echo translate('AttrAlarmFrames') ?></th>
|
||||
<td id="dataAlarmFrames"><?php echo $Event->AlarmFrames() ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="text-right"><?php echo translate('AttrTotalScore') ?></th>
|
||||
<td id="dataTotalScore"><?php echo $Event->TotScore() ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="text-right"><?php echo translate('AttrAvgScore') ?></th>
|
||||
<td id="dataAvgScore"><?php echo $Event->AvgScore() ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="text-right"><?php echo translate('AttrMaxScore') ?></th>
|
||||
<td id="dataMaxScore"><?php echo $Event->MaxScore() ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="text-right"><?php echo translate('DiskSpace') ?></th>
|
||||
<td id="dataDiskSpace"><?php echo human_filesize($Event->DiskSpace(null)) ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="text-right"><?php echo translate('Storage') ?></th>
|
||||
<td id="dataStorage"><?php echo $storage?></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="">
|
||||
<div id="eventVideo">
|
||||
<!-- VIDEO CONTENT -->
|
||||
<?php
|
||||
if ( ($codec == 'MP4' || $codec == 'auto' ) && $Event->DefaultVideo() ) {
|
||||
?>
|
||||
|
@ -322,6 +349,8 @@ echo htmlSelect('rate', $rates, intval($rate), array('id'=>'rateValue'));
|
|||
<?php
|
||||
} // end if Event exists
|
||||
?>
|
||||
</div>
|
||||
</div><!--content-->
|
||||
|
||||
</div><!--page-->
|
||||
<?php xhtmlFooter() ?>
|
||||
|
|
|
@ -65,7 +65,7 @@ getBodyTopHTML();
|
|||
</div>
|
||||
|
||||
<!-- Table styling handled by bootstrap-tables -->
|
||||
<div class="row justify-content-center">
|
||||
<div class="row justify-content-center table-responsive-sm">
|
||||
<table
|
||||
id="eventTable"
|
||||
data-locale="<?php echo i18n() ?>"
|
||||
|
@ -87,7 +87,6 @@ getBodyTopHTML();
|
|||
data-show-fullscreen="true"
|
||||
data-click-to-select="true"
|
||||
data-maintain-meta-data="true"
|
||||
data-mobile-responsive="true"
|
||||
data-buttons-class="btn btn-normal"
|
||||
data-show-jump-to="true"
|
||||
data-show-refresh="true"
|
||||
|
|
|
@ -41,7 +41,7 @@ xhtmlHeaders(__FILE__, translate('Frames').' - '.$Event->Id());
|
|||
</div>
|
||||
|
||||
<!-- Table styling handled by bootstrap-tables -->
|
||||
<div class="row justify-content-center">
|
||||
<div class="row justify-content-center table-responsive-sm">
|
||||
<table
|
||||
id="framesTable"
|
||||
data-locale="<?php echo i18n() ?>"
|
||||
|
@ -60,7 +60,6 @@ xhtmlHeaders(__FILE__, translate('Frames').' - '.$Event->Id());
|
|||
data-toolbar="#toolbar"
|
||||
data-show-fullscreen="true"
|
||||
data-maintain-meta-data="true"
|
||||
data-mobile-responsive="true"
|
||||
data-buttons-class="btn btn-normal"
|
||||
data-detail-view="true"
|
||||
data-detail-formatter="detailFormatter"
|
||||
|
|
|
@ -1,7 +1,40 @@
|
|||
$j.ajaxSetup({timeout: AJAX_TIMEOUT}); //sets timeout for all getJSON.
|
||||
var table = $j('#eventStatsTable');
|
||||
var backBtn = $j('#backBtn');
|
||||
var renameBtn = $j('#renameBtn');
|
||||
var archiveBtn = $j('#archiveBtn');
|
||||
var unarchiveBtn = $j('#unarchiveBtn');
|
||||
var editBtn = $j('#editBtn');
|
||||
var exportBtn = $j('#exportBtn');
|
||||
var downloadBtn = $j('#downloadBtn');
|
||||
var deleteBtn = $j('#deleteBtn');
|
||||
var prevEventId = 0;
|
||||
var nextEventId = 0;
|
||||
var prevEventStartTime = 0;
|
||||
var nextEventStartTime = 0;
|
||||
var PrevEventDefVideoPath = "";
|
||||
var NextEventDefVideoPath = "";
|
||||
var slider = null;
|
||||
var scroll = null;
|
||||
var currEventId = null;
|
||||
var CurEventDefVideoPath = null;
|
||||
var vid = null;
|
||||
var spf = Math.round((eventData.Length / eventData.Frames)*1000000 )/1000000;//Seconds per frame for videojs frame by frame.
|
||||
var intervalRewind;
|
||||
var revSpeed = .5;
|
||||
var cueFrames = null; //make cueFrames available even if we don't send another ajax query
|
||||
var streamCmdTimer = null;
|
||||
var streamStatus = null;
|
||||
var lastEventId = 0;
|
||||
var zmsBroke = false; //Use alternate navigation if zms has crashed
|
||||
var streamParms = "view=request&request=stream&connkey="+connKey;
|
||||
if ( auth_hash ) streamParms += '&auth='+auth_hash;
|
||||
var frameBatch = 40;
|
||||
var currFrameId = null;
|
||||
var eventReq = new Request.JSON( {url: thisUrl, method: 'get', timeout: AJAX_TIMEOUT, link: 'cancel', onSuccess: getEventResponse} );
|
||||
var actReq = new Request.JSON( {url: thisUrl, method: 'get', timeout: AJAX_TIMEOUT, link: 'cancel', onSuccess: getActResponse} );
|
||||
var frameReq = new Request.JSON( {url: thisUrl, method: 'get', timeout: AJAX_TIMEOUT, link: 'chain', onSuccess: getFrameResponse} );
|
||||
var streamReq = new Request.JSON( {url: monitorUrl, method: 'get', timeout: AJAX_TIMEOUT, link: 'chain', onSuccess: getCmdResponse} );
|
||||
|
||||
// Function called when video.js hits the end of the video
|
||||
function vjsReplay() {
|
||||
|
@ -44,10 +77,6 @@ function vjsReplay() {
|
|||
}
|
||||
} // end function vjsReplay
|
||||
|
||||
$j.ajaxSetup({timeout: AJAX_TIMEOUT}); //sets timeout for all getJSON.
|
||||
|
||||
var cueFrames = null; //make cueFrames available even if we don't send another ajax query
|
||||
|
||||
function initialAlarmCues(eventId) {
|
||||
$j.getJSON(thisUrl + '?view=request&request=status&entity=frames&id=' + eventId, setAlarmCues) //get frames data for alarmCues and inserts into html
|
||||
.fail(logAjaxFail);
|
||||
|
@ -134,7 +163,6 @@ function renderAlarmCues(containerEl) {
|
|||
return alarmHtml;
|
||||
}
|
||||
|
||||
|
||||
function changeCodec() {
|
||||
location.replace(thisUrl + '?view=event&eid=' + eventData.Id + filterQuery + sortQuery+'&codec='+$j('#codec').val());
|
||||
}
|
||||
|
@ -217,16 +245,6 @@ function changeRate() {
|
|||
Cookie.write('zmEventRate', rate, {duration: 10*365, samesite: 'strict'});
|
||||
} // end function changeRate
|
||||
|
||||
var streamParms = "view=request&request=stream&connkey="+connKey;
|
||||
if ( auth_hash ) {
|
||||
streamParms += '&auth='+auth_hash;
|
||||
}
|
||||
var streamCmdTimer = null;
|
||||
|
||||
var streamStatus = null;
|
||||
var lastEventId = 0;
|
||||
var zmsBroke = false; //Use alternate navigation if zms has crashed
|
||||
|
||||
function getCmdResponse( respObj, respText ) {
|
||||
if ( checkStreamForErrors('getCmdResponse', respObj) ) {
|
||||
console.log('Got an error from getCmdResponse');
|
||||
|
@ -291,14 +309,6 @@ function getCmdResponse( respObj, respText ) {
|
|||
streamCmdTimer = streamQuery.delay(streamTimeout); //Timeout is refresh rate for progressBox and time display
|
||||
} // end function getCmdResponse( respObj, respText )
|
||||
|
||||
var streamReq = new Request.JSON( {
|
||||
url: monitorUrl,
|
||||
method: 'get',
|
||||
timeout: AJAX_TIMEOUT,
|
||||
link: 'chain',
|
||||
onSuccess: getCmdResponse
|
||||
} );
|
||||
|
||||
function pauseClicked() {
|
||||
if ( vid ) {
|
||||
if ( intervalRewind ) {
|
||||
|
@ -553,11 +563,6 @@ function streamQuery() {
|
|||
streamReq.send( streamParms+"&command="+CMD_QUERY );
|
||||
}
|
||||
|
||||
var slider = null;
|
||||
var scroll = null;
|
||||
var currEventId = null;
|
||||
var CurEventDefVideoPath = null;
|
||||
|
||||
function getEventResponse(respObj, respText) {
|
||||
if ( checkStreamForErrors('getEventResponse', respObj) ) {
|
||||
console.log('getEventResponse: errors');
|
||||
|
@ -572,28 +577,31 @@ function getEventResponse(respObj, respText) {
|
|||
}
|
||||
currEventId = eventData.Id;
|
||||
|
||||
$('dataId').set( 'text', eventData.Id );
|
||||
$j('#dataEventId').text( eventData.Id );
|
||||
$j('#dataEventName').text( eventData.Name );
|
||||
$j('#dataMonitorId').text( eventData.MonitorId );
|
||||
$j('#dataMonitorName').text( eventData.MonitorName );
|
||||
$j('#dataCause').text( eventData.Cause );
|
||||
if ( eventData.Notes ) {
|
||||
$('dataCause').setProperty( 'title', eventData.Notes );
|
||||
$j('#dataCause').prop( 'title', eventData.Notes );
|
||||
} else {
|
||||
$('dataCause').setProperty( 'title', causeString );
|
||||
}
|
||||
$('dataCause').set( 'text', eventData.Cause );
|
||||
$('dataTime').set( 'text', eventData.StartDateTime );
|
||||
$('dataDuration').set( 'text', eventData.Length );
|
||||
$('dataFrames').set( 'text', eventData.Frames+"/"+eventData.AlarmFrames );
|
||||
$('dataScore').set( 'text', eventData.TotScore+"/"+eventData.AvgScore+"/"+eventData.MaxScore );
|
||||
$('eventName').setProperty( 'value', eventData.Name );
|
||||
history.replaceState(null, null, '?view=event&eid=' + eventData.Id + filterQuery + sortQuery);//if popup removed, check if this allows forward
|
||||
if ( canEditEvents ) {
|
||||
if ( parseInt(eventData.Archived) ) {
|
||||
$('archiveEvent').addClass( 'hidden' );
|
||||
$('unarchiveEvent').removeClass( 'hidden' );
|
||||
} else {
|
||||
$('archiveEvent').removeClass( 'hidden' );
|
||||
$('unarchiveEvent').addClass( 'hidden' );
|
||||
}
|
||||
$j('#dataCause').prop( 'title', causeString );
|
||||
}
|
||||
$j('#dataStartTime').text( eventData.StartDateTime );
|
||||
$j('#dataDuration').text( eventData.Length );
|
||||
$j('#dataFrames').text( eventData.Frames );
|
||||
$j('#dataAlarmFrames').text( eventData.AlarmFrames );
|
||||
$j('dataTotalScore').text( eventData.TotScore );
|
||||
$j('dataAvgScore').text( eventData.AvgScore );
|
||||
$j('dataMaxScore').text( eventData.MaxScore );
|
||||
$j('dataDiskSpace').text( eventData.DiskSpace );
|
||||
$j('dataStorage').text( eventData.Storage );
|
||||
|
||||
// Refresh the status of the archive buttons
|
||||
archiveBtn.prop('disabled', !(!eventData.Archived && canEditEvents));
|
||||
unarchiveBtn.prop('disabled', !(eventData.Archived && canEditEvents));
|
||||
|
||||
history.replaceState(null, null, '?view=event&eid=' + eventData.Id + filterQuery + sortQuery); //if popup removed, check if this allows forward
|
||||
// Technically, events can be different sizes, so may need to update the size of the image, but it might be better to have it stay scaled...
|
||||
//var eventImg = $('eventImage');
|
||||
//eventImg.setStyles( { 'width': eventData.width, 'height': eventData.height } );
|
||||
|
@ -613,8 +621,6 @@ function getEventResponse(respObj, respText) {
|
|||
nearEventsQuery( eventData.Id );
|
||||
} // end function getEventResponse
|
||||
|
||||
var eventReq = new Request.JSON( {url: thisUrl, method: 'get', timeout: AJAX_TIMEOUT, link: 'cancel', onSuccess: getEventResponse} );
|
||||
|
||||
function eventQuery( eventId ) {
|
||||
var eventParms = 'view=request&request=status&entity=event&id='+eventId;
|
||||
if ( auth_hash ) {
|
||||
|
@ -623,13 +629,6 @@ function eventQuery( eventId ) {
|
|||
eventReq.send( eventParms );
|
||||
}
|
||||
|
||||
var prevEventId = 0;
|
||||
var nextEventId = 0;
|
||||
var prevEventStartTime = 0;
|
||||
var nextEventStartTime = 0;
|
||||
var PrevEventDefVideoPath = "";
|
||||
var NextEventDefVideoPath = "";
|
||||
|
||||
function getNearEventsResponse( respObj, respText ) {
|
||||
if ( checkStreamForErrors('getNearEventsResponse', respObj) ) {
|
||||
return;
|
||||
|
@ -656,8 +655,6 @@ function nearEventsQuery( eventId ) {
|
|||
nearEventsReq.send( parms );
|
||||
}
|
||||
|
||||
var frameBatch = 40;
|
||||
|
||||
function loadEventThumb( event, frame, loadImage ) {
|
||||
var thumbImg = $('eventThumb'+frame.FrameId);
|
||||
if ( !thumbImg ) {
|
||||
|
@ -789,15 +786,11 @@ function getFrameResponse(respObj, respText) {
|
|||
loadEventThumb(eventData, frame, respObj.loopback=="true");
|
||||
}
|
||||
|
||||
var frameReq = new Request.JSON( {url: thisUrl, method: 'get', timeout: AJAX_TIMEOUT, link: 'chain', onSuccess: getFrameResponse} );
|
||||
|
||||
function frameQuery( eventId, frameId, loadImage ) {
|
||||
var parms = "view=request&request=status&entity=frameimage&id[0]="+eventId+"&id[1]="+frameId+"&loopback="+loadImage;
|
||||
frameReq.send(parms);
|
||||
}
|
||||
|
||||
var currFrameId = null;
|
||||
|
||||
function checkFrames( eventId, frameId, loadImage ) {
|
||||
if ( !eventData ) {
|
||||
console.error("No event "+eventId+" found");
|
||||
|
@ -917,8 +910,6 @@ function getActResponse( respObj, respText ) {
|
|||
}
|
||||
}
|
||||
|
||||
var actReq = new Request.JSON( {url: thisUrl, method: 'get', timeout: AJAX_TIMEOUT, link: 'cancel', onSuccess: getActResponse} );
|
||||
|
||||
function actQuery(action, parms) {
|
||||
var actParms = "view=request&request=event&id="+eventData.Id+"&action="+action;
|
||||
if ( auth_hash ) {
|
||||
|
@ -930,55 +921,17 @@ function actQuery(action, parms) {
|
|||
actReq.send(actParms);
|
||||
}
|
||||
|
||||
function deleteEvent() {
|
||||
pauseClicked(); //Provides visual feedback that your click happened.
|
||||
|
||||
var deleteReq = new Request.JSON({
|
||||
url: thisUrl,
|
||||
method: 'post',
|
||||
timeout: AJAX_TIMEOUT,
|
||||
onSuccess: function onDeleteSuccess(respObj, respText) {
|
||||
getActResponse(respObj, respText);
|
||||
// We must wait for the deletion to happen before navigating to the next
|
||||
// event or this request will be cancelled.
|
||||
streamNext(true);
|
||||
},
|
||||
});
|
||||
deleteReq.send("view=request&request=event&id="+eventData.Id+"&action=delete");
|
||||
}
|
||||
|
||||
function renameEvent() {
|
||||
var newName = $('eventName').get('value');
|
||||
var newName = $j('input').val();
|
||||
actQuery('rename', {eventName: newName});
|
||||
}
|
||||
|
||||
// Manage the EDIT button
|
||||
function editEvent() {
|
||||
$j.getJSON(thisUrl + '?request=modal&modal=eventdetail&eid='+eventData.Id)
|
||||
.done(function(data) {
|
||||
insertModalHtml('eventDetailModal', data.html);
|
||||
$j('#eventDetailModal').modal('show');
|
||||
// Manage the Save button
|
||||
$j('#eventDetailSaveBtn').click(function(evt) {
|
||||
evt.preventDefault();
|
||||
$j('#eventDetailForm').submit();
|
||||
});
|
||||
})
|
||||
.fail(logAjaxFail);
|
||||
//FIXME: update the value of the event name rather than reload the whole page
|
||||
window.location.reload(true);
|
||||
}
|
||||
|
||||
function exportEvent() {
|
||||
window.location.assign('?view=export&eid='+eventData.Id);
|
||||
}
|
||||
|
||||
function archiveEvent() {
|
||||
actQuery('archive');
|
||||
}
|
||||
|
||||
function unarchiveEvent() {
|
||||
actQuery('unarchive');
|
||||
}
|
||||
|
||||
function showEventFrames() {
|
||||
window.location.assign('?view=frames&eid='+eventData.Id);
|
||||
}
|
||||
|
@ -1079,7 +1032,56 @@ function handleClick( event ) {
|
|||
}
|
||||
}
|
||||
|
||||
// Load the Delete Confirmation Modal HTML via Ajax call
|
||||
function getDelConfirmModal() {
|
||||
$j.getJSON(thisUrl + '?request=modal&modal=delconfirm')
|
||||
.done(function(data) {
|
||||
insertModalHtml('deleteConfirm', data.html);
|
||||
manageDelConfirmModalBtns();
|
||||
})
|
||||
.fail(logAjaxFail);
|
||||
}
|
||||
|
||||
// Manage the DELETE CONFIRMATION modal button
|
||||
function manageDelConfirmModalBtns() {
|
||||
document.getElementById("delConfirmBtn").addEventListener("click", function onDelConfirmClick(evt) {
|
||||
if ( ! canEditEvents ) {
|
||||
enoperm();
|
||||
return;
|
||||
}
|
||||
|
||||
evt.preventDefault();
|
||||
$j.getJSON(thisUrl + '?request=events&task=delete&eids[]='+eventData.Id)
|
||||
.done( function(data) {
|
||||
streamNext( true );
|
||||
})
|
||||
.fail(logAjaxFail);
|
||||
});
|
||||
|
||||
// Manage the CANCEL modal button
|
||||
document.getElementById("delCancelBtn").addEventListener("click", function onDelCancelClick(evt) {
|
||||
$j('#deleteConfirm').modal('hide');
|
||||
});
|
||||
}
|
||||
|
||||
function getEvtStatsCookie() {
|
||||
var cookie = 'zmEventStats';
|
||||
var stats = getCookie(cookie);
|
||||
|
||||
if ( !stats ) {
|
||||
stats = 'on';
|
||||
setCookie(cookie, stats, 10*365);
|
||||
}
|
||||
return stats;
|
||||
}
|
||||
|
||||
function initPage() {
|
||||
// Load the delete confirmation modal into the DOM
|
||||
getDelConfirmModal();
|
||||
|
||||
var stats = getEvtStatsCookie();
|
||||
if ( stats != 'on' ) table.toggle(false);
|
||||
|
||||
//FIXME prevent blocking...not sure what is happening or best way to unblock
|
||||
if ( $j('#videoobj').length ) {
|
||||
vid = videojs('videoobj');
|
||||
|
@ -1130,7 +1132,136 @@ function initPage() {
|
|||
document.querySelectorAll('select[name="rate"]').forEach(function(el) {
|
||||
el.onchange = window['changeRate'];
|
||||
});
|
||||
|
||||
// enable or disable buttons based on current selection and user rights
|
||||
renameBtn.prop('disabled', !canEditEvents);
|
||||
archiveBtn.prop('disabled', !(!eventData.Archived && canEditEvents));
|
||||
unarchiveBtn.prop('disabled', !(eventData.Archived && canEditEvents));
|
||||
editBtn.prop('disabled', !canEditEvents);
|
||||
exportBtn.prop('disabled', !canViewEvents);
|
||||
downloadBtn.prop('disabled', !canViewEvents);
|
||||
deleteBtn.prop('disabled', !canEditEvents);
|
||||
|
||||
// Don't enable the back button if there is no previous zm page to go back to
|
||||
backBtn.prop('disabled', !document.referrer.length);
|
||||
|
||||
// Manage the BACK button
|
||||
document.getElementById("backBtn").addEventListener("click", function onBackClick(evt) {
|
||||
evt.preventDefault();
|
||||
window.history.back();
|
||||
});
|
||||
|
||||
// Manage the REFRESH Button
|
||||
document.getElementById("refreshBtn").addEventListener("click", function onRefreshClick(evt) {
|
||||
evt.preventDefault();
|
||||
window.location.reload(true);
|
||||
});
|
||||
|
||||
// Manage the Event RENAME button
|
||||
document.getElementById("renameBtn").addEventListener("click", function onDownloadClick(evt) {
|
||||
evt.preventDefault();
|
||||
$j.getJSON(thisUrl + '?request=modal&modal=eventrename&eid='+eventData.Id)
|
||||
.done(function(data) {
|
||||
insertModalHtml('eventRenameModal', data.html);
|
||||
$j('#eventRenameModal').modal('show');
|
||||
// Manage the SAVE button
|
||||
$j('#eventRenameBtn').click(renameEvent);
|
||||
})
|
||||
.fail(logAjaxFail);
|
||||
});
|
||||
|
||||
// Manage the ARCHIVE button
|
||||
document.getElementById("archiveBtn").addEventListener("click", function onArchiveClick(evt) {
|
||||
evt.preventDefault();
|
||||
$j.getJSON(thisUrl + '?request=events&task=archive&eids[]='+eventData.Id)
|
||||
.done( function(data) {
|
||||
//FIXME: update the status of the archive button reather than reload the whole page
|
||||
window.location.reload(true);
|
||||
})
|
||||
.fail(logAjaxFail);
|
||||
});
|
||||
|
||||
// Manage the UNARCHIVE button
|
||||
document.getElementById("unarchiveBtn").addEventListener("click", function onUnarchiveClick(evt) {
|
||||
if ( ! canEditEvents ) {
|
||||
enoperm();
|
||||
return;
|
||||
}
|
||||
evt.preventDefault();
|
||||
$j.getJSON(thisUrl + '?request=events&task=unarchive&eids[]='+eventData.Id)
|
||||
.done( function(data) {
|
||||
//FIXME: update the status of the unarchive button reather than reload the whole page
|
||||
window.location.reload(true);
|
||||
})
|
||||
.fail(logAjaxFail);
|
||||
});
|
||||
|
||||
// Manage the EDIT button
|
||||
document.getElementById("editBtn").addEventListener("click", function onEditClick(evt) {
|
||||
if ( ! canEditEvents ) {
|
||||
enoperm();
|
||||
return;
|
||||
}
|
||||
|
||||
evt.preventDefault();
|
||||
$j.getJSON(thisUrl + '?request=modal&modal=eventdetail&eids[]='+eventData.Id)
|
||||
.done(function(data) {
|
||||
insertModalHtml('eventDetailModal', data.html);
|
||||
$j('#eventDetailModal').modal('show');
|
||||
// Manage the Save button
|
||||
$j('#eventDetailSaveBtn').click(function(evt) {
|
||||
evt.preventDefault();
|
||||
$j('#eventDetailForm').submit();
|
||||
});
|
||||
})
|
||||
.fail(logAjaxFail);
|
||||
});
|
||||
|
||||
// Manage the EXPORT button
|
||||
document.getElementById("exportBtn").addEventListener("click", function onExportClick(evt) {
|
||||
evt.preventDefault();
|
||||
window.location.assign('?view=export&eids[]='+eventData.Id);
|
||||
});
|
||||
|
||||
// Manage the DOWNLOAD VIDEO button
|
||||
document.getElementById("downloadBtn").addEventListener("click", function onDownloadClick(evt) {
|
||||
evt.preventDefault();
|
||||
$j.getJSON(thisUrl + '?request=modal&modal=download&eids[]='+eventData.Id)
|
||||
.done(function(data) {
|
||||
insertModalHtml('downloadModal', data.html);
|
||||
$j('#downloadModal').modal('show');
|
||||
// Manage the GENERATE DOWNLOAD button
|
||||
$j('#exportButton').click(exportEvent);
|
||||
})
|
||||
.fail(logAjaxFail);
|
||||
});
|
||||
|
||||
// Manage the Event STATISTICS Button
|
||||
document.getElementById("statsBtn").addEventListener("click", function onStatsClick(evt) {
|
||||
evt.preventDefault();
|
||||
var cookie = 'zmEventStats';
|
||||
|
||||
// Toggle the visiblity of the stats table and write an appropriate cookie
|
||||
if ( table.is(':visible') ) {
|
||||
setCookie(cookie, 'off', 10*365);
|
||||
table.toggle(false);
|
||||
} else {
|
||||
setCookie(cookie, 'on', 10*365);
|
||||
table.toggle(true);
|
||||
}
|
||||
});
|
||||
|
||||
// Manage the DELETE button
|
||||
document.getElementById("deleteBtn").addEventListener("click", function onDeleteClick(evt) {
|
||||
if ( ! canEditEvents ) {
|
||||
enoperm();
|
||||
return;
|
||||
}
|
||||
|
||||
evt.preventDefault();
|
||||
$j('#deleteConfirm').modal('show');
|
||||
});
|
||||
}
|
||||
|
||||
// Kick everything off
|
||||
window.addEventListener('DOMContentLoaded', initPage);
|
||||
$j(document).ready(initPage);
|
||||
|
|
|
@ -40,6 +40,7 @@ var connKey = '<?php echo $connkey ?>';
|
|||
|
||||
var eventData = {
|
||||
Id: '<?php echo $Event->Id() ?>',
|
||||
Name: '<?php echo $Event->Name() ?>',
|
||||
MonitorId: '<?php echo $Event->MonitorId() ?>',
|
||||
Width: '<?php echo $Event->Width() ?>',
|
||||
Height: '<?php echo $Event->Height() ?>',
|
||||
|
@ -47,7 +48,10 @@ var eventData = {
|
|||
StartDateTime: '<?php echo $Event->StartDateTime() ?>',
|
||||
EndDateTime: '<?php echo $Event->EndDateTime() ?>',
|
||||
Frames: '<?php echo $Event->Frames() ?>',
|
||||
MonitorName: '<?php echo validJsStr($Monitor->Name()) ?>'
|
||||
MonitorName: '<?php echo validJsStr($Monitor->Name()) ?>',
|
||||
DiskSpace: '<?php echo human_filesize($Event->DiskSpace(null)) ?>',
|
||||
Storage: '<?php validHtmlStr($Event->Storage()->Name()).( $Event->SecondaryStorageId() ? ', '.validHtmlStr($Event->SecondaryStorage()->Name()) : '' ) ?>',
|
||||
Archived: <?php echo $Event->Archived?'true':'false' ?>
|
||||
};
|
||||
var monitorUrl = '<?php echo $Event->Storage()->Server()->UrlToIndex(); ?>';
|
||||
|
||||
|
|
|
@ -31,11 +31,11 @@ function startDownload(file) {
|
|||
|
||||
function exportProgress() {
|
||||
if ( exportTimer ) {
|
||||
var tickerText = $('exportProgressTicker').get('text');
|
||||
var tickerText = $j('#exportProgressTicker').text();
|
||||
if ( tickerText.length < 1 || tickerText.length > 4 ) {
|
||||
$('exportProgressTicker').set('text', '.');
|
||||
$j('#exportProgressTicker').text('.');
|
||||
} else {
|
||||
$('exportProgressTicker').appendText('.');
|
||||
$j('#exportProgressTicker').append('.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -43,9 +43,9 @@ function exportProgress() {
|
|||
function exportResponse(respObj, respText) {
|
||||
clearInterval(exportTimer);
|
||||
if ( respObj.result != 'Ok' ) {
|
||||
$('exportProgressTicker').set('text', respObj.message);
|
||||
$j('#exportProgressTicker').text(respObj.message);
|
||||
} else {
|
||||
$('exportProgressTicker').set('text', exportSucceededString);
|
||||
$j('#exportProgressTicker').text(exportSucceededString);
|
||||
startDownload.pass(decodeURIComponent(respObj.exportFile)).delay(1500);
|
||||
}
|
||||
return;
|
||||
|
|
|
@ -7,6 +7,7 @@ var settingsBtn = $j('#settingsBtn');
|
|||
var enableAlmBtn = $j('#enableAlmBtn');
|
||||
var forceAlmBtn = $j('#forceAlmBtn');
|
||||
var table = $j('#eventList');
|
||||
var filterQuery = '&filter[Query][terms][0][attr]=MonitorId&filter[Query][terms][0][op]=%3d&filter[Query][terms][0][val]='+monitorId;
|
||||
|
||||
if ( monitorType != 'WebSite' ) {
|
||||
var streamCmdParms = 'view=request&request=stream&connkey='+connKey;
|
||||
|
@ -52,17 +53,14 @@ var params =
|
|||
|
||||
// Called by bootstrap-table to retrieve zm event data
|
||||
function ajaxRequest(params) {
|
||||
// Maintain legacy behavior of sorting by Id column only
|
||||
delete params.data.order;
|
||||
delete params.data.limit;
|
||||
params.data.sort = 'Id desc';
|
||||
params.data.count = maxDisplayEvents;
|
||||
params.data.id = monitorId;
|
||||
if ( auth_hash ) params.data.auth = auth_hash;
|
||||
// Maintain legacy behavior by statically setting these parameters
|
||||
params.data.order = 'desc';
|
||||
params.data.limit = maxDisplayEvents;
|
||||
params.data.sort = 'Id';
|
||||
|
||||
$j.getJSON(thisUrl + '?view=request&request=status&entity=events', params.data)
|
||||
$j.getJSON(thisUrl + '?view=request&request=events&task=query'+filterQuery, params.data)
|
||||
.done(function(data) {
|
||||
var rows = processRows(data.events);
|
||||
var rows = processRows(data.rows);
|
||||
// rearrange the result into what bootstrap-table expects
|
||||
params.success({total: data.total, totalNotFiltered: data.totalNotFiltered, rows: rows});
|
||||
})
|
||||
|
@ -72,19 +70,40 @@ function ajaxRequest(params) {
|
|||
function processRows(rows) {
|
||||
$j.each(rows, function(ndx, row) {
|
||||
var eid = row.Id;
|
||||
var filterQuery = '&filter[Query][terms][0][attr]=MonitorId&filter[Query][terms][0][op]=%3d&filter[Query][terms][0][val]='+monitorId;
|
||||
|
||||
row.Delete = '<i class="fa fa-trash text-danger"></i>';
|
||||
row.Id = '<a href="?view=event&eid=' + eid + filterQuery + '">' + eid + '</a>';
|
||||
row.Name = '<a href="?view=event&eid=' + eid + filterQuery + '">' + row.Name + '</a>';
|
||||
row.Frames = '<a href="?view=frames&eid=' + eid + '">' + row.Frames + '</a>';
|
||||
row.AlarmFrames = '<a href="?view=frames&eid=' + eid + '">' + row.AlarmFrames + '</a>';
|
||||
row.MaxScore = '<a href="?view=frame&eid=' + eid + '&fid=0">' + row.MaxScore + '</a>';
|
||||
row.Delete = '<i class="fa fa-trash text-danger"></i>';
|
||||
if ( LIST_THUMBS ) row.Thumbnail = '<a href="?view=event&eid=' + eid + filterQuery + '&page=1">' + row.imgHtml + '</a>';
|
||||
});
|
||||
|
||||
return rows;
|
||||
}
|
||||
|
||||
function thumbnail_onmouseover(event) {
|
||||
var img = event.target;
|
||||
img.src = '';
|
||||
img.src = img.getAttribute('stream_src');
|
||||
}
|
||||
|
||||
function thumbnail_onmouseout(event) {
|
||||
var img = event.target;
|
||||
img.src = '';
|
||||
img.src = img.getAttribute('still_src');
|
||||
}
|
||||
|
||||
function initThumbAnimation() {
|
||||
if ( ANIMATE_THUMBS ) {
|
||||
$j('.colThumbnail img').each(function() {
|
||||
this.addEventListener('mouseover', thumbnail_onmouseover, false);
|
||||
this.addEventListener('mouseout', thumbnail_onmouseout, false);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function showEvents() {
|
||||
$('ptzControls').addClass('hidden');
|
||||
$('events').removeClass('hidden');
|
||||
|
@ -161,6 +180,7 @@ function setAlarmState( currentAlarmState ) {
|
|||
var oldAlarm = ( !isAlarmed && wasAlarmed );
|
||||
|
||||
if ( newAlarm ) {
|
||||
table.bootstrapTable('refresh');
|
||||
if ( SOUND_ON_ALARM ) {
|
||||
// Enable the alarm sound
|
||||
if ( !canPlayPauseAudio ) {
|
||||
|
@ -174,6 +194,7 @@ function setAlarmState( currentAlarmState ) {
|
|||
}
|
||||
}
|
||||
if ( oldAlarm ) { // done with an event do a refresh
|
||||
table.bootstrapTable('refresh');
|
||||
if ( SOUND_ON_ALARM ) {
|
||||
// Disable alarm sound
|
||||
if ( !canPlayPauseAudio ) {
|
||||
|
@ -182,7 +203,6 @@ function setAlarmState( currentAlarmState ) {
|
|||
$('MediaPlayer').Stop();
|
||||
}
|
||||
}
|
||||
table.bootstrapTable('refresh');
|
||||
}
|
||||
|
||||
lastAlarmState = alarmState;
|
||||
|
@ -874,6 +894,18 @@ function initPage() {
|
|||
|
||||
// Take appropriate action when the user clicks on a cell
|
||||
table.on('click-cell.bs.table', processClicks);
|
||||
|
||||
// Some toolbar events break the thumbnail animation, so re-init eventlistener
|
||||
table.on('all.bs.table', initThumbAnimation);
|
||||
|
||||
// Update table links each time after new data is loaded
|
||||
table.on('post-body.bs.table', function(data) {
|
||||
var thumb_ndx = $j('#eventList tr th').filter(function() {
|
||||
return $j(this).text().trim() == 'Thumbnail';
|
||||
}).index();
|
||||
var thmbClass = ANIMATE_THUMBS ? 'colThumbnail zoom' : 'colThumbnail';
|
||||
table.find("tr td:nth-child(" + (thumb_ndx+1) + ")").addClass(thmbClass);
|
||||
});
|
||||
} // initPage
|
||||
|
||||
// Kick everything off
|
||||
|
|
|
@ -50,6 +50,8 @@ var SCALE_BASE = <?php echo SCALE_BASE ?>;
|
|||
|
||||
var SOUND_ON_ALARM = <?php echo ZM_WEB_SOUND_ON_ALARM ?>;
|
||||
var POPUP_ON_ALARM = <?php echo ZM_WEB_POPUP_ON_ALARM ?>;
|
||||
var LIST_THUMBS = <?php echo ZM_WEB_LIST_THUMBS?'true':'false' ?>;
|
||||
var ANIMATE_THUMBS = <?php echo ZM_WEB_ANIMATE_THUMBS?'true':'false' ?>;
|
||||
|
||||
var streamMode = "<?php echo $streamMode ?>";
|
||||
var showMode = "<?php echo ($showPtzControls && !empty($control))?"control":"events" ?>";
|
||||
|
|
|
@ -27,7 +27,7 @@ xhtmlHeaders(__FILE__, translate('SystemLog'));
|
|||
?>
|
||||
<body>
|
||||
<?php echo getNavBarHTML() ?>
|
||||
<div id="page" class="px-3">
|
||||
<div id="page" class="px-3 table-responsive-sm">
|
||||
|
||||
<div id="logSummary" class="text-center">
|
||||
<?php echo translate('State') ?>: <span id="logState"></span> -
|
||||
|
@ -62,7 +62,6 @@ xhtmlHeaders(__FILE__, translate('SystemLog'));
|
|||
data-toolbar="#toolbar"
|
||||
data-show-fullscreen="true"
|
||||
data-maintain-meta-data="true"
|
||||
data-mobile-responsive="true"
|
||||
data-buttons-class="btn btn-normal"
|
||||
data-show-jump-to="true"
|
||||
data-auto-refresh="true"
|
||||
|
|
|
@ -369,8 +369,10 @@ $fastblendopts_alarm = array(
|
|||
);
|
||||
|
||||
$label_size = array(
|
||||
1 => translate('Default'),
|
||||
2 => translate('Large'),
|
||||
1 => translate('Small'),
|
||||
2 => translate('Default'),
|
||||
3 => translate('Large'),
|
||||
4 => translate('Extra Large'),
|
||||
);
|
||||
|
||||
$codecs = array(
|
||||
|
|
|
@ -44,7 +44,9 @@ xhtmlHeaders(__FILE__, translate('Stats')." - ".$eid." - ".$fid );
|
|||
<div id="content" class="row justify-content-center">
|
||||
<form name="contentForm" id="contentForm" method="get" action="?">
|
||||
<input type="hidden" name="view" value="none"/>
|
||||
<?php echo getStatsTableHTML($eid, $fid) ?>
|
||||
<div class="table-responsive-sm">
|
||||
<?php echo getStatsTableHTML($eid, $fid) ?>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -160,7 +160,7 @@ if ( $showPtzControls ) {
|
|||
if ( canView('Events') && ($monitor->Type() != 'WebSite') ) {
|
||||
?>
|
||||
<!-- Table styling handled by bootstrap-tables -->
|
||||
<div id="events" class="row justify-content-center">
|
||||
<div id="events" class="row justify-content-center table-responsive-sm">
|
||||
<table
|
||||
id="eventList"
|
||||
data-locale="<?php echo i18n() ?>"
|
||||
|
@ -172,17 +172,14 @@ if ( canView('Events') && ($monitor->Type() != 'WebSite') ) {
|
|||
data-show-columns="true"
|
||||
data-show-export="true"
|
||||
data-uncheckAll="true"
|
||||
data-mobile-responsive="true"
|
||||
data-buttons-class="btn btn-normal"
|
||||
data-auto-refresh="true"
|
||||
data-auto-refresh-silent="true"
|
||||
data-show-refresh="true"
|
||||
data-auto-refresh-interval="5"
|
||||
class="table-sm table-borderless"
|
||||
>
|
||||
<thead>
|
||||
<!-- Row styling is handled by bootstrap-tables -->
|
||||
<tr>
|
||||
<th data-sortable="false" data-field="Delete"><?php echo translate('Delete') ?></th>
|
||||
<th data-sortable="false" data-field="Id"><?php echo translate('Id') ?></th>
|
||||
<th data-sortable="false" data-field="Name"><?php echo translate('Name') ?></th>
|
||||
<th data-sortable="false" data-field="StartDateTime"><?php echo translate('AttrStartTime') ?></th>
|
||||
|
@ -191,7 +188,7 @@ if ( canView('Events') && ($monitor->Type() != 'WebSite') ) {
|
|||
<th data-sortable="false" data-field="AlarmFrames"><?php echo translate('AlarmBrFrames') ?></th>
|
||||
<th data-sortable="false" data-field="AvgScore"><?php echo translate('AvgBrScore') ?></th>
|
||||
<th data-sortable="false" data-field="MaxScore"><?php echo translate('MaxBrScore') ?></th>
|
||||
<th data-sortable="false" data-field="Delete"><?php echo translate('Delete') ?></th>
|
||||
<th data-sortable="false" data-field="Thumbnail"><?php echo translate('Thumbnail') ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
|
|
Loading…
Reference in New Issue