diff --git a/changelog/52_UNRELEASED_2019-xx-xx.md b/changelog/52_UNRELEASED_2019-xx-xx.md index 3786f0b6..8d2623d8 100644 --- a/changelog/52_UNRELEASED_2019-xx-xx.md +++ b/changelog/52_UNRELEASED_2019-xx-xx.md @@ -7,7 +7,7 @@ - Available on any barcode-enabled field (so currently only for picking products) - a new camera button at the right of side the text field - Implemented using [QuaggaJS](https://github.com/serratus/quaggaJS) - camera stream processing happens totally offline / client-side - Please note due to browser security restrictions, this only works when serving grocy via a secure connection (`https://`) -- There is also a `config.php` setting `DISABLE_BROWSER_BARCODE_CAMERA_SCANNING` to disable this, if you don't need it at all +- There is also a `config.php` setting `DISABLE_BROWSER_BARCODE_CAMERA_SCANNING` to disable this, if you don't need it at all (defaults to `false`) ### Stock improvements - Products can now have variations (nested products) @@ -21,6 +21,11 @@ - It's now possible to print a "Location Content Sheet" with the current stock per location - new button at the top of the stock overview page (thought to hang it at the location, note used amounts on paper and track it in grocy later) - The product description now can have formattings (HTML/WYSIWYG editor like for recipes) - "Factor purchase to stock quantity unit" (product option) can now also be a decimal number when "Allow partial units in stock" is enabled +- New "Sub feature flags" in `config.php` to disable some sub-features (hide the corresponding UI elements) if you don't need them (all new feature flags default to `true`, so no changed behaviour when not configured) + - `FEATURE_FLAG_STOCK_PRICE_TRACKING` to disable product price tracking + - `FEATURE_FLAG_STOCK_LOCATION_TRACKING` to disable product location tracking + - `FEATURE_FLAG_STOCK_BEST_BEFORE_DATE_TRACKING` to disable product best before date tracking + - `FEATURE_FLAG_STOCK_PRODUCT_OPENED_TRACKING` to disable product opened tracking ### Recipe improvements - Based on the new linked quantity units, recipe ingredients can now use any product related unit, the amount is calculated according to the cnoversion factor of the unit relation diff --git a/config-dist.php b/config-dist.php index 0d628844..b2e76a08 100644 --- a/config-dist.php +++ b/config-dist.php @@ -17,8 +17,8 @@ # Either "production", "dev" or "prerelease" Setting('MODE', 'production'); -# Either "en" or "de" or the filename (without extension) of -# one of the other available localization files in the "/localization" directory +# Either "en" or "de" or the directory name of +# one of the other available localization folders in the "/localization" directory Setting('CULTURE', 'en'); # This is used to define the first day of a week for calendar views in the frontend, @@ -45,12 +45,11 @@ Setting('BASE_URL', '/'); # see /data/plugins/DemoBarcodeLookupPlugin.php for an example implementation Setting('STOCK_BARCODE_LOOKUP_PLUGIN', 'DemoBarcodeLookupPlugin'); -# If, however, your webserver does not support URL rewriting, -# set this to true +# If, however, your webserver does not support URL rewriting, set this to true Setting('DISABLE_URL_REWRITING', false); -# Specify an custom homepage if desired. By default the homepage will be set to the stock overview. -# You can chosen one of the following values: +# Specify an custom homepage if desired - by default the homepage will be set to the stock overview, +# this needs to be one of the following values: # stock, shoppinglist, recipes, chores, tasks, batteries, equipment, calendar Setting('ENTRY_PAGE', 'stock'); @@ -61,6 +60,7 @@ Setting('DISABLE_AUTH', false); # Set this to true if you want to disable the ability to scan a barcode via the device camera (Browser API) Setting('DISABLE_BROWSER_BARCODE_CAMERA_SCANNING', false); + # Default user settings # These settings can be changed per user, here the defaults # are defined which are used when the user has not changed the setting so far @@ -103,8 +103,6 @@ DefaultUserSetting('show_clock_in_header', false); DefaultUserSetting('shopping_list_to_stock_workflow_auto_submit_when_prefilled', false); - - # Feature flags # grocy was initially about "stock management for your household", many other things # came and still come by, because they are useful - here you can disable the parts @@ -118,3 +116,9 @@ Setting('FEATURE_FLAG_TASKS', true); Setting('FEATURE_FLAG_BATTERIES', true); Setting('FEATURE_FLAG_EQUIPMENT', true); Setting('FEATURE_FLAG_CALENDAR', true); + +# Sub feature flags +Setting('FEATURE_FLAG_STOCK_PRICE_TRACKING', true); +Setting('FEATURE_FLAG_STOCK_LOCATION_TRACKING', true); +Setting('FEATURE_FLAG_STOCK_BEST_BEFORE_DATE_TRACKING', true); +Setting('FEATURE_FLAG_STOCK_PRODUCT_OPENED_TRACKING', true); diff --git a/public/viewjs/components/productcard.js b/public/viewjs/components/productcard.js index 111f2ca4..1c40ce35 100644 --- a/public/viewjs/components/productcard.js +++ b/public/viewjs/components/productcard.js @@ -100,35 +100,38 @@ Grocy.Components.ProductCard.Refresh = function(productId) } ); - Grocy.Api.Get('stock/products/' + productId + '/price-history', - function(priceHistoryDataPoints) - { - if (priceHistoryDataPoints.length > 0) + if (Grocy.FeatureFlags.GROCY_FEATURE_FLAG_STOCK_PRICE_TRACKING) + { + Grocy.Api.Get('stock/products/' + productId + '/price-history', + function(priceHistoryDataPoints) { - $("#productcard-product-price-history-chart").removeClass("d-none"); - $("#productcard-no-price-data-hint").addClass("d-none"); - - Grocy.Components.ProductCard.ReInitPriceHistoryChart(); - priceHistoryDataPoints.forEach((dataPoint) => + if (priceHistoryDataPoints.length > 0) { - Grocy.Components.ProductCard.PriceHistoryChart.data.labels.push(moment(dataPoint.date).toDate()); + $("#productcard-product-price-history-chart").removeClass("d-none"); + $("#productcard-no-price-data-hint").addClass("d-none"); - var dataset = Grocy.Components.ProductCard.PriceHistoryChart.data.datasets[0]; - dataset.data.push(dataPoint.price); - }); - Grocy.Components.ProductCard.PriceHistoryChart.update(); - } - else + Grocy.Components.ProductCard.ReInitPriceHistoryChart(); + priceHistoryDataPoints.forEach((dataPoint) => + { + Grocy.Components.ProductCard.PriceHistoryChart.data.labels.push(moment(dataPoint.date).toDate()); + + var dataset = Grocy.Components.ProductCard.PriceHistoryChart.data.datasets[0]; + dataset.data.push(dataPoint.price); + }); + Grocy.Components.ProductCard.PriceHistoryChart.update(); + } + else + { + $("#productcard-product-price-history-chart").addClass("d-none"); + $("#productcard-no-price-data-hint").removeClass("d-none"); + } + }, + function(xhr) { - $("#productcard-product-price-history-chart").addClass("d-none"); - $("#productcard-no-price-data-hint").removeClass("d-none"); + console.error(xhr); } - }, - function(xhr) - { - console.error(xhr); - } - ); + ); + } }; Grocy.Components.ProductCard.ReInitPriceHistoryChart = function() diff --git a/public/viewjs/inventory.js b/public/viewjs/inventory.js index cd05cd0e..5562c107 100644 --- a/public/viewjs/inventory.js +++ b/public/viewjs/inventory.js @@ -17,7 +17,14 @@ var jsonData = { }; jsonData.new_amount = jsonForm.new_amount; jsonData.best_before_date = Grocy.Components.DateTimePicker.GetValue(); - jsonData.location_id = Grocy.Components.LocationPicker.GetValue(); + if (Grocy.FeatureFlags.GROCY_FEATURE_FLAG_STOCK_LOCATION_TRACKING) + { + jsonData.location_id = Grocy.Components.LocationPicker.GetValue(); + } + else + { + jsonData.location_id = 1; + } jsonData.price = price; Grocy.Api.Post('stock/products/' + jsonForm.product_id + '/inventory', jsonData, @@ -120,7 +127,10 @@ Grocy.Components.ProductPicker.GetPicker().on('change', function(e) } $('#price').val(productDetails.last_price); - Grocy.Components.LocationPicker.SetId(productDetails.location.id); + if (Grocy.FeatureFlags.GROCY_FEATURE_FLAG_STOCK_LOCATION_TRACKING) + { + Grocy.Components.LocationPicker.SetId(productDetails.location.id); + } $('#new_amount').focus(); }, function(xhr) @@ -221,13 +231,24 @@ $('#new_amount').on('keyup', function(e) { $('#inventory-change-info').text(__t('This means %s will be added to stock', estimatedBookingAmount.toLocaleString() + ' ' + __n(estimatedBookingAmount, productDetails.quantity_unit_stock.name, productDetails.quantity_unit_stock.name_plural))); Grocy.Components.DateTimePicker.GetInputElement().attr('required', ''); - Grocy.Components.LocationPicker.GetInputElement().attr('required', ''); + if (Grocy.FeatureFlags.GROCY_FEATURE_FLAG_STOCK_LOCATION_TRACKING) + { + Grocy.Components.LocationPicker.GetInputElement().attr('required', ''); + } } else if (newAmount < productStockAmount + containerWeight) { $('#inventory-change-info').text(__t('This means %s will be removed from stock', estimatedBookingAmount.toLocaleString() + ' ' + __n(estimatedBookingAmount, productDetails.quantity_unit_stock.name, productDetails.quantity_unit_stock.name_plural))); Grocy.Components.DateTimePicker.GetInputElement().removeAttr('required'); - Grocy.Components.LocationPicker.GetInputElement().removeAttr('required'); + if (Grocy.FeatureFlags.GROCY_FEATURE_FLAG_STOCK_LOCATION_TRACKING) + { + Grocy.Components.LocationPicker.GetInputElement().removeAttr('required'); + } + } + + if (!Grocy.FeatureFlags.GROCY_FEATURE_FLAG_STOCK_BEST_BEFORE_DATE_TRACKING) + { + Grocy.Components.DateTimePicker.GetInputElement().removeAttr('required'); } Grocy.FrontendHelpers.ValidateForm('inventory-form'); diff --git a/public/viewjs/purchase.js b/public/viewjs/purchase.js index ee813a6d..4bac9879 100644 --- a/public/viewjs/purchase.js +++ b/public/viewjs/purchase.js @@ -20,7 +20,14 @@ jsonData.amount = amount; jsonData.best_before_date = Grocy.Components.DateTimePicker.GetValue(); jsonData.price = price; - jsonData.location_id = Grocy.Components.LocationPicker.GetValue(); + if (Grocy.FeatureFlags.GROCY_FEATURE_FLAG_STOCK_LOCATION_TRACKING) + { + jsonData.location_id = Grocy.Components.LocationPicker.GetValue(); + } + else + { + jsonData.location_id = 1; + } Grocy.Api.Post('stock/products/' + jsonForm.product_id + '/add', jsonData, function(result) @@ -73,7 +80,10 @@ $('#price').val(''); $('#amount_qu_unit').text(""); $("#tare-weight-handling-info").addClass("d-none"); - Grocy.Components.LocationPicker.Clear(); + if (Grocy.FeatureFlags.GROCY_FEATURE_FLAG_STOCK_LOCATION_TRACKING) + { + Grocy.Components.LocationPicker.Clear(); + } Grocy.Components.DateTimePicker.Clear(); Grocy.Components.ProductPicker.SetValue(''); Grocy.Components.ProductPicker.GetInputElement().focus(); @@ -107,7 +117,10 @@ Grocy.Components.ProductPicker.GetPicker().on('change', function(e) function (productDetails) { $('#price').val(productDetails.last_price); - Grocy.Components.LocationPicker.SetId(productDetails.location.id); + if (Grocy.FeatureFlags.GROCY_FEATURE_FLAG_STOCK_LOCATION_TRACKING) + { + Grocy.Components.LocationPicker.SetId(productDetails.location.id); + } if (productDetails.product.qu_id_purchase === productDetails.product.qu_id_stock) { @@ -166,7 +179,15 @@ Grocy.Components.ProductPicker.GetPicker().on('change', function(e) } else { - Grocy.Components.DateTimePicker.GetInputElement().focus(); + if (Grocy.FeatureFlags.GROCY_FEATURE_FLAG_STOCK_BEST_BEFORE_DATE_TRACKING) + { + Grocy.Components.DateTimePicker.GetInputElement().focus(); + } + else + { + Grocy.Components.DateTimePicker.SetValue(moment().format('YYYY-MM-DD')); + $('#amount').focus(); + } } }, function(xhr) diff --git a/views/components/datetimepicker.blade.php b/views/components/datetimepicker.blade.php index b1506464..5d6c0679 100644 --- a/views/components/datetimepicker.blade.php +++ b/views/components/datetimepicker.blade.php @@ -13,8 +13,9 @@ @php if(!isset($noNameAttribute)) { $noNameAttribute = false; } @endphp @php if(!isset($nextInputSelector)) { $nextInputSelector = false; } @endphp @php if(empty($additionalAttributes)) { $additionalAttributes = ''; } @endphp +@php if(empty($additionalGroupCssClasses)) { $additionalGroupCssClasses = ''; } @endphp -
+
diff --git a/views/consume.blade.php b/views/consume.blade.php index 0523dc54..bb54450a 100644 --- a/views/consume.blade.php +++ b/views/consume.blade.php @@ -52,7 +52,10 @@ @endif + + @if(GROCY_FEATURE_FLAG_STOCK_PRODUCT_OPENED_TRACKING) + @endif diff --git a/views/inventory.blade.php b/views/inventory.blade.php index 758118bc..cf1f48ce 100644 --- a/views/inventory.blade.php +++ b/views/inventory.blade.php @@ -28,6 +28,13 @@ 'additionalHtmlContextHelp' => '
' . $__t('Tare weight handling enabled - please weigh the whole container, the amount to be posted will be automatically calculcated') . '
' )) + @php + $additionalGroupCssClasses = ''; + if (!GROCY_FEATURE_FLAG_STOCK_BEST_BEFORE_DATE_TRACKING) + { + $additionalGroupCssClasses = 'd-none'; + } + @endphp @include('components.datetimepicker', array( 'id' => 'best_before_date', 'label' => 'Best before', @@ -42,9 +49,12 @@ 'shortcutValue' => '2999-12-31', 'shortcutLabel' => 'Never expires', 'earlierThanInfoLimit' => date('Y-m-d'), - 'earlierThanInfoText' => $__t('The given date is earlier than today, are you sure?') + 'earlierThanInfoText' => $__t('The given date is earlier than today, are you sure?'), + 'additionalGroupCssClasses' => $additionalGroupCssClasses )) + @php $additionalGroupCssClasses = ''; @endphp + @if(GROCY_FEATURE_FLAG_STOCK_PRICE_TRACKING) @include('components.numberpicker', array( 'id' => 'price', 'label' => 'Price', @@ -56,11 +66,18 @@ 'invalidFeedback' => $__t('The price cannot be lower than %s', '0'), 'isRequired' => false )) + @else + + @endif + @if(GROCY_FEATURE_FLAG_STOCK_LOCATION_TRACKING) @include('components.locationpicker', array( 'locations' => $locations, 'hint' => $__t('This will apply to added products') )) + @else + + @endif diff --git a/views/layout/default.blade.php b/views/layout/default.blade.php index 824acc03..5d8d7b72 100644 --- a/views/layout/default.blade.php +++ b/views/layout/default.blade.php @@ -212,12 +212,14 @@ {{ $__t('Products') }} + @if(GROCY_FEATURE_FLAG_STOCK_LOCATION_TRACKING)
  • {{ $__t('Locations') }}
  • + @endif
  • diff --git a/views/productform.blade.php b/views/productform.blade.php index 18fba278..4969b5d9 100644 --- a/views/productform.blade.php +++ b/views/productform.blade.php @@ -73,6 +73,7 @@
    + @if(GROCY_FEATURE_FLAG_STOCK_LOCATION_TRACKING)
    {{ $__t('A location is required') }}
    + @else + + @endif @php if($mode == 'edit') { $value = $product->min_stock_amount; } else { $value = 0; } @endphp @include('components.numberpicker', array( diff --git a/views/products.blade.php b/views/products.blade.php index aa34e0e7..74e22829 100644 --- a/views/products.blade.php +++ b/views/products.blade.php @@ -45,7 +45,7 @@ {{ $__t('Name') }} - {{ $__t('Location') }} + {{ $__t('Location') }} {{ $__t('Min. stock amount') }} {{ $__t('QU purchase') }} {{ $__t('QU stock') }} @@ -73,7 +73,7 @@ {{ $product->name }}@if(!empty($product->picture_file_name)) @endif - + {{ FindObjectInArrayByPropertyValue($locations, 'id', $product->location_id)->name }} diff --git a/views/purchase.blade.php b/views/purchase.blade.php index 161462cd..354495b2 100644 --- a/views/purchase.blade.php +++ b/views/purchase.blade.php @@ -16,6 +16,13 @@ 'nextInputSelector' => '#best_before_date .datetimepicker-input' )) + @php + $additionalGroupCssClasses = ''; + if (!GROCY_FEATURE_FLAG_STOCK_BEST_BEFORE_DATE_TRACKING) + { + $additionalGroupCssClasses = 'd-none'; + } + @endphp @include('components.datetimepicker', array( 'id' => 'best_before_date', 'label' => 'Best before', @@ -29,8 +36,10 @@ 'shortcutValue' => '2999-12-31', 'shortcutLabel' => 'Never expires', 'earlierThanInfoLimit' => date('Y-m-d'), - 'earlierThanInfoText' => $__t('The given date is earlier than today, are you sure?') + 'earlierThanInfoText' => $__t('The given date is earlier than today, are you sure?'), + 'additionalGroupCssClasses' => $additionalGroupCssClasses )) + @php $additionalGroupCssClasses = ''; @endphp @include('components.numberpicker', array( 'id' => 'amount', @@ -41,6 +50,7 @@ 'additionalHtmlContextHelp' => '
    ' . $__t('Tare weight handling enabled - please weigh the whole container, the amount to be posted will be automatically calculcated') . '
    ' )) + @if(GROCY_FEATURE_FLAG_STOCK_PRICE_TRACKING) @include('components.numberpicker', array( 'id' => 'price', 'label' => 'Price', @@ -51,11 +61,18 @@ 'invalidFeedback' => $__t('The price cannot be lower than %s', '0'), 'isRequired' => false )) + @else + + @endif + @if(GROCY_FEATURE_FLAG_STOCK_LOCATION_TRACKING) @include('components.locationpicker', array( 'locations' => $locations, 'isRequired' => false )) + @else + + @endif diff --git a/views/recipes.blade.php b/views/recipes.blade.php index af59fbdc..f5032996 100644 --- a/views/recipes.blade.php +++ b/views/recipes.blade.php @@ -155,6 +155,7 @@ 'additionalAttributes' => 'data-recipe-id="' . $selectedRecipe->id . '"' )) + @if(GROCY_FEATURE_FLAG_STOCK_PRICE_TRACKING)
    + @endif diff --git a/views/stockoverview.blade.php b/views/stockoverview.blade.php index 8bc4adfb..851165b0 100644 --- a/views/stockoverview.blade.php +++ b/views/stockoverview.blade.php @@ -24,12 +24,16 @@
    {{ $__t('Journal') }} + @if(GROCY_FEATURE_FLAG_STOCK_LOCATION_TRACKING) {{ $__t('Location Content Sheet') }} + @endif + @if (GROCY_FEATURE_FLAG_STOCK_BEST_BEFORE_DATE_TRACKING)

    + @endif

    @@ -39,6 +43,7 @@ + @if(GROCY_FEATURE_FLAG_STOCK_LOCATION_TRACKING)
    + @endif
    + @if (GROCY_FEATURE_FLAG_STOCK_BEST_BEFORE_DATE_TRACKING) + @endif
    @@ -89,7 +97,7 @@ @foreach($currentStock as $currentStockEntry) - amount > 0) table-warning @elseif (FindObjectInArrayByPropertyValue($missingProducts, 'id', $currentStockEntry->product_id) !== null) table-info @endif"> + amount > 0) table-warning @elseif (FindObjectInArrayByPropertyValue($missingProducts, 'id', $currentStockEntry->product_id) !== null) table-info @endif"> {{ $__t('All') }} + @if(GROCY_FEATURE_FLAG_STOCK_PRODUCT_OPENED_TRACKING) 1 + @endif