Add track edit/delete feature
This commit is contained in:
parent
a64213940a
commit
7088d326ab
@ -53,6 +53,10 @@ select {
|
||||
#menu input[type = "checkbox"] {
|
||||
width: auto;
|
||||
}
|
||||
.menulink {
|
||||
display: block;
|
||||
margin-top: .2em;
|
||||
}
|
||||
#main {
|
||||
height: 100%;
|
||||
margin-right: 165px;
|
||||
|
@ -102,17 +102,27 @@
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all user's positions
|
||||
* Delete all user's positions, optionally limit to given track
|
||||
*
|
||||
* @param string $userId User id
|
||||
* @param int $userId User id
|
||||
* @param int $trackId Optional track id
|
||||
* @return bool True if success, false otherwise
|
||||
*/
|
||||
public function deleteAll($userId) {
|
||||
public function deleteAll($userId, $trackId = NULL) {
|
||||
$ret = false;
|
||||
if (!empty($userId)) {
|
||||
$query = "DELETE FROM positions WHERE user_id = ?";
|
||||
$args = [];
|
||||
$where = "WHERE user_id = ?";
|
||||
$args[0] = "i";
|
||||
$args[1] = &$userId;
|
||||
if (!empty($trackId)) {
|
||||
$where .= " AND track_id = ?";
|
||||
$args[0] .= "i";
|
||||
$args[2] = &$trackId;
|
||||
}
|
||||
$query = "DELETE FROM positions $where";
|
||||
$stmt = self::$db->prepare($query);
|
||||
$stmt->bind_param('i', $userId);
|
||||
call_user_func_array([ $stmt, 'bind_param' ], $args);
|
||||
$stmt->execute();
|
||||
if (!self::$db->error && !$stmt->errno) {
|
||||
$ret = true;
|
||||
@ -127,6 +137,7 @@
|
||||
* (for given user if specified)
|
||||
*
|
||||
* @param int $userId Optional user id
|
||||
* @return uPosition Self
|
||||
*/
|
||||
public function getLast($userId = NULL) {
|
||||
if (!empty($userId)) {
|
||||
@ -145,6 +156,7 @@
|
||||
$where
|
||||
ORDER BY p.time DESC LIMIT 1";
|
||||
$this->loadWithQuery($query, $params);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -18,6 +18,7 @@
|
||||
*/
|
||||
|
||||
require_once(ROOT_DIR . "/helpers/db.php");
|
||||
require_once(ROOT_DIR . "/helpers/position.php");
|
||||
|
||||
/**
|
||||
* Track handling
|
||||
@ -77,6 +78,64 @@
|
||||
return $trackId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete track with all positions
|
||||
*
|
||||
* @return bool True if success, false otherwise
|
||||
*/
|
||||
public function delete() {
|
||||
$ret = false;
|
||||
if ($this->isValid) {
|
||||
// delete positions
|
||||
$position = new uPosition();
|
||||
if ($position->deleteAll($this->userId, $this->id) === false) {
|
||||
return false;
|
||||
}
|
||||
// delete track metadata
|
||||
$query = "DELETE FROM tracks WHERE id = ?";
|
||||
$stmt = self::$db->prepare($query);
|
||||
$stmt->bind_param('i', $this->id);
|
||||
$stmt->execute();
|
||||
if (!self::$db->error && !$stmt->errno) {
|
||||
$ret = true;
|
||||
$this->id = NULL;
|
||||
$this->userId = NULL;
|
||||
$this->name = NULL;
|
||||
$this->comment = NULL;
|
||||
$this->isValid = false;
|
||||
}
|
||||
$stmt->close();
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update track
|
||||
*
|
||||
* @param string|null $name New name (not empty string) or NULL if not changed
|
||||
* @param string|null $comment New comment or NULL if not changed (to remove content use empty string: "")
|
||||
* @return bool True if success, false otherwise
|
||||
*/
|
||||
public function update($name = NULL, $comment = NULL) {
|
||||
$ret = false;
|
||||
if (empty($name)) { $name = $this->name; }
|
||||
if (is_null($comment)) { $comment = $this->comment; }
|
||||
if ($comment == "") { $comment = NULL; }
|
||||
if ($this->isValid) {
|
||||
$query = "UPDATE tracks SET name = ?, comment = ? WHERE id = ?";
|
||||
$stmt = self::$db->prepare($query);
|
||||
$stmt->bind_param('ssi', $name, $comment, $this->id);
|
||||
$stmt->execute();
|
||||
if (!self::$db->error && !$stmt->errno) {
|
||||
$ret = true;
|
||||
$this->name = $name;
|
||||
$this->comment = $comment;
|
||||
}
|
||||
$stmt->close();
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all user's tracks
|
||||
*
|
||||
|
17
index.php
17
index.php
@ -80,6 +80,7 @@
|
||||
var init_latitude = '<?= $config::$init_latitude ?>';
|
||||
var init_longitude = '<?= $config::$init_longitude ?>';
|
||||
var lang = <?= json_encode($lang) ?>;
|
||||
var admin = <?= json_encode($user->isAdmin) ?>;
|
||||
var auth = '<?= ($user->isValid) ? $user->login : "null" ?>';
|
||||
var pass_regex = <?= $config->passRegex() ?>;
|
||||
</script>
|
||||
@ -95,6 +96,9 @@
|
||||
<?php if ($user->isAdmin): ?>
|
||||
<script type="text/javascript" src="js/admin.js"></script>
|
||||
<?php endif; ?>
|
||||
<?php if ($user->isValid): ?>
|
||||
<script type="text/javascript" src="js/track.js"></script>
|
||||
<?php endif; ?>
|
||||
<script type="text/javascript" src="js/pass.js"></script>
|
||||
<script type="text/javascript" src="//www.google.com/jsapi"></script>
|
||||
<script type="text/javascript">
|
||||
@ -186,15 +190,18 @@
|
||||
|
||||
<div id="export">
|
||||
<u><?= $lang["download"] ?></u><br>
|
||||
<a href="javascript:void(0);" onclick="load('kml', userid, trackid);">kml</a><br>
|
||||
<a href="javascript:void(0);" onclick="load('gpx', userid, trackid);">gpx</a><br>
|
||||
<a class="menulink" href="javascript:void(0);" onclick="load('kml', userid, trackid);">kml</a>
|
||||
<a class="menulink" href="javascript:void(0);" onclick="load('gpx', userid, trackid);">gpx</a>
|
||||
</div>
|
||||
|
||||
<?php if ($user->isAdmin): ?>
|
||||
<?php if ($user->isValid): ?>
|
||||
<div id="admin_menu">
|
||||
<u><?= $lang["adminmenu"] ?></u><br>
|
||||
<a href="javascript:void(0);" onclick="addUser()"><?= $lang["adduser"] ?></a><br>
|
||||
<a href="javascript:void(0);" onclick="editUser()"><?= $lang["edituser"] ?></a><br>
|
||||
<?php if ($user->isAdmin): ?>
|
||||
<a class="menulink" href="javascript:void(0);" onclick="addUser()"><?= $lang["adduser"] ?></a>
|
||||
<a class="menulink" href="javascript:void(0);" onclick="editUser()"><?= $lang["edituser"] ?></a>
|
||||
<?php endif; ?>
|
||||
<a class="menulink" href="javascript:void(0);" onclick="editTrack()"><?= $lang["edittrack"] ?></a>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
|
@ -47,7 +47,7 @@ function editUser() {
|
||||
}
|
||||
|
||||
function confirmedDelete(login) {
|
||||
return confirm(sprintf(lang['deletewarn'], '"' + login + '"'));
|
||||
return confirm(sprintf(lang['userdelwarn'], '"' + login + '"'));
|
||||
}
|
||||
|
||||
function submitUser(action) {
|
||||
|
@ -113,6 +113,7 @@ function getXHR() {
|
||||
}
|
||||
|
||||
function loadTrack(userid, trackid, update) {
|
||||
if (trackid < 0) { return; }
|
||||
if (latest == 1) { trackid = 0; }
|
||||
var xhr = getXHR();
|
||||
xhr.onreadystatechange = function () {
|
||||
@ -274,7 +275,11 @@ function setTrack(t) {
|
||||
}
|
||||
|
||||
function selectTrack(f) {
|
||||
if (f.selectedIndex >= 0) {
|
||||
trackid = f.options[f.selectedIndex].value;
|
||||
} else {
|
||||
trackid = 0;
|
||||
}
|
||||
document.getElementById('latest').checked = false;
|
||||
if (latest == 1) { toggleLatest(); }
|
||||
loadTrack(userid, trackid, 1);
|
||||
|
100
js/track.js
Normal file
100
js/track.js
Normal file
@ -0,0 +1,100 @@
|
||||
/* μlogger
|
||||
*
|
||||
* Copyright(C) 2017 Bartek Fabiszewski (www.fabiszewski.net)
|
||||
*
|
||||
* This 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
function editTrack() {
|
||||
var userForm = document.getElementsByName('user')[0];
|
||||
var trackUser = userForm.options[userForm.selectedIndex].text;
|
||||
if (trackUser != auth && !admin) {
|
||||
alert(lang['owntrackswarn']);
|
||||
return;
|
||||
}
|
||||
var trackForm = document.getElementsByName('track')[0];
|
||||
if (trackForm.selectedIndex < 0) {
|
||||
return;
|
||||
}
|
||||
var trackId = trackForm.options[trackForm.selectedIndex].value;
|
||||
var trackName = trackForm.options[trackForm.selectedIndex].text;
|
||||
var message = '<div style="float:left">' + sprintf(lang['editingtrack'], '<b>' + htmlEncode(trackName) + '</b>') + '</div>';
|
||||
message += '<div class="red-button"><b><a href="javascript:void(0);" onclick="submitTrack(\'delete\'); return false">' + lang['deltrack'] + '</a></b></div>';
|
||||
message += '<div style="clear: both; padding-bottom: 1em;"></div>';
|
||||
|
||||
var form = '<form id="trackForm" method="post" onsubmit="submitTrack(\'update\'); return false">';
|
||||
form += '<input type="hidden" name="trackid" value="' + trackId + '">';
|
||||
form += '<label><b>' + lang['trackname'] + '</b></label><input type="text" placeholder="' + lang['trackname'] + '" name="trackname" value="' + htmlEncode(trackName) + '" required>';
|
||||
form += '<div class="buttons"><button type="button" onclick="removeModal()">' + lang['cancel'] + '</button><button type="submit">' + lang['submit'] + '</button></div>';
|
||||
form += '</form>';
|
||||
showModal(message + form);
|
||||
}
|
||||
|
||||
function confirmedDelete(name) {
|
||||
return confirm(sprintf(lang['trackdelwarn'], '"' + name + '"'));
|
||||
}
|
||||
|
||||
function submitTrack(action) {
|
||||
var form = document.getElementById('trackForm');
|
||||
var trackId = parseInt(form.elements['trackid'].value);
|
||||
var trackName = form.elements['trackname'].value.trim();
|
||||
if (isNaN(trackId)) {
|
||||
alert(lang['allrequired']);
|
||||
return;
|
||||
}
|
||||
if (action != 'delete') {
|
||||
if (!trackName) {
|
||||
alert(lang['allrequired']);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (!confirmedDelete(trackName)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
var xhr = getXHR();
|
||||
xhr.onreadystatechange = function() {
|
||||
if (xhr.readyState == 4 && xhr.status == 200) {
|
||||
var xml = xhr.responseXML;
|
||||
var message = "";
|
||||
if (xml) {
|
||||
var root = xml.getElementsByTagName('root');
|
||||
if (root.length && getNode(root[0], 'error') == 0) {
|
||||
removeModal();
|
||||
alert(lang['actionsuccess']);
|
||||
var f = document.getElementsByName('track')[0];
|
||||
if (action == 'delete') {
|
||||
// select current track in tracks form
|
||||
f.remove(f.selectedIndex);
|
||||
clearMap();
|
||||
selectTrack(f);
|
||||
} else {
|
||||
f.options[f.selectedIndex].innerHTML = htmlEncode(trackName);
|
||||
}
|
||||
return;
|
||||
}
|
||||
errorMsg = getNode(root[0], 'message');
|
||||
if (errorMsg) { message = errorMsg; }
|
||||
}
|
||||
alert(lang['actionfailure'] + '\n' + message);
|
||||
xhr = null;
|
||||
}
|
||||
}
|
||||
xhr.open('POST', 'utils/handletrack.php', true);
|
||||
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
|
||||
var params = 'action=' + action + '&trackid=' + trackId + '&trackname=' + encodeURIComponent(trackName);
|
||||
params = params.replace(/%20/g, '+');
|
||||
xhr.send(params);
|
||||
return;
|
||||
}
|
2
lang.php
2
lang.php
@ -38,7 +38,7 @@
|
||||
}
|
||||
|
||||
// choose password messages based on config
|
||||
$lang['passrules'] = $lang["passrules"][$config::$pass_strength];
|
||||
$lang['passrules'] = isset($lang["passrules"][$config::$pass_strength]) ? $lang["passrules"][$config::$pass_strength] : "";
|
||||
$lang['passlenmin'] = sprintf($lang["passlenmin"], $config::$pass_lenmin);
|
||||
|
||||
?>
|
||||
|
14
lang/en.php
14
lang/en.php
@ -72,13 +72,19 @@ $lang["allrequired"] = "All fields are required";
|
||||
$lang["passnotmatch"] = "Passwords don't match";
|
||||
$lang["actionsuccess"] = "Action completed successfully";
|
||||
$lang["actionfailure"] = "Something went wrong";
|
||||
$lang["deletewarn"] = "Warning!\n\nYou are going to permanently delete user %s, together with all their routes and positions.\n\nAre you sure?"; // substitutes user login
|
||||
$lang["userdelwarn"] = "Warning!\n\nYou are going to permanently delete user %s, together with all their routes and positions.\n\nAre you sure?"; // substitutes user login
|
||||
$lang["editinguser"] = "You are editing user %s"; // substitutes user login
|
||||
$lang["selfeditwarn"] = "Your can't edit your own user with this tool";
|
||||
$lang["apifailure"] = "Sorry, can't load %s API"; // substitures api name (gmaps or openlayers)
|
||||
$lang["trackdelwarn"] = "Warning!\n\nYou are going to permanently delete track %s and all its positions.\n\nAre you sure?"; // substitutes track name
|
||||
$lang["editingtrack"] = "You are editing track %s"; // substitutes track name
|
||||
$lang["deltrack"] = "Remove track";
|
||||
$lang["trackname"] = "Track name";
|
||||
$lang["edittrack"] = "Edit track";
|
||||
$lang["passlenmin"] = "Password must be at least %d characters"; // substitutes password minimum length
|
||||
$lang["passrules"][1] = "It should contain at least one upper case letter, one lower case letter";
|
||||
$lang["passrules"][2] = "It should contain at least one upper case letter, one lower case letter and one digit";
|
||||
$lang["passrules"][3] = "It should contain at least one upper case letter, one lower case letter, one digit and one non-alphanumeric character";
|
||||
$lang["passrules"][1] = "It should contain at least one lower case letter, one upper case letter";
|
||||
$lang["passrules"][2] = "It should contain at least one lower case letter, one upper case letter and one digit";
|
||||
$lang["passrules"][3] = "It should contain at least one lower case letter, one upper case letter, one digit and one non-alphanumeric character";
|
||||
$lang["owntrackswarn"] = "Your can only edit your own tracks";
|
||||
|
||||
?>
|
||||
|
12
lang/pl.php
12
lang/pl.php
@ -70,9 +70,19 @@ $lang["allrequired"] = "Wszystkie pola są wymagane";
|
||||
$lang["passnotmatch"] = "Hasła nie pasują do siebie";
|
||||
$lang["actionsuccess"] = "Operacja zakończona pomyślnie";
|
||||
$lang["actionfailure"] = "Wystąpił błąd";
|
||||
$lang["deletewarn"] = "Uwaga!\n\nZamierzasz całkowicie usunąć użytkownika %s, razem ze wszystkimi jego trasami i pozycjami.\n\nCzy na pewno?";
|
||||
$lang["userdeletewarn"] = "Uwaga!\n\nZamierzasz całkowicie usunąć użytkownika %s, razem ze wszystkimi jego trasami i pozycjami.\n\nCzy na pewno?";
|
||||
$lang["editinguser"] = "Edytujesz użytkownika %s";
|
||||
$lang["selfeditwarn"] = "Nie można edytować własnego użytkownika za pomocą tego narzędzia";
|
||||
$lang["apifailure"] = "Niestety ładowanie API %s nie powiodło się";
|
||||
$lang["trackdelwarn"] = "Uwaga!\n\nZamierzasz całkowicie usunąć trasę %s wraz ze wszystkimi pozycjami.\n\nCzy na pewno?";
|
||||
$lang["editingtrack"] = "Edytujesz trasę %s";
|
||||
$lang["deltrack"] = "Usuń trasę";
|
||||
$lang["trackname"] = "Nazwa trasy";
|
||||
$lang["edittrack"] = "Edytuj trasę";
|
||||
$lang["passlenmin"] = "Hasło musi się składać z minimum %d znaków";
|
||||
$lang["passrules"][1] = "Powinno ono zawierać przynajmniej jedną małą i jedną wielką literę";
|
||||
$lang["passrules"][2] = "Powinno ono zawierać przynajmniej jedną małą, jedną wielką literę i jedną cyfrę";
|
||||
$lang["passrules"][3] = "Powinno ono zawierać przynajmniej jedną małą, jedną wielką literę, jedną cyfrę i jeden znak specjalny (nie alfanumeryczny)";
|
||||
$lang["owntrackswarn"] = "Możesz edytować tylko swoje własne trasy";
|
||||
|
||||
?>
|
||||
|
80
utils/handletrack.php
Normal file
80
utils/handletrack.php
Normal file
@ -0,0 +1,80 @@
|
||||
<?php
|
||||
/* μlogger
|
||||
*
|
||||
* Copyright(C) 2017 Bartek Fabiszewski (www.fabiszewski.net)
|
||||
*
|
||||
* This 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
require_once(dirname(__DIR__) . "/auth.php"); // sets $mysqli, $user
|
||||
require_once(ROOT_DIR . "/helpers/track.php");
|
||||
|
||||
/**
|
||||
* Exit with xml response
|
||||
* @param boolean $isError Error if true
|
||||
* @param string $errorMessage Optional error message
|
||||
*/
|
||||
function exitWithStatus($isError, $errorMessage = NULL) {
|
||||
header("Content-type: text/xml");
|
||||
$xml = new XMLWriter();
|
||||
$xml->openURI("php://output");
|
||||
$xml->startDocument("1.0");
|
||||
$xml->setIndent(true);
|
||||
$xml->startElement('root');
|
||||
$xml->writeElement("error", (int) $isError);
|
||||
if ($isError) {
|
||||
$xml->writeElement("message", $errorMessage);
|
||||
}
|
||||
$xml->endElement();
|
||||
$xml->endDocument();
|
||||
$xml->flush();
|
||||
exit;
|
||||
}
|
||||
|
||||
$action = isset($_REQUEST['action']) ? $_REQUEST['action'] : NULL;
|
||||
$trackId = isset($_REQUEST['trackid']) ? trim($_REQUEST['trackid']) : NULL;
|
||||
$trackName = isset($_REQUEST['trackname']) ? trim($_REQUEST['trackname']) : NULL;
|
||||
if (empty($action) || empty($trackId)) {
|
||||
exitWithStatus(true, $lang["servererror"]);
|
||||
}
|
||||
$track = new uTrack($trackId);
|
||||
if (!$track->isValid || (!$user->isAdmin && $user->id != $track->userId)) {
|
||||
exitWithStatus(true, $lang["servererror"]);
|
||||
}
|
||||
|
||||
switch ($action) {
|
||||
|
||||
case 'update':
|
||||
if (empty($trackName)) {
|
||||
exitWithStatus(true, $lang["servererror"]);
|
||||
}
|
||||
if ($track->update($trackName) === false) {
|
||||
exitWithStatus(true, $mysqli->error);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'delete':
|
||||
if ($track->delete() === false) {
|
||||
exitWithStatus(true, $mysqli->error);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
exitWithStatus(true, $lang["servererror"]);
|
||||
break;
|
||||
}
|
||||
|
||||
exitWithStatus(false);
|
||||
|
||||
?>
|
Loading…
x
Reference in New Issue
Block a user