Squashed commit

Improve journal pages loading time (new date range filter)
Various small style adjustments (meal plan page and others)
Pulled German translations from Transifex
Show the shopping list total value (closes #1309)
Make it possible to copy recipes (closes #714)
Implemented optional "auto decimal separator for price inputs" (closes #1345)
Removed table grouped column fixed order restriction (closes #1402)
Don't filter out style, class, id attributes of html text (closes #1298)
Added product picture as column on the stock overview page (closes #1283)
Added grocycodes also for chores and batteries (+ camera barcode scanning for /choretracking and /batterytracking, this now closes #221)
This commit is contained in:
Bernd Bestel
2021-07-13 19:29:23 +02:00
parent 8d2c3ae584
commit 91d8eaeb74
70 changed files with 1476 additions and 491 deletions

View File

@@ -48,6 +48,22 @@
</select>
</div>
</div>
<div class="col-12 col-md-6 col-xl-3">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fas fa-clock"></i>&nbsp;{{ $__t('Date range') }}</span>
</div>
<select class="custom-control custom-select"
id="daterange-filter">
<option value="1">{{ $__n(1, '%s month', '%s months') }}</option>
<option value="6">{{ $__n(6, '%s month', '%s months') }}</option>
<option value="12">{{ $__n(1, '%s year', '%s years') }}</option>
<option value="24"
selected>{{ $__n(2, '%s month', '%s years') }}</option>
<option value="9999">{{ $__t('All') }}</option>
</select>
</div>
</div>
<div class="col">
<div class="float-right">
<a id="clear-filter-button"
@@ -81,7 +97,7 @@
<tr id="charge-cycle-{{ $chargeCycleEntry->id }}-row"
class="@if($chargeCycleEntry->undone == 1) text-muted @endif">
<td class="fit-content border-right">
<a class="btn btn-secondary btn-sm undo-battery-execution-button @if($chargeCycleEntry->undone == 1) disabled @endif permission-BATTERIES_UNDO_CHARGE_CYCLE"
<a class="btn btn-secondary btn-xs undo-battery-execution-button @if($chargeCycleEntry->undone == 1) disabled @endif permission-BATTERIES_UNDO_CHARGE_CYCLE"
href="#"
data-charge-cycle-id="{{ $chargeCycleEntry->id }}"
data-toggle="tooltip"

View File

@@ -145,6 +145,20 @@
href="{{ $U('/battery/') }}{{ $currentBatteryEntry->battery_id }}?embedded">
<span class="dropdown-item-text">{{ $__t('Edit battery') }}</span>
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item stockentry-grocycode-link"
type="button"
href="{{ $U('/battery/' . $currentBatteryEntry->battery_id . '/grocycode?download=true') }}">
{!! str_replace('grocycode', '<span class="ls-n1">grocycode</span>', $__t('Download %s grocycode', $__t('Battery'))) !!}
</a>
@if(GROCY_FEATURE_FLAG_LABEL_PRINTER)
<a class="dropdown-item battery-grocycode-label-print"
data-battery-id="{{ $currentBatteryEntry->battery_id }}"
type="button"
href="#">
{!! str_replace('grocycode', '<span class="ls-n1">grocycode</span>', $__t('Print %s grocycode on label printer', $__t('Battery'))) !!}
</a>
@endif
</div>
</div>
</td>

View File

@@ -95,4 +95,35 @@
</form>
</div>
</div>
<div class="row mt-2 border-top">
<div class="col clearfix mt-2">
<div class="title-related-links">
<h4>
<span class="ls-n1">{{ $__t('grocycode') }}</span>
<i class="fas fa-question-circle text-muted"
data-toggle="tooltip"
data-trigger="hover click"
title="{{ $__t('grocycode is a unique referer to this %s in your grocy instance - print it onto a label and scan it like any other barcode', $__t('Battery')) }}"></i>
</h4>
<p>
@if($mode == 'edit')
<img src="{{ $U('/battery/' . $battery->id . '/grocycode?size=60') }}"
class="float-lg-left">
@endif
</p>
<p>
<a class="btn btn-outline-primary btn-sm"
href="{{ $U('/battery/' . $battery->id . '/grocycode?download=true') }}">{{ $__t('Download') }}</a>
@if(GROCY_FEATURE_FLAG_LABEL_PRINTER)
<a class="btn btn-outline-primary btn-sm battery-grocycode-label-print"
data-battery-id="{{ $battery->id }}"
href="#">
{{ $__t('Print on label printer') }}
</a>
@endif
</p>
</div>
</div>
</div>
@stop

View File

@@ -15,11 +15,17 @@
novalidate>
<div class="form-group">
<label for="battery_id">{{ $__t('Battery') }}</label>
<select class="form-control combobox"
<label class="w-100"
for="battery_id">
{{ $__t('Battery') }}
<i id="barcode-lookup-hint"
class="fas fa-barcode float-right mt-1"></i>
</label>
<select class="form-control combobox barcodescanner-input"
id="battery_id"
name="battery_id"
required>
required
data-target="@batterypicker">
<option value=""></option>
@foreach($batteries as $battery)
<option value="{{ $battery->id }}">{{ $battery->name }}</option>
@@ -48,4 +54,6 @@
@include('components.batterycard')
</div>
</div>
@include('components.barcodescanner')
@stop

View File

@@ -289,5 +289,38 @@
</form>
</div>
<div class="col-lg-6 col-12 @if($mode == 'create') d-none @endif">
<div class="row">
<div class="col clearfix">
<div class="title-related-links">
<h4>
<span class="ls-n1">{{ $__t('grocycode') }}</span>
<i class="fas fa-question-circle text-muted"
data-toggle="tooltip"
data-trigger="hover click"
title="{{ $__t('grocycode is a unique referer to this %s in your grocy instance - print it onto a label and scan it like any other barcode', $__t('Chore')) }}"></i>
</h4>
<p>
@if($mode == 'edit')
<img src="{{ $U('/chore/' . $chore->id . '/grocycode?size=60') }}"
class="float-lg-left">
@endif
</p>
<p>
<a class="btn btn-outline-primary btn-sm"
href="{{ $U('/chore/' . $chore->id . '/grocycode?download=true') }}">{{ $__t('Download') }}</a>
@if(GROCY_FEATURE_FLAG_LABEL_PRINTER)
<a class="btn btn-outline-primary btn-sm chore-grocycode-label-print"
data-chore-id="{{ $chore->id }}"
href="#">
{{ $__t('Print on label printer') }}
</a>
@endif
</p>
</div>
</div>
</div>
</div>
</div>
@stop

View File

@@ -48,6 +48,22 @@
</select>
</div>
</div>
<div class="col-12 col-md-6 col-xl-3">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fas fa-clock"></i>&nbsp;{{ $__t('Date range') }}</span>
</div>
<select class="custom-control custom-select"
id="daterange-filter">
<option value="1">{{ $__n(1, '%s month', '%s months') }}</option>
<option value="6">{{ $__n(6, '%s month', '%s months') }}</option>
<option value="12"
selected>{{ $__n(1, '%s year', '%s years') }}</option>
<option value="24">{{ $__n(2, '%s month', '%s years') }}</option>
<option value="9999">{{ $__t('All') }}</option>
</select>
</div>
</div>
<div class="col">
<div class="float-right">
<a id="clear-filter-button"
@@ -88,7 +104,7 @@
<tr id="chore-execution-{{ $choreLogEntry->id }}-row"
class="@if($choreLogEntry->undone == 1) text-muted @endif">
<td class="fit-content border-right">
<a class="btn btn-secondary btn-sm undo-chore-execution-button permission-CHORE_UNDO_EXECUTION @if($choreLogEntry->undone == 1) disabled @endif"
<a class="btn btn-secondary btn-xs undo-chore-execution-button permission-CHORE_UNDO_EXECUTION @if($choreLogEntry->undone == 1) disabled @endif"
href="#"
data-execution-id="{{ $choreLogEntry->id }}"
data-toggle="tooltip"

View File

@@ -168,6 +168,20 @@
href="{{ $U('/chore/') }}{{ $curentChoreEntry->chore_id }}">
<span class="dropdown-item-text">{{ $__t('Edit chore') }}</span>
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item stockentry-grocycode-link"
type="button"
href="{{ $U('/chore/' . $curentChoreEntry->chore_id . '/grocycode?download=true') }}">
{!! str_replace('grocycode', '<span class="ls-n1">grocycode</span>', $__t('Download %s grocycode', $__t('Chore'))) !!}
</a>
@if(GROCY_FEATURE_FLAG_LABEL_PRINTER)
<a class="dropdown-item chore-grocycode-label-print"
data-chore-id="{{ $curentChoreEntry->chore_id }}"
type="button"
href="#">
{!! str_replace('grocycode', '<span class="ls-n1">grocycode</span>', $__t('Print %s grocycode on label printer', $__t('Chore'))) !!}
</a>
@endif
</div>
</div>
</td>

View File

@@ -15,11 +15,17 @@
novalidate>
<div class="form-group">
<label for="chore_id">{{ $__t('Chore') }}</label>
<select class="form-control combobox"
<label class="w-100"
for="chore_id">
{{ $__t('Chore') }}
<i id="barcode-lookup-hint"
class="fas fa-barcode float-right mt-1"></i>
</label>
<select class="form-control combobox barcodescanner-input"
id="chore_id"
name="chore_id"
required>
required
data-target="@chorepicker">
<option value=""></option>
@foreach($chores as $chore)
<option value="{{ $chore->id }}">{{ $chore->name }}</option>
@@ -67,4 +73,6 @@
@include('components.chorecard')
</div>
</div>
@include('components.barcodescanner')
@stop

View File

@@ -18,8 +18,7 @@
@php if(empty($additionalGroupCssClasses)) { $additionalGroupCssClasses = ''; } @endphp
@php if(empty($activateNumberPad)) { $activateNumberPad = false; } @endphp
<div class="datetimepicker-wrapper"
class="form-group {{ $additionalGroupCssClasses }}">
<div class="datetimepicker-wrapper form-group {{ $additionalGroupCssClasses }}">
<label for="{{ $id }}">{{ $__t($label) }}
@if(!empty($hint))
&nbsp;<i class="fas fa-question-circle text-muted"

View File

@@ -17,8 +17,7 @@
@php if(empty($additionalAttributes)) { $additionalAttributes = ''; } @endphp
@php if(empty($additionalGroupCssClasses)) { $additionalGroupCssClasses = ''; } @endphp
<div class="datetimepicker2-wrapper"
class="form-group {{ $additionalGroupCssClasses }}">
<div class="datetimepicker2-wrapper form-group {{ $additionalGroupCssClasses }}">
<label for="{{ $id }}">{{ $__t($label) }}
@if(!empty($hint))
&nbsp;<i class="fas fa-question-circle text-muted"

View File

@@ -85,14 +85,22 @@
title="{{ $__t('Edit this item') }}">
<i class="fas fa-edit"></i>
</a>
<a class="btn btn-sm btn-danger hide-when-embedded hide-on-fullscreen-card equipment-delete-button"
href="#"
data-equipment-id="{{ $equipmentItem->id }}"
data-equipment-name="{{ $equipmentItem->name }}"
data-toggle="tooltip"
title="{{ $__t('Delete this item') }}">
<i class="fas fa-trash"></i>
</a>
<div class="dropdown d-inline-block">
<button class="btn btn-sm btn-light text-secondary"
type="button"
data-toggle="dropdown">
<i class="fas fa-ellipsis-v"></i>
</button>
<div class="table-inline-menu dropdown-menu dropdown-menu-right hide-on-fullscreen-card hide-when-embedded">
<a class="dropdown-item equipment-delete-button"
type="button"
href="#"
data-equipment-id="{{ $equipmentItem->id }}"
data-equipment-name="{{ $equipmentItem->name }}">
<span class="dropdown-item-text">{{ $__t('Delete this item') }}</span>
</a>
</div>
</div>
</td>
<td>
{{ $equipmentItem->name }}

View File

@@ -97,7 +97,7 @@
Grocy.LocalizationStrings = {!! $LocalizationStrings !!};
Grocy.FeatureFlags = {!! json_encode($featureFlags) !!};
Grocy.Webhooks = {
@if(GROCY_FEATURE_FLAG_LABELPRINTER && !GROCY_LABEL_PRINTER_RUN_SERVER)
@if(GROCY_FEATURE_FLAG_LABEL_PRINTER && !GROCY_LABEL_PRINTER_RUN_SERVER)
"labelprinter" : {
"hook" : "{{ GROCY_LABEL_PRINTER_WEBHOOK}}",
"extra_data" : {!! json_encode(GROCY_LABEL_PRINTER_PARAMS) !!}

View File

@@ -21,6 +21,13 @@
.img-fluid {
max-width: 90%;
max-height: 140px;
}
@media (min-width: 400px) {
.table-inline-menu.dropdown-menu {
width: 200px !important;
}
}
</style>
@@ -220,4 +227,21 @@
</div>
</div>
</div>
<div class="modal fade"
id="mealplan-productcard-modal"
tabindex="-1">
<div class="modal-dialog">
<div class="modal-content text-center">
<div class="modal-body">
@include('components.productcard')
</div>
<div class="modal-footer">
<button type="button"
class="btn btn-secondary"
data-dismiss="modal">{{ $__t('Close') }}</button>
</div>
</div>
</div>
</div>
@stop

View File

@@ -425,7 +425,7 @@
'entity' => 'products'
))
@if(GROCY_FEATURE_FLAG_LABELPRINTER)
@if(GROCY_FEATURE_FLAG_LABEL_PRINTER)
<div class="form-group">
<div class="custom-control custom-checkbox">
<input @if($mode=='edit'
@@ -616,11 +616,11 @@
<div class="col clearfix">
<div class="title-related-links">
<h4>
{{ $__t('grocycode') }}
<span class="ls-n1">{{ $__t('grocycode') }}</span>
<i class="fas fa-question-circle text-muted"
data-toggle="tooltip"
data-trigger="hover click"
title="{{ $__t('grocycode is a unique referer to this product in your grocy instance - print it onto a label and scan it like any other barcode') }}"></i>
title="{{ $__t('grocycode is a unique referer to this %s in your grocy instance - print it onto a label and scan it like any other barcode', $__t('Product')) }}"></i>
</h4>
<p>
@if($mode == 'edit')
@@ -631,8 +631,8 @@
<p>
<a class="btn btn-outline-primary btn-sm"
href="{{ $U('/product/' . $product->id . '/grocycode?download=true') }}">{{ $__t('Download') }}</a>
@if(GROCY_FEATURE_FLAG_LABELPRINTER)
<a class="btn btn-outline-primary btn-sm stockentry-grocycode-product-label-print"
@if(GROCY_FEATURE_FLAG_LABEL_PRINTER)
<a class="btn btn-outline-primary btn-sm product-grocycode-label-print"
data-product-id="{{ $product->id }}"
href="#">
{{ $__t('Print on label printer') }}

View File

@@ -148,7 +148,7 @@
))
@endif
@if(GROCY_FEATURE_FLAG_LABELPRINTER)
@if(GROCY_FEATURE_FLAG_LABEL_PRINTER)
<div class="form-group">
<label for="print_stock_label">{{ $__t('Stock entry label') }}</label>
<select class="form-control"

View File

@@ -142,14 +142,28 @@
title="{{ $__t('Edit this item') }}">
<i class="fas fa-edit"></i>
</a>
<a class="btn btn-sm btn-danger hide-when-embedded hide-on-fullscreen-card recipe-delete"
href="#"
data-recipe-id="{{ $recipe->id }}"
data-recipe-name="{{ $recipe->name }}"
data-toggle="tooltip"
title="{{ $__t('Delete this item') }}">
<i class="fas fa-trash"></i>
</a>
<div class="dropdown d-inline-block">
<button class="btn btn-sm btn-light text-secondary"
type="button"
data-toggle="dropdown">
<i class="fas fa-ellipsis-v"></i>
</button>
<div class="table-inline-menu dropdown-menu dropdown-menu-right hide-on-fullscreen-card hide-when-embedded">
<a class="dropdown-item recipe-delete"
type="button"
href="#"
data-recipe-id="{{ $recipe->id }}"
data-recipe-name="{{ $recipe->name }}">
<span class="dropdown-item-text">{{ $__t('Delete this item') }}</span>
</a>
<a class="dropdown-item recipe-copy"
type="button"
href="#"
data-recipe-id="{{ $recipe->id }}">
<span class="dropdown-item-text">{{ $__t('Copy recipe') }}</span>
</a>
</div>
</div>
</td>
<td>
{{ $recipe->name }}

View File

@@ -21,6 +21,11 @@
<h2 class="title mr-2 order-0">
@yield('title')
</h2>
@if(GROCY_FEATURE_FLAG_STOCK_PRICE_TRACKING)
<h2 class="mb-0 mr-auto order-3 order-md-1 width-xs-sm-100">
<span class="text-muted small">{!! $__t('%s total value', '<span class="locale-number locale-number-currency">' . SumArrayValue($listItems, 'last_price_total') . '</span>') !!}</span>
</h2>
@endif
<div class="float-right">
<button class="btn btn-outline-dark d-md-none mt-2 order-1 order-md-3"
type="button"
@@ -313,7 +318,7 @@
class="d-none mr-auto"></span>
<button id="shopping-list-stock-add-workflow-skip-button"
type="button"
class="btn btn-primary"><i class="fas fa-angle-double-right"></i> {{ $__t('Skip') }}</button>
class="btn btn-primary">{{ $__t('Skip') }}</button>
<button type="button"
class="btn btn-secondary"
data-dismiss="modal">{{ $__t('Close') }}</button>

View File

@@ -202,21 +202,21 @@
<a class="dropdown-item stockentry-grocycode-link"
type="button"
href="{{ $U('/stockentry/' . $stockEntry->id . '/grocycode?download=true') }}">
{{ $__t('Download stock entry grocycode') }}
{!! str_replace('grocycode', '<span class="ls-n1">grocycode</span>', $__t('Download %s grocycode', $__t('Stock entry'))) !!}
</a>
@if(GROCY_FEATURE_FLAG_LABELPRINTER)
<a class="dropdown-item stockentry-grocycode-stockentry-label-print"
@if(GROCY_FEATURE_FLAG_LABEL_PRINTER)
<a class="dropdown-item stockentry-grocycode-label-print"
data-stock-id="{{ $stockEntry->id }}"
type="button"
href="#">
{{ $__t('Print stock entry grocycode on label printer') }}
{!! str_replace('grocycode', '<span class="ls-n1">grocycode</span>', $__t('Print %s grocycode on label printer', $__t('Stock entry'))) !!}
</a>
@endif
<a class="dropdown-item stockentry-label-link"
type="button"
target="_blank"
href="{{ $U('/stockentry/' . $stockEntry->id . '/label') }}">
{{ $__t('Open stock entry print label in new window') }}
{{ $__t('Open stock entry label in new window') }}
</a>
</div>
</div>

View File

@@ -14,7 +14,7 @@
data-target="#table-filter-row">
<i class="fas fa-filter"></i>
</button>
<button class="btn btn-outline-dark d-md-none mt-2 order-1 order-md-3"
<button class="btn btn-outline-dark d-md-none mt-2 order-1 order-md-3 hide-when-embedded"
type="button"
data-toggle="collapse"
data-target="#related-links">
@@ -45,7 +45,7 @@
placeholder="{{ $__t('Search') }}">
</div>
</div>
<div class="col-12 col-md-6 col-xl-2">
<div class="col-12 col-md-6 col-xl-3">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fas fa-filter"></i>&nbsp;{{ $__t('Product') }}</span>
@@ -73,7 +73,7 @@
</select>
</div>
</div>
<div class="col-12 col-md-6 col-xl-2">
<div class="col-12 col-md-6 col-xl-3">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fas fa-filter"></i>&nbsp;{{ $__t('Location') }}</span>
@@ -87,7 +87,7 @@
</select>
</div>
</div>
<div class="col-12 col-md-6 col-xl-2">
<div class="col-12 col-md-6 col-xl-2 mt-1">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fas fa-filter"></i>&nbsp;{{ $__t('User') }}</span>
@@ -101,6 +101,22 @@
</select>
</div>
</div>
<div class="col-12 col-md-6 col-xl-3 mt-1">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fas fa-clock"></i>&nbsp;{{ $__t('Date range') }}</span>
</div>
<select class="custom-control custom-select"
id="daterange-filter">
<option value="1">{{ $__n(1, '%s month', '%s months') }}</option>
<option value="6"
selected>{{ $__n(6, '%s month', '%s months') }}</option>
<option value="12">{{ $__n(1, '%s year', '%s years') }}</option>
<option value="24">{{ $__n(2, '%s month', '%s years') }}</option>
<option value="9999">{{ $__t('All') }}</option>
</select>
</div>
</div>
<div class="col">
<div class="float-right mt-1">
<a id="clear-filter-button"
@@ -139,7 +155,7 @@
class="@if($stockLogEntry->undone == 1) text-muted @endif stock-booking-correlation-{{ $stockLogEntry->correlation_id }}"
data-correlation-id="{{ $stockLogEntry->correlation_id }}">
<td class="fit-content border-right">
<a class="btn btn-secondary btn-sm undo-stock-booking-button @if($stockLogEntry->undone == 1) disabled @endif"
<a class="btn btn-secondary btn-xs undo-stock-booking-button @if($stockLogEntry->undone == 1) disabled @endif"
href="#"
data-booking-id="{{ $stockLogEntry->id }}"
data-toggle="tooltip"

View File

@@ -173,6 +173,7 @@
<th>{{ $__t('Product description') }}</th>
<th>{{ $__t('Parent product') }}</th>
<th>{{ $__t('Default location') }}</th>
<th>{{ $__t('Product picture') }}</th>
@include('components.userfields_thead', array(
'userfields' => $userfields
@@ -306,14 +307,14 @@
<a class="dropdown-item stockentry-grocycode-link"
type="button"
href="{{ $U('/product/' . $currentStockEntry->product_id . '/grocycode?download=true') }}">
{{ $__t('Download product grocycode') }}
{!! str_replace('grocycode', '<span class="ls-n1">grocycode</span>', $__t('Download %s grocycode', $__t('Product'))) !!}
</a>
@if(GROCY_FEATURE_FLAG_LABELPRINTER)
<a class="dropdown-item stockentry-grocycode-product-label-print"
@if(GROCY_FEATURE_FLAG_LABEL_PRINTER)
<a class="dropdown-item product-grocycode-label-print"
data-product-id="{{ $currentStockEntry->product_id }}"
type="button"
href="#">
{{ $__t('Print product grocycode on label printer') }}
{!! str_replace('grocycode', '<span class="ls-n1">grocycode</span>', $__t('Print %s grocycode on label printer', $__t('Product'))) !!}
</a>
@endif
</div>
@@ -414,6 +415,12 @@
<td>
{{ $currentStockEntry->product_default_location_name }}
</td>
<td>
@if(!empty($currentStockEntry->product_picture_file_name))
<img data-src="{{ $U('/api/files/productpictures/' . base64_encode($currentStockEntry->product_picture_file_name) . '?force_serve_as=picture&best_fit_width=64&best_fit_height=64') }}"
class="lazy">
@endif
</td>
@include('components.userfields_tbody', array(
'userfields' => $userfields,

View File

@@ -157,6 +157,23 @@
'min' => 0,
'additionalCssClasses' => 'user-setting-control'
))
<div class="form-group mt-n3">
<div class="custom-control custom-checkbox">
<input type="checkbox"
class="form-check-input custom-control-input user-setting-control"
id="stock_auto_decimal_separator_prices"
data-setting-key="stock_auto_decimal_separator_prices">
<label class="form-check-label custom-control-label"
for="stock_auto_decimal_separator_prices">
{{ $__t('Add decimal separator automatically for price inputs') }}
<i class="fas fa-question-circle text-muted"
data-toggle="tooltip"
data-trigger="hover click"
title="{{ $__t('When enabled, you always have to enter the value including decimal places, the decimal separator will be automatically added based on the amount of allowed decimal places') }}"></i>
</label>
</div>
</div>
@endif
<a href="{{ $U('/stockoverview') }}"