mirror of
https://github.com/grocy/grocy.git
synced 2025-04-29 09:39:57 +00:00
Added possibility to manage rechargeable batteries
This commit is contained in:
parent
dad6322bac
commit
2d5ed67ae1
@ -131,6 +131,35 @@ class GrocyDbMigrator
|
||||
GROUP BY habit_id
|
||||
ORDER BY MAX(tracked_time) DESC;"
|
||||
);
|
||||
|
||||
self::ExecuteMigrationWhenNeeded($pdo, 13, "
|
||||
CREATE TABLE batteries (
|
||||
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
description TEXT,
|
||||
used_in TEXT,
|
||||
charge_interval_days INTEGER NOT NULL DEFAULT 0,
|
||||
row_created_timestamp DATETIME DEFAULT (datetime('now', 'localtime'))
|
||||
)"
|
||||
);
|
||||
|
||||
self::ExecuteMigrationWhenNeeded($pdo, 14, "
|
||||
CREATE TABLE battery_charge_cycles (
|
||||
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
|
||||
battery_id TEXT NOT NULL,
|
||||
tracked_time DATETIME,
|
||||
row_created_timestamp DATETIME DEFAULT (datetime('now', 'localtime'))
|
||||
)"
|
||||
);
|
||||
|
||||
self::ExecuteMigrationWhenNeeded($pdo, 15, "
|
||||
CREATE VIEW batteries_current
|
||||
AS
|
||||
SELECT battery_id, MAX(tracked_time) AS last_tracked_time
|
||||
FROM battery_charge_cycles
|
||||
GROUP BY battery_id
|
||||
ORDER BY MAX(tracked_time) DESC;"
|
||||
);
|
||||
}
|
||||
|
||||
private static function ExecuteMigrationWhenNeeded(PDO $pdo, int $migrationId, string $sql)
|
||||
|
@ -9,11 +9,11 @@ class GrocyDemoDataGenerator
|
||||
{
|
||||
$sql = "
|
||||
UPDATE locations SET name = 'Vorratskammer', description = '' WHERE id = 1;
|
||||
INSERT INTO locations (name) VALUES ('Süßigkeitenschrank'); --2
|
||||
INSERT INTO locations (name) VALUES ('S<EFBFBD><EFBFBD>igkeitenschrank'); --2
|
||||
INSERT INTO locations (name) VALUES ('Konservenschrank'); --3
|
||||
INSERT INTO locations (name) VALUES ('Kühlschrank'); --4
|
||||
INSERT INTO locations (name) VALUES ('K<EFBFBD>hlschrank'); --4
|
||||
|
||||
UPDATE quantity_units SET name = 'Stück' WHERE id = 1;
|
||||
UPDATE quantity_units SET name = 'St<EFBFBD>ck' WHERE id = 1;
|
||||
INSERT INTO quantity_units (name) VALUES ('Packung'); --2
|
||||
INSERT INTO quantity_units (name) VALUES ('Glas'); --3
|
||||
INSERT INTO quantity_units (name) VALUES ('Dose'); --4
|
||||
@ -21,14 +21,14 @@ class GrocyDemoDataGenerator
|
||||
INSERT INTO quantity_units (name) VALUES ('Bund'); --6
|
||||
|
||||
DELETE FROM products WHERE id IN (1, 2);
|
||||
INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock, min_stock_amount) VALUES ('Gummibärchen', 2, 2, 2, 1, 8); --3
|
||||
INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock, min_stock_amount) VALUES ('Gummib<EFBFBD>rchen', 2, 2, 2, 1, 8); --3
|
||||
INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock, min_stock_amount) VALUES ('Chips', 2, 2, 2, 1, 10); --4
|
||||
INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock) VALUES ('Eier', 1, 2, 1, 10); --5
|
||||
INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock) VALUES ('Nudeln', 1, 2, 2, 1); --6
|
||||
INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock) VALUES ('Essiggurken', 3, 3, 3, 1); --7
|
||||
INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock) VALUES ('Gulaschsuppe', 3, 4, 4, 1); --8
|
||||
INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock) VALUES ('Joghurt', 4, 5, 5, 1); --9
|
||||
INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock) VALUES ('Käse', 4, 2, 2, 1); --10
|
||||
INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock) VALUES ('K<EFBFBD>se', 4, 2, 2, 1); --10
|
||||
INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock) VALUES ('Aufschnitt', 4, 2, 2, 1); --11
|
||||
INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock) VALUES ('Paprika', 4, 1, 1, 1); --12
|
||||
INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock) VALUES ('Gurke', 4, 1, 1, 1); --13
|
||||
@ -38,6 +38,10 @@ class GrocyDemoDataGenerator
|
||||
INSERT INTO habits (name, period_type, period_days) VALUES ('Changed towels in the bathroom', 'manually', 5); --1
|
||||
INSERT INTO habits (name, period_type, period_days) VALUES ('Cleaned the kitchen floor', 'dynamic-regular', 7); --2
|
||||
|
||||
INSERT INTO batteries (name, description, used_in) VALUES ('Battery1', 'Warranty ends 2022', 'TV remote control'); --1
|
||||
INSERT INTO batteries (name, description, used_in) VALUES ('Battery2', 'Warranty ends 2022', 'Alarm clock'); --2
|
||||
INSERT INTO batteries (name, description, used_in, charge_interval_days) VALUES ('Battery3', 'Warranty ends 2022', 'Heat remote control', 60); --3
|
||||
|
||||
INSERT INTO migrations (migration) VALUES (-1);
|
||||
";
|
||||
|
||||
@ -63,6 +67,16 @@ class GrocyDemoDataGenerator
|
||||
GrocyLogicHabits::TrackHabit(1, date('Y-m-d H:i:s', strtotime('-15 days')));
|
||||
GrocyLogicHabits::TrackHabit(2, date('Y-m-d H:i:s', strtotime('-10 days')));
|
||||
GrocyLogicHabits::TrackHabit(2, date('Y-m-d H:i:s', strtotime('-20 days')));
|
||||
|
||||
GrocyLogicBatteries::TrackChargeCycle(1, date('Y-m-d H:i:s', strtotime('-200 days')));
|
||||
GrocyLogicBatteries::TrackChargeCycle(1, date('Y-m-d H:i:s', strtotime('-150 days')));
|
||||
GrocyLogicBatteries::TrackChargeCycle(1, date('Y-m-d H:i:s', strtotime('-100 days')));
|
||||
GrocyLogicBatteries::TrackChargeCycle(1, date('Y-m-d H:i:s', strtotime('-50 days')));
|
||||
GrocyLogicBatteries::TrackChargeCycle(2, date('Y-m-d H:i:s', strtotime('-200 days')));
|
||||
GrocyLogicBatteries::TrackChargeCycle(2, date('Y-m-d H:i:s', strtotime('-150 days')));
|
||||
GrocyLogicBatteries::TrackChargeCycle(2, date('Y-m-d H:i:s', strtotime('-100 days')));
|
||||
GrocyLogicBatteries::TrackChargeCycle(2, date('Y-m-d H:i:s', strtotime('-50 days')));
|
||||
GrocyLogicBatteries::TrackChargeCycle(3, date('Y-m-d H:i:s', strtotime('-65 days')));
|
||||
}
|
||||
}
|
||||
|
||||
|
57
GrocyLogicBatteries.php
Normal file
57
GrocyLogicBatteries.php
Normal file
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
class GrocyLogicBatteries
|
||||
{
|
||||
public static function GetCurrent()
|
||||
{
|
||||
$sql = 'SELECT * from batteries_current';
|
||||
return Grocy::ExecuteDbQuery(Grocy::GetDbConnectionRaw(), $sql)->fetchAll(PDO::FETCH_OBJ);
|
||||
}
|
||||
|
||||
public static function GetNextChargeTime(int $batteryId)
|
||||
{
|
||||
$db = Grocy::GetDbConnection();
|
||||
|
||||
$battery = $db->batteries($batteryId);
|
||||
$batteryLastLogRow = Grocy::ExecuteDbQuery(Grocy::GetDbConnectionRaw(), "SELECT * from batteries_current WHERE battery_id = $batteryId LIMIT 1")->fetch(PDO::FETCH_OBJ);
|
||||
|
||||
if ($battery->charge_interval_days > 0)
|
||||
{
|
||||
return date('Y-m-d H:i:s', strtotime('+' . $battery->charge_interval_days . ' day', strtotime($batteryLastLogRow->last_tracked_time)));
|
||||
}
|
||||
else
|
||||
{
|
||||
return date('Y-m-d H:i:s');
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static function GetBatteryDetails(int $batteryId)
|
||||
{
|
||||
$db = Grocy::GetDbConnection();
|
||||
|
||||
$battery = $db->batteries($batteryId);
|
||||
$batteryChargeCylcesCount = $db->battery_charge_cycles()->where('battery_id', $batteryId)->count();
|
||||
$batteryLastChargedTime = $db->battery_charge_cycles()->where('battery_id', $batteryId)->max('tracked_time');
|
||||
|
||||
return array(
|
||||
'battery' => $battery,
|
||||
'last_charged' => $batteryLastChargedTime,
|
||||
'charge_cycles_count' => $batteryChargeCylcesCount
|
||||
);
|
||||
}
|
||||
|
||||
public static function TrackChargeCycle(int $batteryId, string $trackedTime)
|
||||
{
|
||||
$db = Grocy::GetDbConnection();
|
||||
|
||||
$logRow = $db->battery_charge_cycles()->createRow(array(
|
||||
'battery_id' => $batteryId,
|
||||
'tracked_time' => $trackedTime
|
||||
));
|
||||
$logRow->save();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
66
index.php
66
index.php
@ -11,6 +11,7 @@ require_once __DIR__ . '/GrocyDbMigrator.php';
|
||||
require_once __DIR__ . '/GrocyDemoDataGenerator.php';
|
||||
require_once __DIR__ . '/GrocyLogicStock.php';
|
||||
require_once __DIR__ . '/GrocyLogicHabits.php';
|
||||
require_once __DIR__ . '/GrocyLogicBatteries.php';
|
||||
require_once __DIR__ . '/GrocyPhpHelper.php';
|
||||
|
||||
$app = new \Slim\App;
|
||||
@ -122,6 +123,16 @@ $app->get('/habitsoverview', function(Request $request, Response $response) use(
|
||||
]);
|
||||
});
|
||||
|
||||
$app->get('/batteriesoverview', function(Request $request, Response $response) use($db)
|
||||
{
|
||||
return $this->renderer->render($response, '/layout.php', [
|
||||
'title' => 'Batteries overview',
|
||||
'contentPage' => 'batteriesoverview.php',
|
||||
'batteries' => $db->batteries(),
|
||||
'current' => GrocyLogicBatteries::GetCurrent(),
|
||||
]);
|
||||
});
|
||||
|
||||
$app->get('/purchase', function(Request $request, Response $response) use($db)
|
||||
{
|
||||
return $this->renderer->render($response, '/layout.php', [
|
||||
@ -170,6 +181,15 @@ $app->get('/habittracking', function(Request $request, Response $response) use($
|
||||
]);
|
||||
});
|
||||
|
||||
$app->get('/batterytracking', function(Request $request, Response $response) use($db)
|
||||
{
|
||||
return $this->renderer->render($response, '/layout.php', [
|
||||
'title' => 'Battery tracking',
|
||||
'contentPage' => 'batterytracking.php',
|
||||
'batteries' => $db->batteries()
|
||||
]);
|
||||
});
|
||||
|
||||
$app->get('/products', function(Request $request, Response $response) use($db)
|
||||
{
|
||||
return $this->renderer->render($response, '/layout.php', [
|
||||
@ -208,6 +228,15 @@ $app->get('/habits', function(Request $request, Response $response) use($db)
|
||||
]);
|
||||
});
|
||||
|
||||
$app->get('/batteries', function(Request $request, Response $response) use($db)
|
||||
{
|
||||
return $this->renderer->render($response, '/layout.php', [
|
||||
'title' => 'Batteries',
|
||||
'contentPage' => 'batteries.php',
|
||||
'batteries' => $db->batteries()
|
||||
]);
|
||||
});
|
||||
|
||||
|
||||
$app->get('/product/{productId}', function(Request $request, Response $response, $args) use($db)
|
||||
{
|
||||
@ -299,6 +328,27 @@ $app->get('/habit/{habitId}', function(Request $request, Response $response, $ar
|
||||
}
|
||||
});
|
||||
|
||||
$app->get('/battery/{batteryId}', function(Request $request, Response $response, $args) use($db)
|
||||
{
|
||||
if ($args['batteryId'] == 'new')
|
||||
{
|
||||
return $this->renderer->render($response, '/layout.php', [
|
||||
'title' => 'Create battery',
|
||||
'contentPage' => 'batteryform.php',
|
||||
'mode' => 'create'
|
||||
]);
|
||||
}
|
||||
else
|
||||
{
|
||||
return $this->renderer->render($response, '/layout.php', [
|
||||
'title' => 'Edit battery',
|
||||
'contentPage' => 'batteryform.php',
|
||||
'battery' => $db->batteries($args['batteryId']),
|
||||
'mode' => 'edit'
|
||||
]);
|
||||
}
|
||||
});
|
||||
|
||||
$app->get('/shoppinglistitem/{itemId}', function(Request $request, Response $response, $args) use($db)
|
||||
{
|
||||
if ($args['itemId'] == 'new')
|
||||
@ -434,6 +484,22 @@ $app->group('/api', function() use($db)
|
||||
{
|
||||
echo json_encode(GrocyLogicHabits::GetHabitDetails($args['habitId']));
|
||||
});
|
||||
|
||||
$this->get('/batteries/track-charge-cycle/{batteryId}', function(Request $request, Response $response, $args)
|
||||
{
|
||||
$trackedTime = date('Y-m-d H:i:s');
|
||||
if (isset($request->getQueryParams()['tracked_time']) && !empty($request->getQueryParams()['tracked_time']))
|
||||
{
|
||||
$trackedTime = $request->getQueryParams()['tracked_time'];
|
||||
}
|
||||
|
||||
echo json_encode(array('success' => GrocyLogicBatteries::TrackChargeCycle($args['batteryId'], $trackedTime)));
|
||||
});
|
||||
|
||||
$this->get('/batteries/get-battery-details/{batteryId}', function(Request $request, Response $response, $args)
|
||||
{
|
||||
echo json_encode(GrocyLogicBatteries::GetBatteryDetails($args['batteryId']));
|
||||
});
|
||||
})->add(function($request, $response, $next)
|
||||
{
|
||||
$response = $next($request, $response);
|
||||
|
43
views/batteries.js
Normal file
43
views/batteries.js
Normal file
@ -0,0 +1,43 @@
|
||||
$(document).on('click', '.battery-delete-button', function(e)
|
||||
{
|
||||
bootbox.confirm({
|
||||
message: 'Delete battery <strong>' + $(e.target).attr('data-battery-name') + '</strong>?',
|
||||
buttons: {
|
||||
confirm: {
|
||||
label: 'Yes',
|
||||
className: 'btn-success'
|
||||
},
|
||||
cancel: {
|
||||
label: 'No',
|
||||
className: 'btn-danger'
|
||||
}
|
||||
},
|
||||
callback: function(result)
|
||||
{
|
||||
if (result === true)
|
||||
{
|
||||
Grocy.FetchJson('/api/delete-object/batteries/' + $(e.target).attr('data-battery-id'),
|
||||
function(result)
|
||||
{
|
||||
window.location.href = '/batteries';
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$(function()
|
||||
{
|
||||
$('#batteries-table').DataTable({
|
||||
'pageLength': 50,
|
||||
'order': [[1, 'asc']],
|
||||
'columnDefs': [
|
||||
{ 'orderable': false, 'targets': 0 }
|
||||
]
|
||||
});
|
||||
});
|
46
views/batteries.php
Normal file
46
views/batteries.php
Normal file
@ -0,0 +1,46 @@
|
||||
<div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
|
||||
|
||||
<h1 class="page-header">
|
||||
Batteries
|
||||
<a class="btn btn-default" href="/battery/new" role="button">
|
||||
<i class="fa fa-plus"></i> Add
|
||||
</a>
|
||||
</h1>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table id="batteries-table" class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>Name</th>
|
||||
<th>Description</th>
|
||||
<th>Used in</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($batteries as $battery) : ?>
|
||||
<tr>
|
||||
<td class="fit-content">
|
||||
<a class="btn btn-info" href="/battery/<?php echo $battery->id; ?>" role="button">
|
||||
<i class="fa fa-pencil"></i>
|
||||
</a>
|
||||
<a class="btn btn-danger battery-delete-button" href="#" role="button" data-battery-id="<?php echo $battery->id; ?>" data-battery-name="<?php echo $battery->name; ?>">
|
||||
<i class="fa fa-trash"></i>
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<?php echo $battery->name; ?>
|
||||
</td>
|
||||
<td>
|
||||
<?php echo $battery->description; ?>
|
||||
</td>
|
||||
<td>
|
||||
<?php echo $battery->used_in; ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</div>
|
7
views/batteriesoverview.js
Normal file
7
views/batteriesoverview.js
Normal file
@ -0,0 +1,7 @@
|
||||
$(function()
|
||||
{
|
||||
$('#habits-overview-table').DataTable({
|
||||
'pageLength': 50,
|
||||
'order': [[1, 'desc']]
|
||||
});
|
||||
});
|
38
views/batteriesoverview.php
Normal file
38
views/batteriesoverview.php
Normal file
@ -0,0 +1,38 @@
|
||||
<div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
|
||||
|
||||
<h1 class="page-header">Batteries overview</h1>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table id="batteries-overview-table" class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Battery</th>
|
||||
<th>Last charged</th>
|
||||
<th>Next planned charge cycle</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($current as $curentBatteryEntry) : ?>
|
||||
<tr class="<?php if (GrocyPhpHelper::FindObjectInArrayByPropertyValue($batteries, 'id', $curentBatteryEntry->battery_id)->charge_interval_days > 0 && GrocyLogicBatteries::GetNextChargeTime($curentBatteryEntry->battery_id) < date('Y-m-d H:i:s')) echo 'error-bg'; ?>">
|
||||
<td>
|
||||
<?php echo GrocyPhpHelper::FindObjectInArrayByPropertyValue($batteries, 'id', $curentBatteryEntry->battery_id)->name; ?>
|
||||
</td>
|
||||
<td>
|
||||
<?php echo $curentBatteryEntry->last_tracked_time; ?>
|
||||
<time class="timeago timeago-contextual" datetime="<?php echo $curentBatteryEntry->last_tracked_time; ?>"></time>
|
||||
</td>
|
||||
<td>
|
||||
<?php if (GrocyPhpHelper::FindObjectInArrayByPropertyValue($batteries, 'id', $curentBatteryEntry->battery_id)->charge_interval_days > 0): ?>
|
||||
<?php echo GrocyLogicBatteries::GetNextChargeTime($curentBatteryEntry->battery_id); ?>
|
||||
<time class="timeago timeago-contextual" datetime="<?php echo GrocyLogicBatteries::GetNextChargeTime($curentBatteryEntry->battery_id); ?>"></time>
|
||||
<?php else: ?>
|
||||
Whenever you want...
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</div>
|
38
views/batteryform.js
Normal file
38
views/batteryform.js
Normal file
@ -0,0 +1,38 @@
|
||||
$('#save-battery-button').on('click', function(e)
|
||||
{
|
||||
e.preventDefault();
|
||||
|
||||
if (Grocy.EditMode === 'create')
|
||||
{
|
||||
Grocy.PostJson('/api/add-object/batteries', $('#battery-form').serializeJSON(),
|
||||
function(result)
|
||||
{
|
||||
window.location.href = '/batteries';
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
Grocy.PostJson('/api/edit-object/batteries/' + Grocy.EditObjectId, $('#battery-form').serializeJSON(),
|
||||
function(result)
|
||||
{
|
||||
window.location.href = '/batteries';
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
$(function()
|
||||
{
|
||||
$('#name').focus();
|
||||
$('#battery-form').validator();
|
||||
$('#battery-form').validator('validate');
|
||||
});
|
33
views/batteryform.php
Normal file
33
views/batteryform.php
Normal file
@ -0,0 +1,33 @@
|
||||
<div class="col-sm-3 col-sm-offset-3 col-md-4 col-md-offset-2 main">
|
||||
|
||||
<h1 class="page-header"><?php echo $title; ?></h1>
|
||||
|
||||
<script>Grocy.EditMode = '<?php echo $mode; ?>';</script>
|
||||
|
||||
<?php if ($mode == 'edit') : ?>
|
||||
<script>Grocy.EditObjectId = <?php echo $battery->id; ?>;</script>
|
||||
<?php endif; ?>
|
||||
|
||||
<form id="battery-form">
|
||||
|
||||
<div class="form-group">
|
||||
<label for="name">Name</label>
|
||||
<input type="text" class="form-control" required id="name" name="name" value="<?php if ($mode == 'edit') echo $battery->name; ?>">
|
||||
<div class="help-block with-errors"></div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="description">Description</label>
|
||||
<input type="text" class="form-control" id="description" name="description" value="<?php if ($mode == 'edit') echo $battery->description; ?>">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="name">Used in</label>
|
||||
<input type="text" class="form-control" id="used_in" name="used_in" value="<?php if ($mode == 'edit') echo $battery->used_in; ?>">
|
||||
</div>
|
||||
|
||||
<button id="save-battery-button" type="submit" class="btn btn-default">Save</button>
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
167
views/batterytracking.js
Normal file
167
views/batterytracking.js
Normal file
@ -0,0 +1,167 @@
|
||||
$('#save-batterytracking-button').on('click', function(e)
|
||||
{
|
||||
e.preventDefault();
|
||||
|
||||
var jsonForm = $('#batterytracking-form').serializeJSON();
|
||||
|
||||
Grocy.FetchJson('/api/batteries/get-battery-details/' + jsonForm.battery_id,
|
||||
function (batteryDetails)
|
||||
{
|
||||
Grocy.FetchJson('/api/batteries/track-charge-cycle/' + jsonForm.battery_id + '?tracked_time=' + $('#tracked_time').val(),
|
||||
function(result)
|
||||
{
|
||||
toastr.success('Tracked charge cylce of battery ' + batteryDetails.battery.name + ' on ' + $('#tracked_time').val());
|
||||
|
||||
$('#battery_id').val('');
|
||||
$('#battery_id_text_input').focus();
|
||||
$('#battery_id_text_input').val('');
|
||||
$('#tracked_time').val(moment().format('YYYY-MM-DD HH:mm:ss'));
|
||||
$('#tracked_time').trigger('change');
|
||||
$('#battery_id_text_input').trigger('change');
|
||||
$('#batterytracking-form').validator('validate');
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
$('#battery_id').on('change', function(e)
|
||||
{
|
||||
var batteryId = $(e.target).val();
|
||||
|
||||
if (batteryId)
|
||||
{
|
||||
Grocy.FetchJson('/api/batteries/get-battery-details/' + batteryId,
|
||||
function(batteryDetails)
|
||||
{
|
||||
$('#selected-battery-name').text(batteryDetails.battery.name);
|
||||
$('#selected-battery-last-charged').text((batteryDetails.last_charged || 'never'));
|
||||
$('#selected-battery-last-charged-timeago').text($.timeago(batteryDetails.last_charged || ''));
|
||||
$('#selected-battery-charge-cycles-count').text((batteryDetails.charge_cycles_count || '0'));
|
||||
|
||||
$('#tracked_time').focus();
|
||||
|
||||
Grocy.EmptyElementWhenMatches('#selected-battery-last-charged-timeago', 'NaN years ago');
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
$(function()
|
||||
{
|
||||
$('.datetimepicker').datetimepicker(
|
||||
{
|
||||
format: 'YYYY-MM-DD HH:mm:ss',
|
||||
showTodayButton: true,
|
||||
calendarWeeks: true,
|
||||
maxDate: moment()
|
||||
});
|
||||
|
||||
$('#tracked_time').val(moment().format('YYYY-MM-DD HH:mm:ss'));
|
||||
$('#tracked_time').trigger('change');
|
||||
|
||||
$('#tracked_time').on('focus', function(e)
|
||||
{
|
||||
if ($('#battery_id_text_input').val().length === 0)
|
||||
{
|
||||
$('#battery_id_text_input').focus();
|
||||
}
|
||||
});
|
||||
|
||||
$('.combobox').combobox({
|
||||
appendId: '_text_input'
|
||||
});
|
||||
|
||||
$('#battery_id').val('');
|
||||
$('#battery_id_text_input').focus();
|
||||
$('#battery_id_text_input').val('');
|
||||
$('#battery_id_text_input').trigger('change');
|
||||
|
||||
$('#batterytracking-form').validator();
|
||||
$('#batterytracking-form').validator('validate');
|
||||
|
||||
$('#batterytracking-form input').keydown(function(event)
|
||||
{
|
||||
if (event.keyCode === 13) //Enter
|
||||
{
|
||||
if ($('#batterytracking-form').validator('validate').has('.has-error').length !== 0) //There is at least one validation error
|
||||
{
|
||||
event.preventDefault();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$('#tracked_time').on('change', function(e)
|
||||
{
|
||||
var value = $('#tracked_time').val();
|
||||
var now = new Date();
|
||||
var centuryStart = Number.parseInt(now.getFullYear().toString().substring(0, 2) + '00');
|
||||
var centuryEnd = Number.parseInt(now.getFullYear().toString().substring(0, 2) + '99');
|
||||
|
||||
if (value === 'x' || value === 'X') {
|
||||
value = '29991231';
|
||||
}
|
||||
|
||||
if (value.length === 4 && !(Number.parseInt(value) > centuryStart && Number.parseInt(value) < centuryEnd))
|
||||
{
|
||||
value = (new Date()).getFullYear().toString() + value;
|
||||
}
|
||||
|
||||
if (value.length === 8 && $.isNumeric(value))
|
||||
{
|
||||
value = value.replace(/(\d{4})(\d{2})(\d{2})/, '$1-$2-$3');
|
||||
$('#tracked_time').val(value);
|
||||
$('#batterytracking-form').validator('validate');
|
||||
}
|
||||
});
|
||||
|
||||
$('#tracked_time').on('keypress', function(e)
|
||||
{
|
||||
var element = $(e.target);
|
||||
var value = element.val();
|
||||
var dateObj = moment(element.val(), 'YYYY-MM-DD', true);
|
||||
|
||||
$('.datepicker').datepicker('hide');
|
||||
|
||||
//If input is empty and any arrow key is pressed, set date to today
|
||||
if (value.length === 0 && (e.keyCode === 38 || e.keyCode === 40 || e.keyCode === 37 || e.keyCode === 39))
|
||||
{
|
||||
dateObj = moment(new Date(), 'YYYY-MM-DD', true);
|
||||
}
|
||||
|
||||
if (dateObj.isValid())
|
||||
{
|
||||
if (e.keyCode === 38) //Up
|
||||
{
|
||||
element.val(dateObj.add(-1, 'days').format('YYYY-MM-DD'));
|
||||
}
|
||||
else if (e.keyCode === 40) //Down
|
||||
{
|
||||
element.val(dateObj.add(1, 'days').format('YYYY-MM-DD'));
|
||||
}
|
||||
else if (e.keyCode === 37) //Left
|
||||
{
|
||||
element.val(dateObj.add(-1, 'weeks').format('YYYY-MM-DD'));
|
||||
}
|
||||
else if (e.keyCode === 39) //Right
|
||||
{
|
||||
element.val(dateObj.add(1, 'weeks').format('YYYY-MM-DD'));
|
||||
}
|
||||
}
|
||||
|
||||
$('#batterytracking-form').validator('validate');
|
||||
});
|
42
views/batterytracking.php
Normal file
42
views/batterytracking.php
Normal file
@ -0,0 +1,42 @@
|
||||
<div class="col-sm-3 col-sm-offset-3 col-md-3 col-md-offset-2 main">
|
||||
|
||||
<h1 class="page-header">Battery tracking</h1>
|
||||
|
||||
<form id="batterytracking-form">
|
||||
|
||||
<div class="form-group">
|
||||
<label for="battery_id">Battery</label>
|
||||
<select class="form-control combobox" id="battery_id" name="battery_id" required>
|
||||
<option value=""></option>
|
||||
<?php foreach ($batteries as $battery) : ?>
|
||||
<option value="<?php echo $battery->id; ?>"><?php echo $battery->name; ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<div id="battery-error" class="help-block with-errors"></div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="tracked_time">Tracked time</label>
|
||||
<div class="input-group date datetimepicker">
|
||||
<input type="text" class="form-control" id="tracked_time" name="tracked_time" required >
|
||||
<span class="input-group-addon">
|
||||
<span class="fa fa-calendar"></span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="help-block with-errors"></div>
|
||||
</div>
|
||||
|
||||
<button id="save-batterytracking-button" type="submit" class="btn btn-default">OK</button>
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="col-sm-6 col-md-5 col-lg-3 main well">
|
||||
<h3>Battery overview <strong><span id="selected-battery-name"></span></strong></h3>
|
||||
|
||||
<p>
|
||||
<strong>Charge cycles count:</strong> <span id="selected-battery-charge-cycles-count"></span><br>
|
||||
<strong>Last charged:</strong> <span id="selected-battery-last-charged"></span> <time id="selected-battery-last-charged-timeago" class="timeago timeago-contextual"></time><br>
|
||||
</p>
|
||||
</div>
|
@ -58,6 +58,9 @@
|
||||
<li data-nav-for-page="habitsoverview.php">
|
||||
<a class="discrete-link" href="/habitsoverview"><i class="fa fa-tachometer fa-fw"></i> Habits overview</a>
|
||||
</li>
|
||||
<li data-nav-for-page="batteriesoverview.php">
|
||||
<a class="discrete-link" href="/batteriesoverview"><i class="fa fa-tachometer fa-fw"></i> Batteries overview</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
@ -76,6 +79,9 @@
|
||||
<li data-nav-for-page="habittracking.php">
|
||||
<a class="discrete-link" href="/habittracking"><i class="fa fa-play fa-fw"></i> Habit tracking</a>
|
||||
</li>
|
||||
<li data-nav-for-page="batterytracking.php">
|
||||
<a class="discrete-link" href="/batterytracking"><i class="fa fa-fire fa-fw"></i> Track battery charge cycle</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
@ -92,6 +98,9 @@
|
||||
<li data-nav-for-page="habits.php">
|
||||
<a class="discrete-link" href="/habits"><i class="fa fa-refresh fa-fw"></i> Habits</a>
|
||||
</li>
|
||||
<li data-nav-for-page="batteries.php">
|
||||
<a class="discrete-link" href="/batteries"><i class="fa fa-battery-three-quarters fa-fw"></i> Batteries</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
@ -116,6 +125,9 @@
|
||||
<li data-nav-for-page="habitsoverview.php">
|
||||
<a class="discrete-link" href="/habitsoverview"><i class="fa fa-tachometer fa-fw"></i> Habits overview</a>
|
||||
</li>
|
||||
<li data-nav-for-page="batteriesoverview.php">
|
||||
<a class="discrete-link" href="/batteriesoverview"><i class="fa fa-tachometer fa-fw"></i> Batteries overview</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ul class="nav nav-sidebar">
|
||||
@ -134,6 +146,9 @@
|
||||
<li data-nav-for-page="habittracking.php">
|
||||
<a class="discrete-link" href="/habittracking"><i class="fa fa-play fa-fw"></i> Habit tracking</a>
|
||||
</li>
|
||||
<li data-nav-for-page="batterytracking.php">
|
||||
<a class="discrete-link" href="/batterytracking"><i class="fa fa-fire fa-fw"></i> Track battery charge cycle</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ul class="nav nav-sidebar">
|
||||
@ -150,6 +165,9 @@
|
||||
<li data-nav-for-page="habits.php">
|
||||
<a class="discrete-link" href="/habits"><i class="fa fa-refresh fa-fw"></i> Habits</a>
|
||||
</li>
|
||||
<li data-nav-for-page="batteries.php">
|
||||
<a class="discrete-link" href="/batteries"><i class="fa fa-battery-three-quarters fa-fw"></i> Batteries</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="nav-copyright nav nav-sidebar">
|
||||
|
Loading…
x
Reference in New Issue
Block a user