Finished more-or-less stable web version

This commit is contained in:
Maximilian Giller 2020-11-09 14:22:34 +01:00
parent 060ce6964c
commit d3d1b752ed
8 changed files with 284 additions and 20 deletions

View file

@ -0,0 +1,29 @@
<?php
session_start();
require_once(__DIR__ . "/services/apiBranch.inc.php");
require_once(__DIR__ . "/services/jsonBuilder.inc.php");
require_once(__DIR__ . "/services/responses.inc.php");
require_once(__DIR__ . "/services/jugglDbApi.inc.php");
class GetRunningRecordsBranch extends ApiBranch
{
function get(ParamCleaner $params)
{
respondStatus(405);
}
function post(ParamCleaner $params)
{
$user_id = $params->get("user_id");
$records = getRunningRecords($user_id);
$json = new JsonBuilder();
$json->addRecords($records);
respondJson($json);
}
}
$branch = new GetRunningRecordsBranch();
$branch->execute();

View file

@ -18,6 +18,8 @@ class JsonBuilder
function addRecords(array $records) function addRecords(array $records)
{ {
if ($records === null) return;
$columns = array( $columns = array(
"record_id" => "", "record_id" => "",
"start_time" => "", "start_time" => "",
@ -37,6 +39,8 @@ class JsonBuilder
function addProjects(array $projects) function addProjects(array $projects)
{ {
if ($projects === null) return;
$columns = array( $columns = array(
"project_id" => "", "project_id" => "",
"name" => "", "name" => "",

View file

@ -98,13 +98,12 @@ function getProjectRecord($user_id, $project_id, $finished = null)
$db->where("user_id", Comparison::EQUAL, $user_id); $db->where("user_id", Comparison::EQUAL, $user_id);
$db->where("project_id", Comparison::EQUAL, $project_id); $db->where("project_id", Comparison::EQUAL, $project_id);
if ($finished != null) { if ($finished !== null) {
$comp = Comparison::UNEQUAL; if ($finished) {
if ($finished == false) { $db->addSql(" AND end_time IS NOT NULL");
$comp = Comparison::EQUAL; } else {
$db->addSql(" AND end_time IS NULL");
} }
$db->where("end_time", $comp, null);
} }
$db->orderBy("start_time", Order::DESC); $db->orderBy("start_time", Order::DESC);
@ -123,12 +122,30 @@ function getProjectRecord($user_id, $project_id, $finished = null)
return $result; return $result;
} }
function getRunningRecords($user_id)
{
$db = new DbOperations();
$db->select("time_records");
$db->where("user_id", Comparison::EQUAL, $user_id);
$db->addSql(" AND end_time IS NULL");
$results = $db->execute();
// Is still running?
foreach ($results as $key => $value) {
$results[$key]["duration"] = calcDuration($results[$key]["start_time"]);
}
return $results;
}
function updateEndRecord($user_id, $params) function updateEndRecord($user_id, $params)
{ {
$record_id = $params->get("record_id"); $record_id = $params->get("record_id");
// Get start instance to calculate duration // Get start instance to calculate duration
$start_time = getTimeRecord($user_id, $record_id)[0]["start_time"]; $start_time = getTimeRecord($user_id, $record_id)["start_time"];
var_dump($start_time);
var_dump($params->get("end_time"));
$data = [ $data = [
"end_time" => $params->get("end_time"), "end_time" => $params->get("end_time"),
@ -202,5 +219,5 @@ function isDeviceValid($start_device_id, $user_id)
function calcDuration($start_time, $end_time = "NOW") function calcDuration($start_time, $end_time = "NOW")
{ {
return (int)((new DateTime($start_time))->diff(new DateTime($end_time))->format("%s")); return (int)(strtotime($end_time) - strtotime($start_time));
} }

View file

@ -123,3 +123,11 @@ thead * {
margin: 0px; margin: 0px;
padding: 0px; padding: 0px;
} }
#current-record-duration {
margin-bottom: 0px;
}
#update-notice {
margin-bottom: 20px;
}

View file

@ -16,15 +16,70 @@
<script src="js/helper.js"></script> <script src="js/helper.js"></script>
<script> <script>
var intervallId = undefined;
window.onblur = () => {
stopBackgroundUpdates();
}
window.onfocus = () => {
startBackgroundUpdates();
}
window.onload = () => { window.onload = () => {
// Create Callbacks // Create Callbacks
callbacks.leaving[States.PUBLIC] = () => { callbacks.entering[States.RECORDING] = () => {
loadProjectList(); updateProgess();
}; };
initState(); initState();
onLogIn();
updateVisibility(); updateVisibility();
updateAuthBtnText(); updateAuthBtnText();
startBackgroundUpdates();
}
function onLogIn() {
loadProjectList().then(() => {
checkForUpdate();
});
}
function checkForUpdate() {
if (currentRecord !== undefined) {
updateProgess();
} else {
initRunningRecords().then(() => {
if (currentRecord !== undefined) {
setState(States.RECORDING);
}
});
}
}
function updateProgess () {
if (currentRecord === undefined) {
return;
}
updateCurrentRecord().then((record) => {
if (record.end_time != null) {
currentRecord = undefined;
setState(States.IDLE);
return;
}
u("#current-project-name").text(currentProject.name);
u("#current-record-duration").text((parseInt(record.duration) / 60).toFixed(1) + " min.");
});
}
function startBackgroundUpdates () {
if (intervallId !== undefined) return;
intervallId = setInterval(checkForUpdate, 30000);
checkForUpdate();
}
function stopBackgroundUpdates () {
clearInterval(intervallId);
intervallId = undefined;
} }
</script> </script>
</head> </head>
@ -36,20 +91,28 @@
<img src="assets/logo_title.png"> <img src="assets/logo_title.png">
</li> </li>
<li style="float: right"> <li style="float: right">
<input id="user-id" class="public" type="text" placeholder="User ID" /> <input id="user-id" class="public hidden" type="text" placeholder="User ID" />
<input id="api-key" class="public" type="password" placeholder="API Key" /> <input id="api-key" class="public hidden" type="password" placeholder="API Key" />
<button id="auth-btn" onclick="handleAuthBtn()">Log In</button> <button id="auth-btn" onclick="handleAuthBtn()">Log In</button>
</li> </li>
</ul> </ul>
</header> </header>
<main> <main>
<div class="idle hidden"> <div class="idle hidden" style="text-align: center;">
<h1> <h1>
Select project to track Select project to track
</h1> </h1>
<div id="project-list"> <div id="project-list">
</div> </div>
</div> </div>
<div class="recording hidden" style="text-align: center;">
<h1>
Tracking <span id="current-project-name"></span>
</h1>
<h2 id="current-record-duration" style="color: red;"></h2>
<small id="update-notice" >Updated every 30 seconds</small><br/>
<button id="stop-btn" onclick="stopRecord()">Stop</button>
</div>
</main> </main>
</body> </body>

View file

@ -11,7 +11,65 @@ const api = {
}) })
.catch((e) => { .catch((e) => {
console.log(e); console.log(e);
return []; return {};
});
},
startRecord(projectId, startTime = new Date()) {
return request("/startRecord.php", {
project_id: projectId,
start_time: dateToString(startTime),
})
.then((r) => {
return r.json();
})
.then((j) => {
return addDuration(j.records[0]);
})
.catch((e) => {
console.log(e);
return undefined;
});
},
getRecord(recordId) {
return request("/getRecord.php", {
record_id: recordId,
})
.then((r) => {
return r.json();
})
.then((j) => {
return addDuration(j.records[0]);
})
.catch((e) => {
console.log(e);
return undefined;
});
},
getRunningRecords() {
return request("/getRunningRecords.php")
.then((r) => {
return r.json();
})
.then((j) => {
var records = Object.values(j.records);
records.forEach((r) => {
r = addDuration(r);
});
return records;
})
.catch((e) => {
console.log(e);
return undefined;
});
},
endRecord(recordId, endTime = new Date()) {
return request("/endRecord.php", {
record_id: recordId,
end_time: dateToString(endTime),
}).catch((e) => {
console.log(e);
return undefined;
}); });
}, },
}; };
@ -30,3 +88,28 @@ function request(path, json = {}, options = {}) {
return fetch(url, options); return fetch(url, options);
} }
function addDuration(record) {
if (record.end_time != null) return record;
record.duration =
(new Date().getTime() - new Date(record.start_time).getTime()) / 1000;
return record;
}
function dateToString(date) {
return (
date.getFullYear() +
"-" +
(date.getMonth() + 1) +
"-" +
date.getDate() +
" " +
date.getHours() +
":" +
date.getMinutes() +
":" +
date.getSeconds()
);
}

View file

@ -52,7 +52,3 @@ function updateAuthBtnText() {
btn.text("Log In"); btn.text("Log In");
} }
} }
function onLogIn() {
loadProjectList();
}

View file

@ -1,9 +1,14 @@
const PROJECT_OBJECT = "div"; const PROJECT_OBJECT = "div";
const PROJECT_TITLE = "h1"; const PROJECT_TITLE = "h1";
const PROJECT_META = "p"; const PROJECT_META = "p";
let currentRecord = undefined;
let currentProject = undefined;
let projectList = undefined;
function loadProjectList() { function loadProjectList() {
api.getProjects().then((projects) => { return api.getProjects().then((projects) => {
projectList = Object.values(projects);
var container = u(u("#project-list").first()); var container = u(u("#project-list").first());
Object.values(projects).forEach((project) => { Object.values(projects).forEach((project) => {
var obj = createNode(PROJECT_OBJECT); var obj = createNode(PROJECT_OBJECT);
@ -46,5 +51,64 @@ function append(parent, el) {
} }
function projectClicked(event) { function projectClicked(event) {
console.log(event); var projectObject = event.target;
if (projectObject.tagName !== "DIV") {
projectObject = projectObject.parentElement;
}
var projectId = u(projectObject).data("project-id");
return api.startRecord(projectId).then((record) => {
currentRecord = record;
currentProject = getProjectById(record.project_id);
setState(States.RECORDING);
});
}
function getProjectById(id) {
for (let i = 0; i < projectList.length; i++) {
const element = projectList[i];
if (element.project_id == id) {
return element;
}
}
return undefined;
}
function updateCurrentRecord() {
if (currentRecord === undefined) {
return;
}
return api.getRecord(currentRecord.record_id).then((record) => {
currentRecord = record;
currentProject = getProjectById(record.project_id);
return record;
});
}
function stopRecord() {
if (currentRecord === undefined) {
return;
}
return api.endRecord(currentRecord.record_id).then(() => {
setState(States.IDLE);
currentRecord = undefined;
});
}
function initRunningRecords() {
return api.getRunningRecords().then((records) => {
if (records === undefined || records.length <= 0) {
currentRecord = undefined;
return;
}
// Assuming, there is only one
currentRecord = records[0];
});
} }