parsley/app/javascript/components/RecipeEditIngredientEditor.vue
2018-04-01 21:43:23 -05:00

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>