improved property system to differentiate between unknown and zero
This commit is contained in:
parent
717d4d2346
commit
28479e96e9
@ -182,6 +182,8 @@ class OpenDataImporter:
|
|||||||
self._update_slug_cache(PropertyType, 'property')
|
self._update_slug_cache(PropertyType, 'property')
|
||||||
self._update_slug_cache(SupermarketCategory, 'category')
|
self._update_slug_cache(SupermarketCategory, 'category')
|
||||||
|
|
||||||
|
unit_g = Unit.objects.filter(space=self.request.space, base_unit__iexact='g').first()
|
||||||
|
|
||||||
existing_data = {}
|
existing_data = {}
|
||||||
for obj in Food.objects.filter(space=self.request.space, open_data_slug__isnull=False).values('pk', 'name', 'open_data_slug'):
|
for obj in Food.objects.filter(space=self.request.space, open_data_slug__isnull=False).values('pk', 'name', 'open_data_slug'):
|
||||||
existing_data[obj['open_data_slug']] = obj
|
existing_data[obj['open_data_slug']] = obj
|
||||||
@ -197,6 +199,7 @@ class OpenDataImporter:
|
|||||||
'supermarket_category_id': self.slug_id_cache['category'][self.data[datatype][k]['store_category']],
|
'supermarket_category_id': self.slug_id_cache['category'][self.data[datatype][k]['store_category']],
|
||||||
'fdc_id': re.sub(r'\D', '', self.data[datatype][k]['fdc_id']) if self.data[datatype][k]['fdc_id'] != '' else None,
|
'fdc_id': re.sub(r'\D', '', self.data[datatype][k]['fdc_id']) if self.data[datatype][k]['fdc_id'] != '' else None,
|
||||||
'open_data_slug': k,
|
'open_data_slug': k,
|
||||||
|
'properties_food_unit': unit_g,
|
||||||
'space': self.request.space.id,
|
'space': self.request.space.id,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,7 +213,7 @@ class OpenDataImporter:
|
|||||||
|
|
||||||
total_count = 0
|
total_count = 0
|
||||||
if self.update_existing and len(update_list) > 0:
|
if self.update_existing and len(update_list) > 0:
|
||||||
Food.objects.bulk_update(update_list, ['name', 'plural_name', 'preferred_unit_id', 'preferred_shopping_unit_id', 'supermarket_category_id', 'fdc_id', 'open_data_slug', ])
|
Food.objects.bulk_update(update_list, ['name', 'plural_name', 'properties_food_unit', 'supermarket_category_id', 'fdc_id', 'open_data_slug', ])
|
||||||
total_count += len(update_list)
|
total_count += len(update_list)
|
||||||
|
|
||||||
if len(create_list) > 0:
|
if len(create_list) > 0:
|
||||||
|
@ -46,7 +46,7 @@ class FoodPropertyHelper:
|
|||||||
for pt in property_types:
|
for pt in property_types:
|
||||||
found_property = False
|
found_property = False
|
||||||
if i.food.properties_food_amount == 0 or i.food.properties_food_unit is None:
|
if i.food.properties_food_amount == 0 or i.food.properties_food_unit is None:
|
||||||
computed_properties[pt.id]['food_values'][i.food.id] = {'id': i.food.id, 'food': i.food.name, 'value': 0}
|
computed_properties[pt.id]['food_values'][i.food.id] = {'id': i.food.id, 'food': i.food.name, 'value': None}
|
||||||
computed_properties[pt.id]['missing_value'] = i.food.properties_food_unit is None
|
computed_properties[pt.id]['missing_value'] = i.food.properties_food_unit is None
|
||||||
else:
|
else:
|
||||||
for p in i.food.properties.all():
|
for p in i.food.properties.all():
|
||||||
@ -59,7 +59,7 @@ class FoodPropertyHelper:
|
|||||||
computed_properties[p.property_type.id]['food_values'], c.food.id, (c.amount / i.food.properties_food_amount) * p.property_amount, c.food)
|
computed_properties[p.property_type.id]['food_values'], c.food.id, (c.amount / i.food.properties_food_amount) * p.property_amount, c.food)
|
||||||
if not found_property:
|
if not found_property:
|
||||||
computed_properties[pt.id]['missing_value'] = True
|
computed_properties[pt.id]['missing_value'] = True
|
||||||
computed_properties[pt.id]['food_values'][i.food.id] = {'id': i.food.id, 'food': i.food.name, 'value': 0}
|
computed_properties[pt.id]['food_values'][i.food.id] = {'id': i.food.id, 'food': i.food.name, 'value': None}
|
||||||
|
|
||||||
return computed_properties
|
return computed_properties
|
||||||
|
|
||||||
|
18
cookbook/migrations/0212_alter_property_property_amount.py
Normal file
18
cookbook/migrations/0212_alter_property_property_amount.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 4.2.7 on 2024-02-18 07:51
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('cookbook', '0211_recipebook_order'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='property',
|
||||||
|
name='property_amount',
|
||||||
|
field=models.DecimalField(decimal_places=4, default=None, max_digits=32, null=True),
|
||||||
|
),
|
||||||
|
]
|
@ -846,7 +846,7 @@ class PropertyType(models.Model, PermissionModelMixin):
|
|||||||
|
|
||||||
|
|
||||||
class Property(models.Model, PermissionModelMixin):
|
class Property(models.Model, PermissionModelMixin):
|
||||||
property_amount = models.DecimalField(default=0, decimal_places=4, max_digits=32)
|
property_amount = models.DecimalField(default=None, null=True, decimal_places=4, max_digits=32)
|
||||||
property_type = models.ForeignKey(PropertyType, on_delete=models.PROTECT)
|
property_type = models.ForeignKey(PropertyType, on_delete=models.PROTECT)
|
||||||
|
|
||||||
import_food_id = models.IntegerField(null=True, blank=True) # field to hold food id when importing properties from the open data project
|
import_food_id = models.IntegerField(null=True, blank=True) # field to hold food id when importing properties from the open data project
|
||||||
|
@ -563,7 +563,7 @@ class PropertyTypeSerializer(OpenDataModelMixin, WritableNestedModelSerializer,
|
|||||||
|
|
||||||
class PropertySerializer(UniqueFieldsMixin, WritableNestedModelSerializer):
|
class PropertySerializer(UniqueFieldsMixin, WritableNestedModelSerializer):
|
||||||
property_type = PropertyTypeSerializer()
|
property_type = PropertyTypeSerializer()
|
||||||
property_amount = CustomDecimalField()
|
property_amount = CustomDecimalField(allow_null=True)
|
||||||
|
|
||||||
def create(self, validated_data):
|
def create(self, validated_data):
|
||||||
validated_data['space'] = self.context['request'].space
|
validated_data['space'] = self.context['request'].space
|
||||||
|
@ -67,7 +67,7 @@ def test_food_property(space_1, space_2, u1_s1):
|
|||||||
|
|
||||||
assert property_values[property_fat.id]['name'] == property_fat.name
|
assert property_values[property_fat.id]['name'] == property_fat.name
|
||||||
assert abs(property_values[property_fat.id]['total_value']) < 0.0001
|
assert abs(property_values[property_fat.id]['total_value']) < 0.0001
|
||||||
assert abs(property_values[property_fat.id]['food_values'][food_1.id]['value']) < 0.0001
|
assert property_values[property_fat.id]['food_values'][food_1.id]['value'] is None
|
||||||
|
|
||||||
print('\n----------- TEST PROPERTY - PROPERTY CALCULATION UNIT CONVERSION ---------------')
|
print('\n----------- TEST PROPERTY - PROPERTY CALCULATION UNIT CONVERSION ---------------')
|
||||||
uc1 = UnitConversion.objects.create(
|
uc1 = UnitConversion.objects.create(
|
||||||
|
@ -607,11 +607,21 @@ class FoodViewSet(viewsets.ModelViewSet, TreeMixin):
|
|||||||
if properties with a fdc_id already exist they will be overridden, if existing properties don't have a fdc_id they won't be changed
|
if properties with a fdc_id already exist they will be overridden, if existing properties don't have a fdc_id they won't be changed
|
||||||
"""
|
"""
|
||||||
food = self.get_object()
|
food = self.get_object()
|
||||||
|
if not food.fdc_id:
|
||||||
|
return JsonResponse({'msg': 'Food has no FDC ID associated.'}, status=400,
|
||||||
|
json_dumps_params={'indent': 4})
|
||||||
|
|
||||||
response = requests.get(f'https://api.nal.usda.gov/fdc/v1/food/{food.fdc_id}?api_key={FDC_API_KEY}')
|
response = requests.get(f'https://api.nal.usda.gov/fdc/v1/food/{food.fdc_id}?api_key={FDC_API_KEY}')
|
||||||
if response.status_code == 429:
|
if response.status_code == 429:
|
||||||
return JsonResponse({'msg', 'API Key Rate Limit reached/exceeded, see https://api.data.gov/docs/rate-limits/ for more information. Configure your key in Tandoor using environment FDC_API_KEY variable.'}, status=429,
|
return JsonResponse({'msg': 'API Key Rate Limit reached/exceeded, see https://api.data.gov/docs/rate-limits/ for more information. Configure your key in Tandoor using environment FDC_API_KEY variable.'}, status=429,
|
||||||
json_dumps_params={'indent': 4})
|
json_dumps_params={'indent': 4})
|
||||||
|
if response.status_code != 200:
|
||||||
|
return JsonResponse({'msg': f'Error while requesting FDC data using url https://api.nal.usda.gov/fdc/v1/food/{food.fdc_id}?api_key=****'}, status=response.status_code,
|
||||||
|
json_dumps_params={'indent': 4})
|
||||||
|
|
||||||
|
food.properties_food_amount = 100
|
||||||
|
food.properties_food_unit = Unit.objects.get_or_create(base_unit__iexact='g', space=self.request.space, defaults={'name': 'g', 'base_unit': 'g', 'space': self.request.space})[0]
|
||||||
|
food.save()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
data = json.loads(response.content)
|
data = json.loads(response.content)
|
||||||
@ -625,14 +635,23 @@ class FoodViewSet(viewsets.ModelViewSet, TreeMixin):
|
|||||||
|
|
||||||
for pt in PropertyType.objects.filter(space=request.space, fdc_id__gte=0).all():
|
for pt in PropertyType.objects.filter(space=request.space, fdc_id__gte=0).all():
|
||||||
if pt.fdc_id:
|
if pt.fdc_id:
|
||||||
|
property_found = False
|
||||||
for fn in data['foodNutrients']:
|
for fn in data['foodNutrients']:
|
||||||
if fn['nutrient']['id'] == pt.fdc_id:
|
if fn['nutrient']['id'] == pt.fdc_id:
|
||||||
|
property_found = True
|
||||||
food_property_list.append(Property(
|
food_property_list.append(Property(
|
||||||
property_type_id=pt.id,
|
property_type_id=pt.id,
|
||||||
property_amount=max(0, round(fn['amount'], 2)), # sometimes FDC might return negative values which make no sense, set to 0
|
property_amount=max(0, round(fn['amount'], 2)), # sometimes FDC might return negative values which make no sense, set to 0
|
||||||
import_food_id=food.id,
|
import_food_id=food.id,
|
||||||
space=self.request.space,
|
space=self.request.space,
|
||||||
))
|
))
|
||||||
|
if not property_found:
|
||||||
|
food_property_list.append(Property(
|
||||||
|
property_type_id=pt.id,
|
||||||
|
property_amount=0, # if field not in FDC data the food does not have that property
|
||||||
|
import_food_id=food.id,
|
||||||
|
space=self.request.space,
|
||||||
|
))
|
||||||
|
|
||||||
Property.objects.bulk_create(food_property_list, ignore_conflicts=True, unique_fields=('space', 'import_food_id', 'property_type',))
|
Property.objects.bulk_create(food_property_list, ignore_conflicts=True, unique_fields=('space', 'import_food_id', 'property_type',))
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
<h2><a :href="resolveDjangoUrl('view_recipe', recipe.id)">{{ recipe.name }}</a></h2>
|
<h2><a :href="resolveDjangoUrl('view_recipe', recipe.id)">{{ recipe.name }}</a></h2>
|
||||||
{{ recipe.description }}
|
{{ recipe.description }}
|
||||||
<keywords-component :recipe="recipe"></keywords-component>
|
<keywords-component :recipe="recipe"></keywords-component>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col col-4" v-if="recipe.image">
|
<div class="col col-4" v-if="recipe.image">
|
||||||
<img style="max-height: 10vh" class="img-thumbnail float-right" :src="recipe.image">
|
<img style="max-height: 10vh" class="img-thumbnail float-right" :src="recipe.image">
|
||||||
@ -17,7 +18,7 @@
|
|||||||
|
|
||||||
<div class="row mt-3">
|
<div class="row mt-3">
|
||||||
<div class="col col-12">
|
<div class="col col-12">
|
||||||
<b-button variant="success" href="https://fdc.nal.usda.gov/index.html" target="_blank"><i class="fas fa-external-link-alt"></i> {{$t('FDC_Search')}}</b-button>
|
<b-button variant="success" href="https://fdc.nal.usda.gov/index.html" target="_blank"><i class="fas fa-external-link-alt"></i> {{ $t('FDC_Search') }}</b-button>
|
||||||
|
|
||||||
<table class="table table-sm table-bordered table-responsive mt-2 pb-5">
|
<table class="table table-sm table-bordered table-responsive mt-2 pb-5">
|
||||||
<thead>
|
<thead>
|
||||||
@ -29,7 +30,7 @@
|
|||||||
<td v-for="pt in property_types" v-bind:key="pt.id">
|
<td v-for="pt in property_types" v-bind:key="pt.id">
|
||||||
<b-button variant="primary" @click="editing_property_type = pt" class="btn-block">{{ pt.name }}
|
<b-button variant="primary" @click="editing_property_type = pt" class="btn-block">{{ pt.name }}
|
||||||
<span v-if="pt.unit !== ''">({{ pt.unit }}) </span> <br/>
|
<span v-if="pt.unit !== ''">({{ pt.unit }}) </span> <br/>
|
||||||
<b-badge variant="light" ><i class="fas fa-sort-amount-down-alt"></i> {{ pt.order}}</b-badge>
|
<b-badge variant="light"><i class="fas fa-sort-amount-down-alt"></i> {{ pt.order }}</b-badge>
|
||||||
<b-badge variant="success" v-if="pt.fdc_id > 0" class="mt-2" v-b-tooltip.hover :title="$t('property_type_fdc_hint')"><i class="fas fa-check"></i> FDC</b-badge>
|
<b-badge variant="success" v-if="pt.fdc_id > 0" class="mt-2" v-b-tooltip.hover :title="$t('property_type_fdc_hint')"><i class="fas fa-check"></i> FDC</b-badge>
|
||||||
<b-badge variant="warning" v-if="pt.fdc_id < 1" class="mt-2" v-b-tooltip.hover :title="$t('property_type_fdc_hint')"><i class="fas fa-times"></i> FDC</b-badge>
|
<b-badge variant="warning" v-if="pt.fdc_id < 1" class="mt-2" v-b-tooltip.hover :title="$t('property_type_fdc_hint')"><i class="fas fa-times"></i> FDC</b-badge>
|
||||||
</b-button>
|
</b-button>
|
||||||
@ -48,7 +49,7 @@
|
|||||||
<b-input-group>
|
<b-input-group>
|
||||||
<b-form-input v-model="f.fdc_id" type="number" @change="updateFood(f)" :disabled="f.loading"></b-form-input>
|
<b-form-input v-model="f.fdc_id" type="number" @change="updateFood(f)" :disabled="f.loading"></b-form-input>
|
||||||
<b-input-group-append>
|
<b-input-group-append>
|
||||||
<b-button variant="success" @click="updateFoodFromFDC(f)" :disabled="f.loading"><i class="fas fa-sync-alt" :class="{'fa-spin': loading}"></i></b-button>
|
<b-button variant="success" @click="updateFoodFromFDC(f)" :disabled="f.loading || f.fdc_id < 1"><i class="fas fa-sync-alt" :class="{'fa-spin': loading}"></i></b-button>
|
||||||
<b-button variant="info" :href="`https://fdc.nal.usda.gov/fdc-app.html#/food-details/${f.fdc_id}`" :disabled="f.fdc_id < 1" target="_blank"><i class="fas fa-external-link-alt"></i></b-button>
|
<b-button variant="info" :href="`https://fdc.nal.usda.gov/fdc-app.html#/food-details/${f.fdc_id}`" :disabled="f.fdc_id < 1" target="_blank"><i class="fas fa-external-link-alt"></i></b-button>
|
||||||
</b-input-group-append>
|
</b-input-group-append>
|
||||||
</b-input-group>
|
</b-input-group>
|
||||||
@ -67,7 +68,12 @@
|
|||||||
</td>
|
</td>
|
||||||
<td v-for="p in f.properties" v-bind:key="`${f.id}_${p.property_type.id}`">
|
<td v-for="p in f.properties" v-bind:key="`${f.id}_${p.property_type.id}`">
|
||||||
<b-input-group>
|
<b-input-group>
|
||||||
<b-form-input v-model="p.property_amount" type="number" :disabled="f.loading" v-b-tooltip.focus :title="p.property_type.name" @change="updateFood(f)"></b-form-input>
|
<template v-if="p.property_amount == null">
|
||||||
|
<b-btn class="btn-sm btn-block btn-success" @click="p.property_amount = 0; updateFood(f)">Add</b-btn>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<b-form-input v-model="p.property_amount" type="number" :disabled="f.loading" v-b-tooltip.focus :title="p.property_type.name" @change="updateFood(f)"></b-form-input>
|
||||||
|
</template>
|
||||||
</b-input-group>
|
</b-input-group>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -76,6 +82,40 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<b-row class="mt-2">
|
||||||
|
<b-col>
|
||||||
|
<b-card>
|
||||||
|
<b-card-title>
|
||||||
|
<i class="fas fa-calculator"></i> {{ $t('Calculator') }}
|
||||||
|
</b-card-title>
|
||||||
|
<b-card-text>
|
||||||
|
<b-form inline>
|
||||||
|
<b-input type="number" v-model="calculator_from_amount"></b-input>
|
||||||
|
<i class="fas fa-divide fa-fw mr-1 ml-1"></i>
|
||||||
|
<b-input type="number" v-model="calculator_from_per"></b-input>
|
||||||
|
<i class="fas fa-equals fa-fw mr-1 ml-1"></i>
|
||||||
|
|
||||||
|
<b-input-group >
|
||||||
|
<b-input v-model="calculator_to_amount" disabled></b-input>
|
||||||
|
<b-input-group-append>
|
||||||
|
<b-btn variant="success" @click="copyCalculatedResult()"><i class="far fa-copy"></i></b-btn>
|
||||||
|
</b-input-group-append>
|
||||||
|
</b-input-group>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<i class="fas fa-divide fa-fw mr-1 ml-1"></i>
|
||||||
|
<b-input type="number" v-model="calculator_to_per"></b-input>
|
||||||
|
</b-form>
|
||||||
|
</b-card-text>
|
||||||
|
|
||||||
|
</b-card>
|
||||||
|
|
||||||
|
|
||||||
|
</b-col>
|
||||||
|
|
||||||
|
</b-row>
|
||||||
|
|
||||||
|
|
||||||
<generic-modal-form
|
<generic-modal-form
|
||||||
:show="editing_property_type !== null"
|
:show="editing_property_type !== null"
|
||||||
@ -109,8 +149,8 @@ import {ApiApiFactory} from "@/utils/openapi/api";
|
|||||||
import GenericMultiselect from "@/components/GenericMultiselect.vue";
|
import GenericMultiselect from "@/components/GenericMultiselect.vue";
|
||||||
import GenericModalForm from "@/components/Modals/GenericModalForm.vue";
|
import GenericModalForm from "@/components/Modals/GenericModalForm.vue";
|
||||||
import KeywordsComponent from "@/components/KeywordsComponent.vue";
|
import KeywordsComponent from "@/components/KeywordsComponent.vue";
|
||||||
|
import VueClipboard from 'vue-clipboard2'
|
||||||
|
Vue.use(VueClipboard)
|
||||||
Vue.use(BootstrapVue)
|
Vue.use(BootstrapVue)
|
||||||
|
|
||||||
|
|
||||||
@ -118,7 +158,11 @@ export default {
|
|||||||
name: "PropertyEditorView",
|
name: "PropertyEditorView",
|
||||||
mixins: [ApiMixin],
|
mixins: [ApiMixin],
|
||||||
components: {KeywordsComponent, GenericModalForm, GenericMultiselect},
|
components: {KeywordsComponent, GenericModalForm, GenericMultiselect},
|
||||||
computed: {},
|
computed: {
|
||||||
|
calculator_to_amount: function () {
|
||||||
|
return (this.calculator_from_amount / this.calculator_from_per * this.calculator_to_per).toFixed(2)
|
||||||
|
},
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
recipe: null,
|
recipe: null,
|
||||||
@ -127,6 +171,10 @@ export default {
|
|||||||
new_property_type: false,
|
new_property_type: false,
|
||||||
loading: false,
|
loading: false,
|
||||||
foods: [],
|
foods: [],
|
||||||
|
|
||||||
|
calculator_from_amount: 1,
|
||||||
|
calculator_from_per: 300,
|
||||||
|
calculator_to_per: 100,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
@ -176,7 +224,7 @@ export default {
|
|||||||
this.property_types.forEach(pt => {
|
this.property_types.forEach(pt => {
|
||||||
let new_food_property = {
|
let new_food_property = {
|
||||||
property_type: pt,
|
property_type: pt,
|
||||||
property_amount: 0,
|
property_amount: null,
|
||||||
}
|
}
|
||||||
if (pt.id in existing_properties) {
|
if (pt.id in existing_properties) {
|
||||||
new_food_property = existing_properties[pt.id]
|
new_food_property = existing_properties[pt.id]
|
||||||
@ -217,6 +265,9 @@ export default {
|
|||||||
StandardToasts.makeStandardToast(this, StandardToasts.FAIL_UPDATE, err)
|
StandardToasts.makeStandardToast(this, StandardToasts.FAIL_UPDATE, err)
|
||||||
food.loading = false;
|
food.loading = false;
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
copyCalculatedResult: function(){
|
||||||
|
this.$copyText(this.calculator_to_amount)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -41,10 +41,8 @@
|
|||||||
|
|
||||||
<td class="align-middle text-center" v-if="!show_recipe_properties">
|
<td class="align-middle text-center" v-if="!show_recipe_properties">
|
||||||
<a href="#" @click="selected_property = p">
|
<a href="#" @click="selected_property = p">
|
||||||
<!-- <i v-if="p.missing_value" class="text-warning fas fa-exclamation-triangle"></i>-->
|
<i v-if="p.missing_value" class="text-warning fas fa-exclamation-triangle"></i>
|
||||||
<!-- <i v-if="!p.missing_value" class="text-muted fas fa-info-circle"></i>-->
|
<i v-if="!p.missing_value" class="text-muted fas fa-info-circle"></i>
|
||||||
<i class="text-muted fas fa-info-circle"></i>
|
|
||||||
<!-- TODO find solution for missing values as 0 can either be missing or actually correct for any given property -->
|
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -117,6 +115,7 @@ export default {
|
|||||||
has_food_properties = true
|
has_food_properties = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
console.log('has food propers', has_food_properties)
|
||||||
return has_food_properties
|
return has_food_properties
|
||||||
},
|
},
|
||||||
property_list: function () {
|
property_list: function () {
|
||||||
|
@ -83,6 +83,7 @@
|
|||||||
"Open_Data_Import": "Open Data Import",
|
"Open_Data_Import": "Open Data Import",
|
||||||
"Properties_Food_Amount": "Properties Food Amount",
|
"Properties_Food_Amount": "Properties Food Amount",
|
||||||
"Properties_Food_Unit": "Properties Food Unit",
|
"Properties_Food_Unit": "Properties Food Unit",
|
||||||
|
"Calculator": "Calculator",
|
||||||
"FDC_ID": "FDC ID",
|
"FDC_ID": "FDC ID",
|
||||||
"FDC_Search": "FDC Search",
|
"FDC_Search": "FDC Search",
|
||||||
"FDC_ID_help": "FDC database ID",
|
"FDC_ID_help": "FDC database ID",
|
||||||
|
Loading…
Reference in New Issue
Block a user