Add timecard editing (close #2)

master
Skylar Ittner 6 years ago
parent 0a2ced319a
commit 30db1512f5

@ -74,6 +74,71 @@ switch ($VARS['action']) {
$out = ["status" => "OK", "in" => $in];
header('Content-Type: application/json');
exit(json_encode($out));
case "editpunch":
require_once __DIR__ . "/lib/userinfo.php";
if (user_exists($VARS['user'])) {
$uid = getUserByUsername($VARS['user'])['uid'];
} else {
returnToSender("invalid_user");
}
$in = strtotime($VARS['in']);
$out = strtotime($VARS['out']);
if ($in === false) {
returnToSender("invalid_datetime");
}
if ($out === false) {
returnToSender("invalid_datetime");
}
if ($out < $in) {
returnToSender("in_before_out");
}
if (
account_has_permission($_SESSION['username'], "QWIKCLOCK_ADMIN") || (
account_has_permission($_SESSION['username'], "QWIKCLOCK_MANAGE") && isManagerOf($_SESSION['uid'], $uid)
) || (
account_has_permission($_SESSION['username'], "QWIKCLOCK_EDITSELF") && $_SESSION['uid'] == $uid
)
) {
$data = [
"uid" => $uid,
"in" => date('Y-m-d H:i:s', $in),
"out" => date('Y-m-d H:i:s', $out),
"notes" => $VARS['notes']
];
if ($database->has("punches", ["punchid" => $VARS['punchid']])) {
$database->update("punches", $data, ["punchid" => $VARS['punchid']]);
} else {
$database->insert("punches", $data);
}
returnToSender("punch_saved");
} else {
returnToSender("no_permission");
}
case "deletepunch":
require_once __DIR__ . "/lib/userinfo.php";
if (!$database->has("punches", ["punchid" => $VARS['punchid']])) {
returnToSender("invalid_parameters");
}
$pid = $VARS['punchid'];
$uid = $database->get("punches", "uid", ["punchid" => $pid]);
if (
account_has_permission($_SESSION['username'], "QWIKCLOCK_ADMIN") || (
account_has_permission($_SESSION['username'], "QWIKCLOCK_MANAGE") && isManagerOf($_SESSION['uid'], $uid)
) || (
account_has_permission($_SESSION['username'], "QWIKCLOCK_EDITSELF") && $_SESSION['uid'] == $uid
)
) {
$database->delete("punches", ["punchid" => $VARS['punchid']]);
returnToSender("punch_deleted");
} else {
returnToSender("no_permission");
}
case "editshift":
if (account_has_permission($_SESSION['username'], "QWIKCLOCK_ADMIN")) {
$valid_daycodes = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
@ -134,7 +199,7 @@ switch ($VARS['action']) {
returnToSender("no_permission");
}
case "assignshift":
if (!account_has_permission($_SESSION['username'], "QWIKCLOCK_MANAGE")) {
if (!account_has_permission($_SESSION['username'], "QWIKCLOCK_MANAGE") && !account_has_permission($_SESSION['username'], "QWIKCLOCK_ADMIN")) {
returnToSender("no_permission");
}
if (!$database->has('shifts', ['shiftid' => $VARS['shift']])) {

@ -45,6 +45,7 @@ define("STRINGS", [
"this week" => "This Week",
"x on the clock" => "{time} on the clock",
"x punches" => "{count} punches",
"1 punch" => "1 punch",
"history" => "History",
"shifts" => "Shifts",
"show all punches" => "Show other users",
@ -102,4 +103,15 @@ define("STRINGS", [
"punches" => "Punches",
"not assigned to work now" => "You are not assigned to work right now.",
"not a managed user" => "Not a managed user",
"actions" => "Actions",
"edit" => "Edit",
"invalid user" => "That user does not exist.",
"no editself permission" => "You don't have permission to edit your own punches.",
"edit punch" => "Edit Punch",
"new punch" => "New Punch",
"user" => "User",
"in must be before out" => "The in time must be before the out time.",
"punch saved" => "Punch saved.",
"invalid datetime" => "Could not understand the dates/times given. Please use a standard format, such as \"January 1, 2018 3:30pm\".",
"punch deleted" => "Punch deleted.",
]);

@ -76,5 +76,29 @@ define("MESSAGES", [
"not_assigned_to_work" => [
"string" => "not assigned to work now",
"type" => "danger"
]
],
"invalid_user" => [
"string" => "invalid user",
"type" => "danger"
],
"no_editself_permission" => [
"string" => "no editself permission",
"type" => "danger"
],
"in_before_out" => [
"string" => "in must be before out",
"type" => "danger"
],
"punch_saved" => [
"string" => "punch saved",
"type" => "success"
],
"invalid_datetime" => [
"string" => "invalid datetime",
"type" => "danger"
],
"punch_deleted" => [
"string" => "punch deleted",
"type" => "success"
],
]);

@ -9,12 +9,18 @@ header("Content-Type: application/json");
require_once __DIR__ . "/login.php";
require_once __DIR__ . "/userinfo.php";
$showmanaged = ($VARS['show_all'] == 1 && account_has_permission($_SESSION['username'], "QWIKCLOCK_MANAGE"));
$account_is_admin = account_has_permission($_SESSION['username'], "QWIKCLOCK_ADMIN");
$showmanaged = ($VARS['show_all'] == 1 && (account_has_permission($_SESSION['username'], "QWIKCLOCK_MANAGE") || $account_is_admin));
$managed_uids = [];
$managed_uids[] = $_SESSION['uid'];
if ($showmanaged) {
$managed_uids = getManagedUIDs($_SESSION['uid']);
if ($account_is_admin) {
$managed_uids = false;
} else {
$managed_uids = getManagedUIDs($_SESSION['uid']);
$managed_uids[] = $_SESSION['uid'];
}
}
$managed_uids[] = $_SESSION['uid'];
$out = [];
@ -30,13 +36,13 @@ if ($VARS['order'][0]['dir'] == 'asc') {
$sortby = "ASC";
}
switch ($VARS['order'][0]['column']) {
case 1:
case 2:
$order = ["uid" => $sortby];
break;
case 2:
case 3:
$order = ["in" => $sortby];
break;
case 3:
case 4:
$order = ["out" => $sortby];
break;
}
@ -53,10 +59,16 @@ if (!is_empty($VARS['search']['value'])) {
"uid" => $managed_uids
]
];
if ($managed_uids !== false) {
$where["AND"]["uid"] = $managed_uids;
}
$where = $wherenolimit;
$where["LIMIT"] = [$VARS['start'], $VARS['length']];
} else {
$where = ["uid" => $managed_uids, "LIMIT" => [$VARS['start'], $VARS['length']]];
$where = ["LIMIT" => [$VARS['start'], $VARS['length']]];
if ($managed_uids !== false) {
$where["uid"] = $managed_uids;
}
}
if (!is_null($order)) {
@ -65,6 +77,7 @@ if (!is_null($order)) {
$punches = $database->select('punches', [
'punchid',
'uid',
'in',
'out',
@ -73,21 +86,34 @@ $punches = $database->select('punches', [
$usercache = [];
$editself = account_has_permission($_SESSION['username'], "QWIKCLOCK_EDITSELF");
for ($i = 0; $i < count($punches); $i++) {
// Get user info
if (!isset($usercache[$punches[$i]['uid']])) {
$usercache[$punches[$i]['uid']] = getUserByID($punches[$i]['uid']);
}
$punches[$i][0] = "";
$punches[$i][1] = $usercache[$punches[$i]['uid']]['name'];
$punches[$i][2] = date(DATETIME_FORMAT, strtotime($punches[$i]['in']));
if ($_SESSION['uid'] == $punches[$i]['uid']) {
if ($editself) {
$punches[$i][1] = '<a class="btn btn-blue btn-xs" href="app.php?page=editpunch&pid=' . $punches[$i]['punchid'] . '"><i class="fa fa-pencil-square-o"></i> ' . lang("edit", false) . '</a>';
} else {
$punches[$i][1] = "";
}
} else if ($showmanaged) {
$punches[$i][1] = '<a class="btn btn-blue btn-xs" href="app.php?page=editpunch&pid=' . $punches[$i]['punchid'] . '"><i class="fa fa-pencil-square-o"></i> ' . lang("edit", false) . '</a>';
} else {
$punches[$i][1] = "";
}
$punches[$i][2] = $usercache[$punches[$i]['uid']]['name'];
$punches[$i][3] = date(DATETIME_FORMAT, strtotime($punches[$i]['in']));
if (is_null($punches[$i]['out'])) {
$punches[$i][3] = lang("na", false);
$punches[$i][4] = lang("na", false);
} else {
$punches[$i][3] = date(DATETIME_FORMAT, strtotime($punches[$i]['out']));
$punches[$i][4] = date(DATETIME_FORMAT, strtotime($punches[$i]['out']));
}
$punches[$i][4] = $punches[$i]['notes'];
$punches[$i][5] = $punches[$i]['notes'];
}
$out['status'] = "OK";

@ -51,6 +51,20 @@ define("PAGES", [
"static/js/addshift.js"
]
],
"editpunch" => [
"title" => "edit punch",
"navbar" => false,
"styles" => [
"static/css/bootstrap-datetimepicker.min.css",
"static/css/easy-autocomplete.min.css"
],
"scripts" => [
"static/js/moment.min.js",
"static/js/bootstrap-datetimepicker.min.js",
"static/js/jquery.easy-autocomplete.min.js",
"static/js/editpunch.js"
]
],
"export" => [
"title" => "report export",
"navbar" => true,

@ -0,0 +1,114 @@
<?php
require_once __DIR__ . '/../required.php';
require_once __DIR__ . '/../lib/login.php';
require_once __DIR__ . '/../lib/userinfo.php';
redirectifnotloggedin();
$data = [
"punchid" => "",
"uid" => "",
"in" => "",
"out" => "",
"notes" => "",
"username" => ""
];
$editing = false;
$ownpunch = false;
if (isset($VARS['pid']) && $database->has('punches', ['punchid' => $VARS['pid']])) {
$editing = true;
$data = $database->get('punches', [
"punchid",
"uid",
"in",
"out",
"notes",
"shiftid"
], [
'punchid' => $VARS['pid']
]);
if ($data["uid"] == $_SESSION['uid']) {
$ownpunch = true;
}
}
if ($ownpunch) {
if (!account_has_permission($_SESSION['username'], "QWIKCLOCK_EDITSELF")) {
header("Location: app.php?page=punches&msg=no_editself_permission");
die();
}
} else {
if (account_has_permission($_SESSION['username'], "QWIKCLOCK_ADMIN")) {
// All good
} else if (account_has_permission($_SESSION['username'], "QWIKCLOCK_MANAGE")) {
if ($editing && !isManagerOf($_SESSION['uid'], $data['uid'])) {
header("Location: app.php?page=punches&msg=you_arent_my_supervisor");
die();
}
} else {
header("Location: app.php?page=punches&msg=no_permission");
die();
}
}
if ($data['uid'] != "") {
$data['username'] = getUserByID($data['uid'])['username'];
}
?>
<form role="form" action="action.php" method="POST">
<div class="panel panel-blue">
<div class="panel-heading">
<h3 class="panel-title">
<?php if ($editing) { ?>
<i class="fa fa-calendar-o"></i> <?php lang("edit punch"); ?>
<?php } else { ?>
<i class="fa fa-calendar-plus-o"></i> <?php lang("new punch"); ?>
<?php } ?>
</h3>
</div>
<div class="panel-body">
<div class="row">
<div class="col-xs-12 col-sm-6 col-md-4">
<div class="form-group">
<label for="user"><i class="fa fa-user"></i> <?php lang("user"); ?></label>
<input type="text" class="form-control" name="user" id="user" required="required" value="<?php echo $data['username']; ?>" />
</div>
</div>
<div class="col-xs-12 col-sm-6 col-md-4">
<div class="form-group">
<label for="in"><i class="fa fa-play"></i> <?php lang("in"); ?></label>
<input type="text" class="form-control" name="in" id="in" required="required" value="<?php echo is_empty($data['in']) ? "" : date("D F j Y g:i a", strtotime($data['in'])); ?>" />
</div>
</div>
<div class="col-xs-12 col-sm-6 col-md-4">
<div class="form-group">
<label for="out"><i class="fa fa-stop"></i> <?php lang("out"); ?></label>
<input type="text" class="form-control" name="out" id="out" required="required" value="<?php echo is_empty($data['out']) ? "" : date("D F j Y g:i a", strtotime($data['out'])); ?>" />
</div>
</div>
<div class="col-xs-12 col-sm-6">
<div class="form-group">
<label for="notes"><i class="fa fa-sticky-note-o"></i> <?php lang("notes"); ?></label>
<textarea class="form-control" name="notes" maxlength="1000"><?php echo htmlspecialchars($data['notes']); ?></textarea>
</div>
</div>
</div>
</div>
<input type="hidden" name="punchid" value="<?php echo $data['punchid']; ?>" />
<input type="hidden" name="action" value="editpunch" />
<input type="hidden" name="source" value="punches" />
<div class="panel-footer">
<button type="submit" class="btn btn-success"><i class="fa fa-floppy-o"></i> <?php lang("save"); ?></button>
<?php
if ($editing) {
?>
<a href="action.php?action=deletepunch&source=punches&punchid=<?php echo $data['punchid']; ?>" class="btn btn-danger btn-xs pull-right mgn-top-8px"><i class="fa fa-times"></i> <?php lang('delete'); ?></a>
<?php
}
?>
</div>
</div>
</form>

@ -3,7 +3,7 @@ require_once __DIR__ . '/../required.php';
redirectifnotloggedin();
if (!account_has_permission($_SESSION['username'], "QWIKCLOCK_MANAGE")) {
if (!account_has_permission($_SESSION['username'], "QWIKCLOCK_MANAGE") && !account_has_permission($_SESSION['username'], "QWIKCLOCK_ADMIN")) {
?>
<div class="alert alert-danger"><?php lang("missing permission") ?></div>
<?php

@ -6,7 +6,8 @@ redirectifnotloggedin();
require_once __DIR__ . "/../lib/dates.php";
$weekstart = sqldatetime(getstartofweek(WEEK_START));
$punches = $database->select('punches', ['in', 'out'], ['AND' => ['uid' => $_SESSION['uid'], 'in[>]' => $weekstart]]);
$weekend = sqldatetime(getstartofweek(WEEK_START) + 604800);
$punches = $database->select('punches', ['in', 'out'], ['AND' => ['uid' => $_SESSION['uid'], 'in[>]' => $weekstart, 'in[<]' => $weekend]]);
$punchtimes = [];
foreach ($punches as $p) {
$punchtimes[] = [$p['in'], $p['out']];
@ -34,7 +35,11 @@ $totalpunches = count($punches);
<div class="panel-body">
<h4>
<?php
lang2("x punches", ["count" => $totalpunches]);
if ($totalpunches != 1) {
lang2("x punches", ["count" => $totalpunches]);
} else {
lang("1 punch");
}
?>
</h4>
</div>
@ -49,6 +54,7 @@ $totalpunches = count($punches);
<thead>
<tr>
<th data-priority="0"></th>
<th data-priority="1"><?php lang('actions'); ?></th>
<th data-priority="2"><i class="fa fa-fw fa-user hidden-xs"></i> <?php lang('name'); ?></th>
<th data-priority="1"><i class="fa fa-fw fa-play hidden-xs"></i> <?php lang('in'); ?></th>
<th data-priority="1"><i class="fa fa-fw fa-stop hidden-xs"></i> <?php lang('out'); ?></th>
@ -61,6 +67,7 @@ $totalpunches = count($punches);
<tfoot>
<tr>
<th data-priority="0"></th>
<th data-priority="1"><?php lang('actions'); ?></th>
<th data-priority="2"><i class="fa fa-fw fa-user hidden-xs"></i> <?php lang('name'); ?></th>
<th data-priority="1"><i class="fa fa-fw fa-play hidden-xs"></i> <?php lang('in'); ?></th>
<th data-priority="1"><i class="fa fa-fw fa-stop hidden-xs"></i> <?php lang('out'); ?></th>

@ -0,0 +1,37 @@
var options = {
url: "action.php",
ajaxSettings: {
dataType: "json",
method: "GET",
data: {
action: "autocomplete_user"
}
},
preparePostData: function (data) {
data.q = $("#user").val();
return data;
},
getValue: function (element) {
return element.username;
},
template: {
type: "custom",
method: function (value, item) {
return item.name + " <i class=\"small\">" + item.username + "</i>";
}
}
};
$("#user").easyAutocomplete(options);
$(function () {
$('#in').datetimepicker({
format: "ddd MMMM D YYYY h:mm a",
useCurrent: false
});
$('#out').datetimepicker({
format: "ddd MMMM D YYYY h:mm a",
useCurrent: false
});
});

@ -20,12 +20,16 @@ var punchtable = $('#punchtable').DataTable({
orderable: false
},
{
targets: 4,
targets: 1,
orderable: false
}
},
{
targets: 5,
orderable: false
},
],
order: [
[2, 'desc']
[3, 'desc']
],
serverSide: true,
ajax: {

Loading…
Cancel
Save