diff --git a/build.bat b/build.bat
index 6a01a6b4..aa887f14 100644
--- a/build.bat
+++ b/build.bat
@@ -4,7 +4,7 @@ if %projectPath:~-1%==\ set projectPath=%projectPath:~0,-1%
set releasePath=%projectPath%\.release
mkdir "%releasePath%"
-for /f "tokens=*" %%a in ('type version.txt') do set version=%%a
+for /f "tokens=*" %%a in ('build_tools\jq.exe .Version version.json --raw-output') do set version=%%a
del "%releasePath%\grocy_%version%.zip"
"build_tools\7za.exe" a -r "%releasePath%\grocy_%version%.zip" "%projectPath%\*" -xr!.* -xr!build_tools -xr!build.bat -xr!composer.json -xr!composer.lock -xr!package.json -xr!yarn.lock -xr!publication_assets
diff --git a/build_tools/jq.exe b/build_tools/jq.exe
new file mode 100644
index 00000000..81685175
Binary files /dev/null and b/build_tools/jq.exe differ
diff --git a/localization/de.php b/localization/de.php
index 60c42def..de51f17d 100644
--- a/localization/de.php
+++ b/localization/de.php
@@ -131,6 +131,7 @@ return array(
'Track execution of habit #1' => 'Erfasse eine Ausführung von #1',
'Filter by location' => 'Nach Standort filtern',
'Search' => 'Suche',
+ 'Not logged in' => 'Nicht angemeldet',
//Constants
'manually' => 'Manuell',
diff --git a/package.json b/package.json
index fcf53332..57934326 100644
--- a/package.json
+++ b/package.json
@@ -3,14 +3,15 @@
"private": true,
"dependencies": {
"bootstrap": "^4.1.1",
+ "startbootstrap-sb-admin": "^4.0.0",
"jquery": "^3.3.1",
"font-awesome": "^4.7.0",
- "bootbox": "^4.4.0",
+ "bootbox": "https://github.com/makeusabrew/bootbox.git#v5.x",
"jquery-serializejson": "^2.8.1",
"bootstrap-validator": "^0.11.9",
"bootstrap-datepicker": "^1.8.0",
"moment": "^2.18.1",
- "@danielfarrell/bootstrap-combobox": "^1.1.8",
+ "@danielfarrell/bootstrap-combobox": "https://github.com/pallidus-fintech/bootstrap-combobox.git#enhance/boostrap_4",
"datatables.net": "^1.10.19",
"datatables.net-bs4": "^1.10.19",
"datatables.net-responsive": "^2.2.3",
@@ -18,7 +19,7 @@
"timeago": "^1.6.1",
"toastr": "^2.1.3",
"tagmanager": "https://github.com/max-favilli/tagmanager.git#3.0.2",
- "eonasdan-bootstrap-datetimepicker": "^4.17.47",
+ "tempusdominus-bootstrap-4": "^5.0.1",
"swagger-ui-dist": "^3.13.4",
"jquery-ui-dist": "^1.12.1",
"bootstrap-side-navbar": "https://github.com/samrayner/bootstrap-side-navbar.git#1.0.1"
diff --git a/public/css/grocy.css b/public/css/grocy.css
index 8bc026c4..fa946ef1 100644
--- a/public/css/grocy.css
+++ b/public/css/grocy.css
@@ -1,112 +1,26 @@
-body {
+/* Main style customizations */
+body {
font-family: 'Noto Sans', sans-serif;
- font-size: 0.85rem
}
-#top-nav {
- background-color: #e5e5e5;
- border-bottom: 2px solid;
- border-color: #d6d6d6;
-}
-
-.navbar-brand {
- font-weight: bold;
- letter-spacing: -5px;
- font-size: 2.2em;
- color: #0b024c !important;
- margin-left: 0 !important;
- padding-left: 5px !important;
-}
-
-#sidebar {
- background-color: #e5e5e5;
- border-right: 2px solid #d6d6d6;
- max-width: 260px;
- border-left: 0;
- overflow-y: auto;
- height: 100%;
-}
-
-#sidebar > ul > a > li {
- background-color: #e5e5e5;
- border: 0;
-}
-
-@media (min-width: 768px) {
- #navbar-mobile {
- display: none !important;
- }
-
- .nav-copyright {
- padding-bottom: 100px;
- }
-}
-
-.sidebar-nav > li {
- padding-right: 20px;
- padding-left: 20px;
- transition: all 0.3s;
-}
-
-.sidebar-nav > li:hover {
- box-shadow: inset 5px 0 0 #337ab7;
- transition: all 0.3s;
-}
-
-.sidebar-nav > li:focus {
- box-shadow: inset 5px 0 0 #ab2230;
- transition: all 0.3s;
-}
-
-.sidebar-nav > .active,
-.sidebar-nav > .active:hover,
-.sidebar-nav > .active:focus {
- background-color: #d6d6d6;
- box-shadow: inset 5px 0 0 #ab2230;
- transition: all 0.3s;
-}
-
-.nav > li.disabled > a,
-.nav-link-navbar {
- color: #7d7d7d;
-}
-
-.nav-copyright {
- color: #a7a7a7;
- font-size: 11px;
- text-align: center;
-}
-
-.nav-copyright > li > a {
- padding-top: 0 !important;
- padding-bottom: 0 !important;
-}
-
-#top-nav .navbar-nav > .open > a {
- background-color: #d6d6d6 !important;
-}
-
-.dropdown-item > li > a:hover,
-.dropdown-item > li > a:focus,
-.dropdown-item:active {
- background-color: #e5e5e5 !important;
-}
-
-.well {
- background-color: #e5e5e5;
- padding-right: 25px;
- padding-left: 25px;
-}
-
-td {
- vertical-align: middle !important;
+.content-text {
+ font-size: 0.85rem;
}
.responsive-button {
white-space: normal;
}
-.discrete-link {
+.no-real-button {
+ pointer-events: none;
+}
+
+.timeago-contextual {
+ font-style: italic;
+ font-size: 0.8em;
+}
+
+a.discrete-link {
color: inherit !important;
transition: all 0.3s !important;
}
@@ -114,70 +28,114 @@ td {
a.discrete-link:hover {
color: #337ab7 !important;
text-decoration: none !important;
- transition: all 0.3s !important;
}
a.discrete-link:focus {
color: #ab2230 !important;
text-decoration: none !important;
+}
+
+.card {
+ border: 2px solid;
+ border-color: #d6d6d6;
+ border-radius: 0;
+}
+
+.card-header {
+ background-color: #e5e5e5;
+}
+
+/* Navigation style customizations */
+#mainNav {
+ background-color: #e5e5e5 !important;
+ border-bottom: 2px solid !important;
+ border-color: #d6d6d6 !important;
+}
+
+.navbar-sidenav {
+ overflow-y: auto;
+ overflow-x: hidden;
+}
+
+.navbar-sidenav,
+.sidenav-second-level {
+ background-color: #e5e5e5 !important;
+ border-top: 2px solid !important;
+ border-right: 2px solid !important;
+ border-color: #d6d6d6 !important;
+}
+
+.navbar-nav .dropdown-menu {
+ background-color: #e5e5e5 !important;
+ border: 0;
+ border-radius: 0;
+}
+
+.navbar-nav .dropdown-divider {
+ border-top: 2px solid !important;
+ border-color: #d6d6d6 !important;
+}
+
+.sidenav-toggler {
+ background-color: #d6d6d6 !important;
+ border-right: 2px solid !important;
+ border-color: #d6d6d6 !important;
+}
+
+.navbar-sidenav > li,
+.sidenav-second-level > li {
transition: all 0.3s !important;
}
+.navbar-sidenav > li:hover,
+.sidenav-second-level > li:hover,
+.navbar-nav .dropdown-item:hover {
+ box-shadow: inset 5px 0 0 #337ab7 !important;
+ background-color: #d6d6d6 !important;
+}
+
+.navbar-sidenav > li > a:focus,
+.sidenav-second-level > li > a:focus,
+.navbar-nav .dropdown-item:focus {
+ box-shadow: inset 5px 0 0 #ab2230 !important;
+ background-color: #d6d6d6 !important;
+}
+
+.active-page {
+ box-shadow: inset 5px 0 0 #ab2230 !important;
+ background-color: #d6d6d6 !important;
+}
+
+/* Third party component customizations - DataTables */
+td {
+ vertical-align: middle !important;
+}
+
.table td.fit-content,
.table th.fit-content {
white-space: nowrap;
width: 1%;
}
-.dataTables_info,
-.dataTables_length,
-.dataTables_filter {
- font-style: italic;
-}
-
-.timeago-contextual {
- font-style: italic;
- font-size: 0.8em;
-}
-
-.disabled,
-.no-real-button {
- pointer-events: none;
- margin-top: 2px;
- margin-bottom: 2px;
-}
-
-.discrete-content-separator-2x {
- padding-top: 10px;
- padding-bottom: 10px;
-}
-
-.warning-bg {
- background-color: #fcf8e3 !important;
-}
-
-.error-bg {
- background-color: #f2dede !important;
-}
-
-.info-bg {
- background-color: #afd9ee !important;
+.dataTables_filter,
+.dataTables_info {
+ display: none;
}
+/* Third party component customizations - toastr */
#toast-container > div {
opacity: 1;
filter: alpha(opacity=100);
}
.toast-success {
- background-color: #4c994c;
+ background-color: #28a745;
+}
+
+.toast-error {
+ background-color: #dc3545;
}
#toast-container > div {
box-shadow: none;
}
-
-.dataTables_filter,
-.dataTables_info {
- display: none;
-}
diff --git a/public/img/grocy.png b/public/img/grocy.png
deleted file mode 100644
index b1e6c121..00000000
Binary files a/public/img/grocy.png and /dev/null differ
diff --git a/public/img/grocy_icon.svg b/public/img/grocy_icon.svg
new file mode 100644
index 00000000..5e80ca3e
--- /dev/null
+++ b/public/img/grocy_icon.svg
@@ -0,0 +1,20 @@
+
+
+
diff --git a/public/img/grocy_logo.svg b/public/img/grocy_logo.svg
new file mode 100644
index 00000000..8525d8a0
--- /dev/null
+++ b/public/img/grocy_logo.svg
@@ -0,0 +1,33 @@
+
+
+
diff --git a/public/js/grocy.js b/public/js/grocy.js
index d63d236c..8b556799 100644
--- a/public/js/grocy.js
+++ b/public/js/grocy.js
@@ -21,8 +21,8 @@ U = function(relativePath)
if (!Grocy.ActiveNav.isEmpty())
{
- var menuItem = $('.nav').find("[data-nav-for-page='" + Grocy.ActiveNav + "']");
- menuItem.addClass('active');
+ var menuItem = $('#sidebarResponsive').find("[data-nav-for-page='" + Grocy.ActiveNav + "']");
+ menuItem.addClass('active-page');
}
$.timeago.settings.allowFuture = true;
diff --git a/public/viewjs/batteries.js b/public/viewjs/batteries.js
index 1335f373..76f0d5fe 100644
--- a/public/viewjs/batteries.js
+++ b/public/viewjs/batteries.js
@@ -4,7 +4,8 @@
'columnDefs': [
{ 'orderable': false, 'targets': 0 }
],
- 'language': JSON.parse(L('datatables_localization'))
+ 'language': JSON.parse(L('datatables_localization')),
+ 'scrollY': false
});
$("#search").on("keyup", function()
diff --git a/public/viewjs/batteriesoverview.js b/public/viewjs/batteriesoverview.js
index 7b7e2adf..cde2b71d 100644
--- a/public/viewjs/batteriesoverview.js
+++ b/public/viewjs/batteriesoverview.js
@@ -4,7 +4,8 @@
'columnDefs': [
{ 'orderable': false, 'targets': 0 }
],
- 'language': JSON.parse(L('datatables_localization'))
+ 'language': JSON.parse(L('datatables_localization')),
+ 'scrollY': false
});
$("#search").on("keyup", function()
diff --git a/public/viewjs/components/datetimepicker.js b/public/viewjs/components/datetimepicker.js
index 5a6ab3b0..3a8cf9e6 100644
--- a/public/viewjs/components/datetimepicker.js
+++ b/public/viewjs/components/datetimepicker.js
@@ -6,6 +6,6 @@ $(function()
showTodayButton: true,
calendarWeeks: true,
maxDate: moment(),
- locale: moment.locale('de')
+ locale: moment.locale()
});
});
diff --git a/public/viewjs/habits.js b/public/viewjs/habits.js
index 7e106ebb..2959908a 100644
--- a/public/viewjs/habits.js
+++ b/public/viewjs/habits.js
@@ -4,7 +4,8 @@
'columnDefs': [
{ 'orderable': false, 'targets': 0 }
],
- 'language': JSON.parse(L('datatables_localization'))
+ 'language': JSON.parse(L('datatables_localization')),
+ 'scrollY': false
});
$("#search").on("keyup", function()
diff --git a/public/viewjs/habitsoverview.js b/public/viewjs/habitsoverview.js
index b7a3d84e..e0413d83 100644
--- a/public/viewjs/habitsoverview.js
+++ b/public/viewjs/habitsoverview.js
@@ -4,7 +4,8 @@
'columnDefs': [
{ 'orderable': false, 'targets': 0 }
],
- 'language': JSON.parse(L('datatables_localization'))
+ 'language': JSON.parse(L('datatables_localization')),
+ 'scrollY': false
});
$("#search").on("keyup", function()
diff --git a/public/viewjs/inventory.js b/public/viewjs/inventory.js
index 340aad75..843aa0cf 100644
--- a/public/viewjs/inventory.js
+++ b/public/viewjs/inventory.js
@@ -243,8 +243,8 @@ var addBarcode = GetUriParam('addbarcodetoselection');
if (addBarcode !== undefined)
{
$('#addbarcodetoselection').text(addBarcode);
- $('#flow-info-addbarcodetoselection').removeClass('hide');
- $('#barcode-lookup-disabled-hint').removeClass('hide');
+ $('#flow-info-addbarcodetoselection').removeClass('d-none');
+ $('#barcode-lookup-disabled-hint').removeClass('d-none');
}
$('#new_amount').on('keypress', function(e)
diff --git a/public/viewjs/locations.js b/public/viewjs/locations.js
index 4ed99907..493fa340 100644
--- a/public/viewjs/locations.js
+++ b/public/viewjs/locations.js
@@ -4,7 +4,8 @@
'columnDefs': [
{ 'orderable': false, 'targets': 0 }
],
- 'language': JSON.parse(L('datatables_localization'))
+ 'language': JSON.parse(L('datatables_localization')),
+ 'scrollY': false
});
$("#search").on("keyup", function()
diff --git a/public/viewjs/login.js b/public/viewjs/login.js
index 0ecea09e..97908729 100644
--- a/public/viewjs/login.js
+++ b/public/viewjs/login.js
@@ -1,4 +1,5 @@
$('.logout-button').hide();
+$('.logout-button-divider').hide();
$('#username').focus();
diff --git a/public/viewjs/manageapikeys.js b/public/viewjs/manageapikeys.js
index 6d5bec44..dc3c4bfb 100644
--- a/public/viewjs/manageapikeys.js
+++ b/public/viewjs/manageapikeys.js
@@ -4,7 +4,8 @@
'columnDefs': [
{ 'orderable': false, 'targets': 0 }
],
- 'language': JSON.parse(L('datatables_localization'))
+ 'language': JSON.parse(L('datatables_localization')),
+ 'scrollY': false
});
var createdApiKeyId = GetUriParam('CreatedApiKeyId');
diff --git a/public/viewjs/products.js b/public/viewjs/products.js
index 7f65eb1f..cd02b8f8 100644
--- a/public/viewjs/products.js
+++ b/public/viewjs/products.js
@@ -4,7 +4,8 @@
'columnDefs': [
{ 'orderable': false, 'targets': 0 }
],
- 'language': JSON.parse(L('datatables_localization'))
+ 'language': JSON.parse(L('datatables_localization')),
+ 'scrollY': false
});
$("#search").on("keyup", function()
diff --git a/public/viewjs/purchase.js b/public/viewjs/purchase.js
index c49fed8f..566c7706 100644
--- a/public/viewjs/purchase.js
+++ b/public/viewjs/purchase.js
@@ -97,7 +97,8 @@ $('#product_id').on('change', function(e)
});
$('.combobox').combobox({
- appendId: '_text_input'
+ appendId: '_text_input',
+ bsVersion: '4'
});
$('#product_id_text_input').on('change', function(e)
@@ -253,8 +254,8 @@ var addBarcode = GetUriParam('addbarcodetoselection');
if (addBarcode !== undefined)
{
$('#addbarcodetoselection').text(addBarcode);
- $('#flow-info-addbarcodetoselection').removeClass('hide');
- $('#barcode-lookup-disabled-hint').removeClass('hide');
+ $('#flow-info-addbarcodetoselection').removeClass('d-none');
+ $('#barcode-lookup-disabled-hint').removeClass('d-none');
}
$('#best_before_date').on('change', function(e)
diff --git a/public/viewjs/quantityunits.js b/public/viewjs/quantityunits.js
index 2aee5631..d3eb75bc 100644
--- a/public/viewjs/quantityunits.js
+++ b/public/viewjs/quantityunits.js
@@ -4,7 +4,8 @@
'columnDefs': [
{ 'orderable': false, 'targets': 0 }
],
- 'language': JSON.parse(L('datatables_localization'))
+ 'language': JSON.parse(L('datatables_localization')),
+ 'scrollY': false
});
$("#search").on("keyup", function()
diff --git a/public/viewjs/shoppinglist.js b/public/viewjs/shoppinglist.js
index ce56ed81..7841095f 100644
--- a/public/viewjs/shoppinglist.js
+++ b/public/viewjs/shoppinglist.js
@@ -4,7 +4,8 @@
'columnDefs': [
{ 'orderable': false, 'targets': 0 }
],
- 'language': JSON.parse(L('datatables_localization'))
+ 'language': JSON.parse(L('datatables_localization')),
+ 'scrollY': false
});
$("#search").on("keyup", function()
diff --git a/views/batteries.blade.php b/views/batteries.blade.php
index cde45cb8..6c2cf4dc 100644
--- a/views/batteries.blade.php
+++ b/views/batteries.blade.php
@@ -5,55 +5,59 @@
@section('viewJsName', 'batteries')
@section('content')
-
-
-
-
-
-
-
-
+
-
-
-
-
- # |
- {{ $L('Name') }} |
- {{ $L('Description') }} |
- {{ $L('Used in') }} |
-
-
-
- @foreach($batteries as $battery)
-
-
-
-
-
-
-
-
- |
-
- {{ $battery->name }}
- |
-
- {{ $battery->description }}
- |
-
- {{ $battery->used_in }}
- |
-
- @endforeach
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+ # |
+ {{ $L('Name') }} |
+ {{ $L('Description') }} |
+ {{ $L('Used in') }} |
+
+
+
+ @foreach($batteries as $battery)
+
+
+
+
+
+
+
+
+ |
+
+ {{ $battery->name }}
+ |
+
+ {{ $battery->description }}
+ |
+
+ {{ $battery->used_in }}
+ |
+
+ @endforeach
+
+
+
@stop
diff --git a/views/batteriesoverview.blade.php b/views/batteriesoverview.blade.php
index c34e95b4..c42b07bb 100644
--- a/views/batteriesoverview.blade.php
+++ b/views/batteriesoverview.blade.php
@@ -9,60 +9,61 @@
@endpush
@section('content')
-
-
-
-
-
{{ $L('#1 batteries are due to be charged within the next #2 days', $countDueNextXDays, $nextXDays) }}
+
+
+
@yield('title')
+
{{ $L('#1 batteries are due to be charged within the next #2 days', $countDueNextXDays, $nextXDays) }}
{{ $L('#1 batteries are overdue to be charged', $countOverdue) }}
-
-
-
-
-
-
+
+
+
-
-
-
-
- # |
- {{ $L('Battery') }} |
- {{ $L('Last charged') }} |
- {{ $L('Next planned charge cycle') }} |
-
-
-
- @foreach($current as $curentBatteryEntry)
-
-
-
-
-
- |
-
- {{ FindObjectInArrayByPropertyValue($batteries, 'id', $curentBatteryEntry->battery_id)->name }}
- |
-
- {{ $curentBatteryEntry->last_tracked_time }}
-
- |
-
- @if(FindObjectInArrayByPropertyValue($batteries, 'id', $curentBatteryEntry->battery_id)->charge_interval_days > 0)
- {{ $nextChargeTimes[$curentBatteryEntry->battery_id] }}
-
- @else
- ...
- @endif
- |
-
- @endforeach
-
-
+
+
+
+
+
+ # |
+ {{ $L('Battery') }} |
+ {{ $L('Last charged') }} |
+ {{ $L('Next planned charge cycle') }} |
+
+
+
+ @foreach($current as $curentBatteryEntry)
+
+
+
+
+
+ |
+
+ {{ FindObjectInArrayByPropertyValue($batteries, 'id', $curentBatteryEntry->battery_id)->name }}
+ |
+
+ {{ $curentBatteryEntry->last_tracked_time }}
+
+ |
+
+ @if(FindObjectInArrayByPropertyValue($batteries, 'id', $curentBatteryEntry->battery_id)->charge_interval_days > 0)
+ {{ $nextChargeTimes[$curentBatteryEntry->battery_id] }}
+
+ @else
+ ...
+ @endif
+ |
+
+ @endforeach
+
+
+
@stop
diff --git a/views/batteryform.blade.php b/views/batteryform.blade.php
index 1c064d76..b973c705 100644
--- a/views/batteryform.blade.php
+++ b/views/batteryform.blade.php
@@ -9,35 +9,37 @@
@section('viewJsName', 'batteryform')
@section('content')
-
-
+
+
+
@yield('title')
-
+
- @if($mode == 'edit')
-
- @endif
+ @if($mode == 'edit')
+
+ @endif
-
+
+
@stop
diff --git a/views/batterytracking.blade.php b/views/batterytracking.blade.php
index 8a387bf9..295cd14d 100644
--- a/views/batterytracking.blade.php
+++ b/views/batterytracking.blade.php
@@ -5,39 +5,41 @@
@section('viewJsName', 'batterytracking')
@section('content')
-
-
+
+
@stop
diff --git a/views/components/batterycard.blade.php b/views/components/batterycard.blade.php
index 7bc388c7..945079c3 100644
--- a/views/components/batterycard.blade.php
+++ b/views/components/batterycard.blade.php
@@ -2,14 +2,13 @@
@endpush
-
-
-
{{ $L('Battery overview') }}
-
-
+
+
+
{{ $L('Used in') }}:
{{ $L('Charge cycles count') }}:
{{ $L('Last charged') }}:
-
-
+
diff --git a/views/components/datepicker.blade.php b/views/components/datepicker.blade.php
index 0f303dd0..75d356a8 100644
--- a/views/components/datepicker.blade.php
+++ b/views/components/datepicker.blade.php
@@ -6,9 +6,9 @@
diff --git a/views/components/datetimepicker.blade.php b/views/components/datetimepicker.blade.php
index 52952ece..b272cef2 100644
--- a/views/components/datetimepicker.blade.php
+++ b/views/components/datetimepicker.blade.php
@@ -3,12 +3,12 @@
@endpush