-
-
Notifications
You must be signed in to change notification settings - Fork 607
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
d1174ea
commit 3e083e2
Showing
8 changed files
with
281 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
{% extends "base.html" %} | ||
{% load render_bundle from webpack_loader %} | ||
{% load static %} | ||
{% load i18n %} | ||
{% load l10n %} | ||
|
||
{% block title %}{% trans 'Property Editor' %}{% endblock %} | ||
|
||
{% block content_fluid %} | ||
|
||
<div id="app"> | ||
<property-editor-view></property-editor-view> | ||
</div> | ||
|
||
|
||
{% endblock %} | ||
|
||
|
||
{% block script %} | ||
{% if debug %} | ||
<script src="{% url 'js_reverse' %}"></script> | ||
{% else %} | ||
<script src="{% static 'django_js_reverse/reverse.js' %}"></script> | ||
{% endif %} | ||
|
||
<script type="application/javascript"> | ||
window.RECIPE_ID = {{ recipe_id }} | ||
</script> | ||
|
||
{% render_bundle 'property_editor_view' %} | ||
{% endblock %} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,209 @@ | ||
<template> | ||
|
||
<div id="app"> | ||
<div> | ||
<div class="row" v-if="recipe" style="max-height: 10vh"> | ||
|
||
<div class="col col-8"> | ||
<h2><a :href="resolveDjangoUrl('view_recipe', recipe.id)">{{ recipe.name }}</a></h2> | ||
{{ recipe.description }} | ||
<keywords-component :recipe="recipe"></keywords-component> | ||
</div> | ||
<div class="col col-4" v-if="recipe.image"> | ||
<img style="max-height: 10vh" class="img-thumbnail float-right" :src="recipe.image"> | ||
</div> | ||
</div> | ||
|
||
|
||
<div class="row mt-5"> | ||
<div class="col col-12"> | ||
|
||
<table class="table table-sm table-bordered table-responsive"> | ||
<thead> | ||
<tr> | ||
<td>{{ $t('Name') }}</td> | ||
<td>FDC</td> | ||
<td>{{ $t('Properties_Food_Amount') }}</td> | ||
<td>{{ $t('Properties_Food_Unit') }}</td> | ||
<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 }} <span v-if="pt.unit !== ''">({{ pt.unit }})</span></b-button> | ||
</td> | ||
</tr> | ||
</thead> | ||
<tbody> | ||
<tr v-for="f in this.foods" v-bind:key="f.id"> | ||
<td> | ||
{{ f.name }} | ||
</td> | ||
<td style="width: 11em;"> | ||
<b-input-group> | ||
<b-form-input v-model="f.fdc_id" type="number" @change="updateFood(f)" :disabled="f.loading"></b-form-input> | ||
<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-input-group-append> | ||
</b-input-group> | ||
|
||
</td> | ||
<td style="width: 5em; "> | ||
<b-input v-model="f.properties_food_amount" type="number" @change="updateFood(f)" :disabled="f.loading"></b-input> | ||
</td> | ||
<td style="width: 8em;"> | ||
<generic-multiselect | ||
@change="f.properties_food_unit = $event.val; updateFood(f)" | ||
:initial_single_selection="f.properties_food_unit" | ||
label="name" :model="Models.UNIT" | ||
:multiple="false" | ||
:disabled="f.loading"/> | ||
</td> | ||
<td v-for="p in f.properties" v-bind:key="`${f.id}_${p.property_type.id}`"> | ||
<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> | ||
</b-input-group> | ||
</td> | ||
</tr> | ||
</tbody> | ||
</table> | ||
</div> | ||
</div> | ||
|
||
|
||
<generic-modal-form | ||
:show="editing_property_type !== null" | ||
:model="Models.PROPERTY_TYPE" | ||
:action="Actions.UPDATE" | ||
:item1="editing_property_type" | ||
@finish-action="editing_property_type = null; loadData()"> | ||
</generic-modal-form> | ||
|
||
</div> | ||
</div> | ||
</template> | ||
|
||
|
||
<script> | ||
import Vue from "vue" | ||
import {BootstrapVue} from "bootstrap-vue" | ||
import "bootstrap-vue/dist/bootstrap-vue.css" | ||
import {ApiMixin, resolveDjangoUrl, StandardToasts} from "@/utils/utils"; | ||
import axios from "axios"; | ||
import BetaWarning from "@/components/BetaWarning.vue"; | ||
import {ApiApiFactory} from "@/utils/openapi/api"; | ||
import GenericMultiselect from "@/components/GenericMultiselect.vue"; | ||
import GenericModalForm from "@/components/Modals/GenericModalForm.vue"; | ||
import KeywordsComponent from "@/components/KeywordsComponent.vue"; | ||
Vue.use(BootstrapVue) | ||
export default { | ||
name: "PropertyEditorView", | ||
mixins: [ApiMixin], | ||
components: {KeywordsComponent, GenericModalForm, GenericMultiselect}, | ||
computed: {}, | ||
data() { | ||
return { | ||
recipe: null, | ||
property_types: [], | ||
editing_property_type: null, | ||
loading: false, | ||
foods: [], | ||
} | ||
}, | ||
mounted() { | ||
this.$i18n.locale = window.CUSTOM_LOCALE | ||
this.loadData(); | ||
}, | ||
methods: { | ||
resolveDjangoUrl, | ||
loadData: function () { | ||
let apiClient = new ApiApiFactory() | ||
apiClient.listPropertyTypes().then(result => { | ||
this.property_types = result.data | ||
apiClient.retrieveRecipe(window.RECIPE_ID).then(result => { | ||
this.recipe = result.data | ||
this.foods = [] | ||
this.recipe.steps.forEach(s => { | ||
s.ingredients.forEach(i => { | ||
if (this.foods.filter(x => (x.id === i.food.id)).length === 0) { | ||
this.foods.push(this.buildFood(i.food)) | ||
} | ||
}) | ||
}) | ||
this.loading = false; | ||
}).catch((err) => { | ||
StandardToasts.makeStandardToast(this, StandardToasts.FAIL_FETCH, err) | ||
}) | ||
}).catch((err) => { | ||
StandardToasts.makeStandardToast(this, StandardToasts.FAIL_FETCH, err) | ||
}) | ||
}, | ||
buildFood: function (food) { | ||
/** | ||
* Prepare food for display in grid by making sure the food properties are in the same order as property_types and that no types are missing | ||
* */ | ||
let existing_properties = {} | ||
food.properties.forEach(fp => { | ||
existing_properties[fp.property_type.id] = fp | ||
}) | ||
let food_properties = [] | ||
this.property_types.forEach(pt => { | ||
let new_food_property = { | ||
property_type: pt, | ||
property_amount: 0, | ||
} | ||
if (pt.id in existing_properties) { | ||
new_food_property = existing_properties[pt.id] | ||
} | ||
food_properties.push(new_food_property) | ||
}) | ||
this.$set(food, 'loading', false) | ||
food.properties = food_properties | ||
return food | ||
}, | ||
spliceInFood: function (food) { | ||
/** | ||
* replace food in foods list, for example after updates from the server | ||
*/ | ||
this.foods = this.foods.map(f => (f.id === food.id) ? food : f) | ||
}, | ||
updateFood: function (food) { | ||
let apiClient = new ApiApiFactory() | ||
apiClient.partialUpdateFood(food.id, food).then(result => { | ||
this.spliceInFood(this.buildFood(result.data)) | ||
StandardToasts.makeStandardToast(this, StandardToasts.SUCCESS_UPDATE) | ||
}).catch((err) => { | ||
StandardToasts.makeStandardToast(this, StandardToasts.FAIL_UPDATE, err) | ||
}) | ||
}, | ||
updateFoodFromFDC: function (food) { | ||
food.loading = true; | ||
let apiClient = new ApiApiFactory() | ||
apiClient.fdcFood(food.id).then(result => { | ||
StandardToasts.makeStandardToast(this, StandardToasts.SUCCESS_UPDATE) | ||
this.spliceInFood(this.buildFood(result.data)) | ||
}).catch((err) => { | ||
StandardToasts.makeStandardToast(this, StandardToasts.FAIL_UPDATE, err) | ||
food.loading = false; | ||
}) | ||
} | ||
}, | ||
} | ||
</script> | ||
|
||
<style> | ||
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import Vue from 'vue' | ||
import App from './PropertyEditorView.vue' | ||
import i18n from '@/i18n' | ||
import {createPinia, PiniaVuePlugin} from "pinia"; | ||
|
||
Vue.config.productionTip = false | ||
|
||
// TODO move this and other default stuff to centralized JS file (verify nothing breaks) | ||
let publicPath = localStorage.STATIC_URL + 'vue/' | ||
if (process.env.NODE_ENV === 'development') { | ||
publicPath = 'http://localhost:8080/' | ||
} | ||
export default __webpack_public_path__ = publicPath // eslint-disable-line | ||
|
||
Vue.use(PiniaVuePlugin) | ||
const pinia = createPinia() | ||
|
||
new Vue({ | ||
pinia, | ||
i18n, | ||
render: h => h(App), | ||
}).$mount('#app') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters