Finished more-or-less stable web version
This commit is contained in:
parent
060ce6964c
commit
d3d1b752ed
8 changed files with 284 additions and 20 deletions
29
juggl-server/api/getRunningRecords.php
Normal file
29
juggl-server/api/getRunningRecords.php
Normal 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();
|
|
@ -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" => "",
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
|
@ -123,3 +123,11 @@ thead * {
|
||||||
margin: 0px;
|
margin: 0px;
|
||||||
padding: 0px;
|
padding: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#current-record-duration {
|
||||||
|
margin-bottom: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#update-notice {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
|
@ -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>
|
||||||
|
|
||||||
|
|
|
@ -11,9 +11,67 @@ 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;
|
||||||
|
});
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
function request(path, json = {}, options = {}) {
|
function request(path, json = {}, options = {}) {
|
||||||
|
@ -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()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
@ -52,7 +52,3 @@ function updateAuthBtnText() {
|
||||||
btn.text("Log In");
|
btn.text("Log In");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onLogIn() {
|
|
||||||
loadProjectList();
|
|
||||||
}
|
|
||||||
|
|
|
@ -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];
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue