169 lines
4.5 KiB
Vue
169 lines
4.5 KiB
Vue
|
<template>
|
||
|
<div>
|
||
|
<button type="button" class="button is-primary" @click="bulkEditIngredients">Bulk Edit</button>
|
||
|
<app-modal :open="isBulkEditing" title="Edit Ingredients" @dismiss="cancelBulkEditing">
|
||
|
<div class="columns is-mobile">
|
||
|
<div class="column is-half">
|
||
|
<textarea ref="bulkEditTextarea" class="textarea is-size-7 bulk-input" v-model="bulkEditText"></textarea>
|
||
|
</div>
|
||
|
<div class="column is-half">
|
||
|
<table class="table is-bordered is-narrow is-size-7">
|
||
|
<tr>
|
||
|
<th>#</th>
|
||
|
<th>Unit</th>
|
||
|
<th>Name</th>
|
||
|
<th>Prep</th>
|
||
|
</tr>
|
||
|
<tr v-for="i in bulkIngredientPreview">
|
||
|
<td>{{i.quantity}}</td>
|
||
|
<td>{{i.units}}</td>
|
||
|
<td>{{i.name}}</td>
|
||
|
<td>{{i.preparation}}</td>
|
||
|
</tr>
|
||
|
</table>
|
||
|
</div>
|
||
|
</div>
|
||
|
<button class="button is-primary" type="button" @click="saveBulkEditing">Save</button>
|
||
|
<button class="button is-secondary" type="button" @click="cancelBulkEditing">Cancel</button>
|
||
|
</app-modal>
|
||
|
|
||
|
<recipe-edit-ingredient-item v-for="(i, idx) in visibleIngredients" :key="i.id" :ingredient="i" :show-labels="idx === 0 || isMobile" @deleteIngredient="deleteIngredient"></recipe-edit-ingredient-item>
|
||
|
|
||
|
<button type="button" class="button is-primary" @click="addIngredient">Add Ingredient</button>
|
||
|
</div>
|
||
|
</template>
|
||
|
|
||
|
<script>
|
||
|
|
||
|
import AppModal from "./AppModal";
|
||
|
import RecipeEditIngredientItem from "./RecipeEditIngredientItem";
|
||
|
|
||
|
import { mapState } from "vuex";
|
||
|
|
||
|
export default {
|
||
|
props: {
|
||
|
ingredients: {
|
||
|
required: true,
|
||
|
type: Array
|
||
|
}
|
||
|
},
|
||
|
|
||
|
data() {
|
||
|
return {
|
||
|
isBulkEditing: false,
|
||
|
bulkEditText: null
|
||
|
};
|
||
|
},
|
||
|
|
||
|
computed: {
|
||
|
...mapState({
|
||
|
isMobile: state => state.mediaQueries.mobile
|
||
|
}),
|
||
|
bulkIngredientPreview() {
|
||
|
if (this.bulkEditText === null) {
|
||
|
return [];
|
||
|
}
|
||
|
|
||
|
const regex = /^(?:([\d\/.]+(?:\s+[\d\/]+)?)\s+)?(?:([\w-]+)(?:\s+of)?\s+)?([^,]*)(?:,\s*(.*))?$/i;
|
||
|
|
||
|
const magicFunc = function(str) {
|
||
|
if (str === "-") {
|
||
|
return "";
|
||
|
} else {
|
||
|
return str;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
const parsed = [];
|
||
|
const lines = this.bulkEditText.replace("\r", "").split("\n");
|
||
|
|
||
|
for (let line of lines) {
|
||
|
if (line.length === 0) { continue; }
|
||
|
|
||
|
const barIndex = line.lastIndexOf("|");
|
||
|
let afterBar = null;
|
||
|
|
||
|
if (barIndex >= 0) {
|
||
|
afterBar = line.slice(barIndex + 1);
|
||
|
line = line.slice(0, barIndex);
|
||
|
}
|
||
|
|
||
|
const match = line.match(regex);
|
||
|
|
||
|
if (match) {
|
||
|
let item = {quantity: magicFunc(match[1]), units: magicFunc(match[2]), name: magicFunc(match[3]), preparation: magicFunc(match[4])};
|
||
|
if (afterBar) {
|
||
|
item.name = item.name + ", " + item.preparation;
|
||
|
item.preparation = afterBar;
|
||
|
}
|
||
|
parsed.push(item);
|
||
|
} else {
|
||
|
parsed.push(null);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return parsed;
|
||
|
},
|
||
|
|
||
|
visibleIngredients() {
|
||
|
return this.ingredients.filter(i => i._destroy !== true);
|
||
|
}
|
||
|
},
|
||
|
|
||
|
methods: {
|
||
|
addIngredient() {
|
||
|
this.ingredients.push({
|
||
|
quantity: null,
|
||
|
units: null,
|
||
|
name: null,
|
||
|
preparation: null,
|
||
|
ingredient_id: null,
|
||
|
sort_order: Math.max([0].concat(this.ingredients.map(i => i.sort_order))) + 5
|
||
|
});
|
||
|
},
|
||
|
|
||
|
deleteIngredient(ingredient) {
|
||
|
if (ingredient.id) {
|
||
|
ingredient._destroy = true;
|
||
|
} else {
|
||
|
const idx = this.ingredients.findIndex(i => i === ingredient);
|
||
|
this.ingredients.splice(idx, 1);
|
||
|
}
|
||
|
},
|
||
|
|
||
|
bulkEditIngredients() {
|
||
|
this.isBulkEditing = true;
|
||
|
|
||
|
let text = [];
|
||
|
|
||
|
for (let item of this.visibleIngredients) {
|
||
|
text.push(
|
||
|
item.quantity + " " +
|
||
|
(item.units || "-") + " " +
|
||
|
item.name +
|
||
|
(item.preparation ? (", " + item.preparation) : "")
|
||
|
);
|
||
|
}
|
||
|
|
||
|
this.bulkEditText = text.join("\n");
|
||
|
},
|
||
|
|
||
|
cancelBulkEditing() {
|
||
|
this.isBulkEditing = false;
|
||
|
},
|
||
|
|
||
|
saveBulkEditing() {
|
||
|
this.isBulkEditing = false;
|
||
|
}
|
||
|
},
|
||
|
|
||
|
components: {
|
||
|
AppModal,
|
||
|
RecipeEditIngredientItem
|
||
|
}
|
||
|
}
|
||
|
|
||
|
</script>
|
||
|
|
||
|
<style lang="scss" scoped>
|
||
|
</style>
|