rework devices view, remove inline onclick

This commit is contained in:
Andrew Bauer 2020-10-02 12:39:05 -05:00
parent 1c54efa88d
commit 6c0f61ebbd
5 changed files with 223 additions and 64 deletions

47
web/ajax/device.php Normal file
View File

@ -0,0 +1,47 @@
<?php
//
// ZoneMinder web action file
// Copyright (C) 2019 ZoneMinder LLC
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// Device view actions
if ( !canEdit('Devices') ) {
ajaxError('Insufficient permissions for user '.$user['Username']);
return;
}
if ( $action == 'device' ) {
if ( !empty($_REQUEST['command']) ) {
setDeviceStatusX10($_REQUEST['key'], $_REQUEST['command']);
} else if ( isset($_REQUEST['newDevice']) ) {
if ( isset($_REQUEST['did']) && $_REQUEST['did'] ) {
ZM\Warning('did value is: '.$_REQUEST['did']);
ZM\Warning('newDevice array value is: '.print_r($_REQUEST['newDevice'],true));
dbQuery('UPDATE Devices SET Name=?, KeyString=? WHERE Id=?',
array($_REQUEST['newDevice']['Name'], $_REQUEST['newDevice']['KeyString'], $_REQUEST['did']) );
} else {
dbQuery('INSERT INTO Devices SET Name=?, KeyString=?',
array($_REQUEST['newDevice']['Name'], $_REQUEST['newDevice']['KeyString']) );
}
}
ajaxResponse();
} else {
ajaxError('Unrecognised action '.$_REQUEST['action']);
} // end if action
?>

38
web/ajax/devices.php Normal file
View File

@ -0,0 +1,38 @@
<?php
//
// ZoneMinder web action file
// Copyright (C) 2019 ZoneMinder LLC
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// Device view actions
if ( !canEdit('Devices') ) {
ajaxError('Insufficient permissions for user '.$user['Username']);
return;
}
if ( $action == 'delete' ) {
if ( isset($_REQUEST['markDids']) ) {
foreach( $_REQUEST['markDids'] as $markDid ) {
dbQuery('DELETE FROM Devices WHERE Id=?', array($markDid));
}
}
ajaxResponse();
} else {
ajaxError('Unrecognised action '.$_REQUEST['action']);
}
?>

View File

@ -262,6 +262,7 @@ $SLANG = array(
'ConfiguredFor' => 'Configured for', 'ConfiguredFor' => 'Configured for',
'ConfigURL' => 'Config Base URL', 'ConfigURL' => 'Config Base URL',
'ConfirmDeleteControl' => 'Warning, deleting a control will reset all monitors that use it to be uncontrollable.<br><br>Are you sure you wish to delete?', 'ConfirmDeleteControl' => 'Warning, deleting a control will reset all monitors that use it to be uncontrollable.<br><br>Are you sure you wish to delete?',
'ConfirmDeleteDevices' => 'Are you sure you wish to delete the selected devices?',
'ConfirmDeleteEvents' => 'Are you sure you wish to delete the selected events?', 'ConfirmDeleteEvents' => 'Are you sure you wish to delete the selected events?',
'ConfirmDeleteTitle' => 'Delete Confirmation', 'ConfirmDeleteTitle' => 'Delete Confirmation',
'ConfirmPassword' => 'Confirm Password', 'ConfirmPassword' => 'Confirm Password',

View File

@ -36,23 +36,45 @@ xhtmlHeaders(__FILE__, translate('Devices') );
?> ?>
<body> <body>
<?php echo getNavBarHTML(); ?> <?php echo getNavBarHTML(); ?>
<div id="page"> <div id="page" class="container-fluid">
<div class="w-100 py-1"> <h2>X10 <?php echo translate('Devices') ?></h2>
<div class="float-left pl-3">
<button type="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> <div id="toolbar">
<button type="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="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="newDeviceBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('New') ?>"><i class="fa fa-plus"></i></button>
<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>
<div class="w-100 pt-2">
<h2><?php echo translate('Devices') ?></h2> <div id="content" class="row justify-content-center">
</div> <table
</div> id="devicesTable"
<div id="content"> class="table-sm table-borderless"
<form name="contentForm" method="get" action="?"> data-search="true"
<input type="hidden" name="view" value="none"/> data-cookie="true"
<input type="hidden" name="action" value="device"/> data-cookie-id-table="zmDevicesTable"
<input type="hidden" name="key" value=""/> data-cookie-expire="2y"
<input type="hidden" name="command" value=""/> data-cookie-expire="2y"
<table id="contentTable" class="major" cellspacing="0"> 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"
>
<thead>
<tr>
<th data-sortable="true" data-field="Id"><?php echo translate('Id') ?></th>
<th data-sortable="true" data-field="Name"><?php echo translate('Name') ?></th>
<th data-sortable="true" data-field="KeyString"><?php echo translate('KeyString') ?></th>
<th data-sortable="false" data-field="On"><?php echo translate('On') ?></th>
<th data-sortable="false" data-field="Off"><?php echo translate('Off') ?></th>
<th data-sortable="false" data-field="toggleCheck" data-checkbox="true"></th>
</tr>
</thead>
<tbody> <tbody>
<?php <?php
foreach( $devices as $device ) { foreach( $devices as $device ) {
@ -68,21 +90,18 @@ foreach( $devices as $device ) {
$str_opt = 'class="deviceCol" data-did="'.$device['Id'].'"'; $str_opt = 'class="deviceCol" data-did="'.$device['Id'].'"';
?> ?>
<tr> <tr>
<td><?php echo makeLink( '#', '<span class="'.$fclass.'">'.validHtmlStr($device['Name']).' ('.validHtmlStr($device['KeyString']).')</span>', canEdit( 'Devices' ), $str_opt ) ?></td> <td><?php echo $device['Id'] ?></td>
<td><input type="button" value="<?php echo translate('On') ?>"<?php echo ($device['Status'] != 'ON')?' class="set"':'' ?> onclick="switchDeviceOn( this, '<?php echo validHtmlStr($device['KeyString']) ?>' )"<?php echo canEdit( 'Devices' )?"":' disabled="disabled"' ?>/></td> <td><?php echo makeLink( '#', '<span class="'.$fclass.'">'.validHtmlStr($device['Name']).'</span>', canEdit( 'Devices' ), $str_opt ) ?></td>
<td><input type="button" value="<?php echo translate('Off') ?>"<?php echo ($device['Status'] != 'OFF')?' class="set"':'' ?> onclick="switchDeviceOff( this, '<?php echo validHtmlStr($device['KeyString']) ?>' )"<?php echo canEdit( 'Devices' )?"":' disabled="disabled"' ?>/></td> <td><?php echo makeLink( '#', '<span class="'.$fclass.'">'.validHtmlStr($device['KeyString']).'</span>', canEdit( 'Devices' ), $str_opt ) ?></td>
<td><input type="checkbox" name="markDids[]" value="<?php echo $device['Id'] ?>" onclick="configureButtons( this, 'markDids' );"<?php if ( !canEdit( 'Devices' ) ) {?> disabled="disabled"<?php } ?>/></td> <td><button class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('On') ?>"><i class="fa fa-toggle-on"></i></button></td>
<td><button class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Off') ?>"><i class="fa fa-toggle-off"></i></button></td>
<td data-checkbox="true"></td>
</tr> </tr>
<?php <?php
} }
?> ?>
</tbody> </tbody>
</table> </table>
<div id="contentButtons">
<button type="button" id="newDeviceBtn" value="<?php echo translate('New') ?>" disabled="disabled"><?php echo translate('New') ?></button>
<input type="button" class="btn-danger" name="deleteBtn" value="<?php echo translate('Delete') ?>" data-on-click-this="deleteDevice" disabled="disabled"/>
</div>
</form>
</div> </div>
</div> </div>
<?php xhtmlFooter() ?> <?php xhtmlFooter() ?>

View File

@ -1,43 +1,6 @@
var newDeviceBtn = $j('#newDeviceBtn'); var newDeviceBtn = $j('#newDeviceBtn');
var table = $j('#devicesTable');
function switchDeviceOn( element, key ) { var deleteBtn = $j('#deleteBtn');
var form = element.form;
form.view.value = currentView;
form.action.value = 'device';
form.command.value = 'on';
form.key.value = key;
form.submit();
}
function switchDeviceOff( element, key ) {
var form = element.form;
form.view.value = currentView;
form.action.value = 'device';
form.command.value = 'off';
form.key.value = key;
form.submit();
}
function deleteDevice( element ) {
var form = element.form;
form.view.value = currentView;
form.action.value = 'delete';
form.submit();
}
function configureButtons( element, name ) {
var form = element.form;
var checked = false;
for (var i = 0; i < form.elements.length; i++) {
if ( form.elements[i].name.indexOf(name) == 0) {
if ( form.elements[i].checked ) {
checked = true;
break;
}
}
}
form.deleteBtn.disabled = !checked;
}
// Load the Device Modal HTML via Ajax call // Load the Device Modal HTML via Ajax call
function getDeviceModal(did) { function getDeviceModal(did) {
@ -70,7 +33,72 @@ function enableDeviceModal() {
}); });
} }
// Load the Delete Confirmation Modal HTML via Ajax call
function getDelConfirmModal(key) {
$j.getJSON(thisUrl + '?request=modal&modal=delconfirm&key=' + key)
.done(function(data) {
if ( $j('#deleteConfirm').length ) {
$j('#deleteConfirm').replaceWith(data.html);
} else {
$j("body").append(data.html);
}
manageDelConfirmModalBtns();
})
.fail(logAjaxFail);
}
// Manage the DELETE CONFIRMATION modal button
function manageDelConfirmModalBtns() {
document.getElementById("delConfirmBtn").addEventListener("click", function onDelConfirmClick(evt) {
if ( ! canEditDevice ) {
enoperm();
return;
}
var selections = getIdSelections();
evt.preventDefault();
$j.getJSON(thisUrl + '?request=devices&action=delete&markDids[]='+selections.join('&markDids[]='))
.done( function(data) {
$j('#devicesTable').bootstrapTable('refresh');
window.location.reload(true);
})
.fail(logAjaxFail);
});
// Manage the CANCEL modal button
document.getElementById("delCancelBtn").addEventListener("click", function onDelCancelClick(evt) {
$j('#deleteConfirm').modal('hide');
});
}
// Returns the event id's of the selected rows
function getIdSelections() {
return $j.map(table.bootstrapTable('getSelections'), function(row) {
return row.Id.replace(/(<([^>]+)>)/gi, ''); // strip the html from the element before sending
});
}
// Take the appropriate action when the user clicks on cells in the table
function processClicks(event, field, value, row, $element) {
if ( field == 'On' || field == 'Off' ) {
var key = row.KeyString.replace(/(<([^>]+)>)/gi, '');
var url = '?request=device&action=device&command=' + field + '&key=' + key;
console.log('Url sent to device: ' + url);
$j.getJSON(thisUrl + url)
.done(function(data) {
// TODO - verify if either of these are needed
$j('#devicesTable').bootstrapTable('refresh');
window.location.reload(true);
})
.fail(logAjaxFail);
}
}
function initPage() { function initPage() {
// Init the bootstrap-table
table.bootstrapTable({icons: icons});
if ( canEditDevice ) enableDeviceModal(); if ( canEditDevice ) enableDeviceModal();
newDeviceBtn.prop('disabled', !canEditDevice); newDeviceBtn.prop('disabled', !canEditDevice);
@ -89,6 +117,32 @@ function initPage() {
evt.preventDefault(); evt.preventDefault();
window.location.reload(true); window.location.reload(true);
}); });
// Manage the DELETE button
document.getElementById("deleteBtn").addEventListener("click", function onDeleteClick(evt) {
if ( ! canEditDevice ) {
enoperm();
return;
}
evt.preventDefault();
$j('#deleteConfirm').modal('show');
});
// Load the delete confirmation modal into the DOM
getDelConfirmModal('ConfirmDeleteDevices');
// enable or disable buttons based on current selection and user rights
table.on('check.bs.table uncheck.bs.table ' +
'check-all.bs.table uncheck-all.bs.table',
function() {
selections = table.bootstrapTable('getSelections');
deleteBtn.prop('disabled', !(selections.length && canEditDevice));
});
// Process mouse clicks on the table cells
table.on('click-cell.bs.table', processClicks);
} }
$j(document).ready(initPage); $j(document).ready(initPage);