Added ingredient prep to recipe_ingredient; update to bulk editing
This commit is contained in:
parent
0cc568344e
commit
422c77b131
@ -53,7 +53,6 @@
|
|||||||
$editors.each(function(idx, elem) {
|
$editors.each(function(idx, elem) {
|
||||||
var $editor = $(elem);
|
var $editor = $(elem);
|
||||||
var $ingredientId = $editor.find("input.ingredient_id");
|
var $ingredientId = $editor.find("input.ingredient_id");
|
||||||
var $customDensity = $editor.find("input.custom_density");
|
|
||||||
var $group = $editor.find("div.typeahead-group");
|
var $group = $editor.find("div.typeahead-group");
|
||||||
|
|
||||||
$editor.find(".ingredient-typeahead").typeahead({},
|
$editor.find(".ingredient-typeahead").typeahead({},
|
||||||
@ -66,7 +65,6 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
if ($ingredientId.val().length) {
|
if ($ingredientId.val().length) {
|
||||||
$customDensity.prop('disabled', true);
|
|
||||||
$group.addClass("has-success");
|
$group.addClass("has-success");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -75,12 +73,10 @@
|
|||||||
function ingredientItemPicked($typeahead, datum) {
|
function ingredientItemPicked($typeahead, datum) {
|
||||||
var $container = $typeahead.closest(".nested-fields");
|
var $container = $typeahead.closest(".nested-fields");
|
||||||
var $ingredientId = $container.find("input.ingredient_id");
|
var $ingredientId = $container.find("input.ingredient_id");
|
||||||
var $customDensity = $container.find("input.custom_density");
|
|
||||||
var $group = $container.find("div.typeahead-group");
|
var $group = $container.find("div.typeahead-group");
|
||||||
|
|
||||||
$ingredientId.val(datum.id);
|
$ingredientId.val(datum.id);
|
||||||
$typeahead.typeahead('val', datum.name);
|
$typeahead.typeahead('val', datum.name);
|
||||||
$customDensity.val(datum.density).prop('disabled', true);
|
|
||||||
$group.addClass("has-success");
|
$group.addClass("has-success");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,22 +99,41 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function addIngredient(quantity, units, name, ingredient_id) {
|
function addIngredient(item) {
|
||||||
$("#ingredient-list").one("cocoon:before-insert", function(e, $container) {
|
$("#ingredient-list").one("cocoon:before-insert", function(e, $container) {
|
||||||
var $ingredientId = $container.find("input.ingredient_id");
|
var $ingredientId = $container.find("input.ingredient_id");
|
||||||
var $name = $container.find("input.custom_name");
|
var $name = $container.find("input.ingredient-typeahead.tt-input");
|
||||||
var $quantity = $container.find("input.quantity");
|
var $quantity = $container.find("input.quantity");
|
||||||
var $units = $container.find("input.units");
|
var $units = $container.find("input.units");
|
||||||
|
var $preparation = $container.find("input.preparation");
|
||||||
|
|
||||||
$ingredientId.typeahead("val", name);
|
$name.typeahead("val", item.name);
|
||||||
$name.val(name);
|
$ingredientId.val(item.ingredient_id);
|
||||||
$units.val(units);
|
$units.val(item.units);
|
||||||
$quantity.val(quantity);
|
$quantity.val(item.quantity);
|
||||||
|
$preparation.val(item.preparation);
|
||||||
});
|
});
|
||||||
|
|
||||||
$("#addIngredientButton").trigger("click");
|
$("#addIngredientButton").trigger("click");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getIngredients() {
|
||||||
|
var data = [];
|
||||||
|
$("#ingredient-list .ingredient-editor").each(function() {
|
||||||
|
var $container = $(this);
|
||||||
|
|
||||||
|
var $ingredientId = $container.find("input.ingredient_id");
|
||||||
|
var $name = $container.find("input.ingredient-typeahead.tt-input");
|
||||||
|
var $quantity = $container.find("input.quantity");
|
||||||
|
var $units = $container.find("input.units");
|
||||||
|
var $preparation = $container.find("input.preparation");
|
||||||
|
|
||||||
|
data.push({ingredient_id: $ingredientId.val(), name: $name.typeahead("val"), quantity: $quantity.val(), units: $units.val(), preparation: $preparation.val()});
|
||||||
|
});
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
function addStep(step) {
|
function addStep(step) {
|
||||||
$("#step-list").one("cocoon:before-insert", function(e, $container) {
|
$("#step-list").one("cocoon:before-insert", function(e, $container) {
|
||||||
var $step = $container.find("textarea.step");
|
var $step = $container.find("textarea.step");
|
||||||
@ -226,14 +241,7 @@
|
|||||||
var $ingredientBulkList = $("#ingredient_bulk_parsed_list");
|
var $ingredientBulkList = $("#ingredient_bulk_parsed_list");
|
||||||
autosize($ingredientBulkInput);
|
autosize($ingredientBulkInput);
|
||||||
|
|
||||||
$bulkIngredientsModal
|
var parseBulkIngredients = function() {
|
||||||
.on('show.bs.modal', function (event) {
|
|
||||||
$ingredientBulkInput.val('');
|
|
||||||
$ingredientBulkList.empty();
|
|
||||||
autosize.update($ingredientBulkInput);
|
|
||||||
});
|
|
||||||
|
|
||||||
$ingredientBulkInput.on('keyup', function() {
|
|
||||||
var data = $ingredientBulkInput.val();
|
var data = $ingredientBulkInput.val();
|
||||||
$ingredientBulkList.empty();
|
$ingredientBulkList.empty();
|
||||||
|
|
||||||
@ -242,7 +250,7 @@
|
|||||||
|
|
||||||
var lines = data.replace("\r", "").split("\n");
|
var lines = data.replace("\r", "").split("\n");
|
||||||
|
|
||||||
var regex = /^(?:([\d\/.]+(?:\s+[\d\/]+)?)\s+)?(?:([\w-]+)(?:\s+of)?\s+)?(\w[\w ,\-\(\)\/'"]*)$/i;
|
var regex = /^(?:([\d\/.]+(?:\s+[\d\/]+)?)\s+)?(?:([\w-]+)(?:\s+of)?\s+)?([^,]*)(?:,\s*(.*))?$/i;
|
||||||
|
|
||||||
var magicFunc = function(str) {
|
var magicFunc = function(str) {
|
||||||
if (str == "-") {
|
if (str == "-") {
|
||||||
@ -256,10 +264,23 @@
|
|||||||
var line = lines[x].trim();
|
var line = lines[x].trim();
|
||||||
if (line.length == 0) { continue; }
|
if (line.length == 0) { continue; }
|
||||||
|
|
||||||
|
var barIndex = line.lastIndexOf("|");
|
||||||
|
var afterBar = null;
|
||||||
|
|
||||||
|
if (barIndex >= 0) {
|
||||||
|
afterBar = line.slice(barIndex + 1);
|
||||||
|
line = line.slice(0, barIndex);
|
||||||
|
}
|
||||||
|
|
||||||
var match = line.match(regex);
|
var match = line.match(regex);
|
||||||
|
|
||||||
if (match) {
|
if (match) {
|
||||||
parsed.push({quantity: magicFunc(match[1]), units: magicFunc(match[2]), name: magicFunc(match[3])});
|
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 {
|
} else {
|
||||||
parsed.push(null);
|
parsed.push(null);
|
||||||
}
|
}
|
||||||
@ -275,14 +296,44 @@
|
|||||||
.append($("<td />").addClass("quantity").text(item.quantity))
|
.append($("<td />").addClass("quantity").text(item.quantity))
|
||||||
.append($("<td />").addClass("units").text(item.units))
|
.append($("<td />").addClass("units").text(item.units))
|
||||||
.append($("<td />").addClass("name").text(item.name))
|
.append($("<td />").addClass("name").text(item.name))
|
||||||
|
.append($("<td />").addClass("preparation").text(item.preparation))
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
$ingredientBulkList.append(
|
$ingredientBulkList.append(
|
||||||
$("<tr />")
|
$("<tr />")
|
||||||
.append($("<td />").attr("colspan", "3").text("<Cannot Parse>"))
|
.append($("<td />").attr("colspan", "4").text("<Cannot Parse>"))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$bulkIngredientsModal
|
||||||
|
.on('show.bs.modal', function (event) {
|
||||||
|
var data = getIngredients();
|
||||||
|
var x;
|
||||||
|
var text = [];
|
||||||
|
|
||||||
|
for (x = 0; x < data.length; x++) {
|
||||||
|
var item = data[x];
|
||||||
|
|
||||||
|
text.push(
|
||||||
|
item.quantity + " " +
|
||||||
|
(item.units || "-") + " " +
|
||||||
|
item.name +
|
||||||
|
(item.preparation ? (", " + item.preparation) : "")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$ingredientBulkInput.val(text.join("\n"));
|
||||||
|
|
||||||
|
setTimeout(function() {
|
||||||
|
parseBulkIngredients();
|
||||||
|
autosize.update($ingredientBulkInput);
|
||||||
|
}, 250);
|
||||||
|
});
|
||||||
|
|
||||||
|
$ingredientBulkInput.on('keyup', function() {
|
||||||
|
parseBulkIngredients();
|
||||||
});
|
});
|
||||||
|
|
||||||
$("#bulkIngredientAddSubmit").on("click", function() {
|
$("#bulkIngredientAddSubmit").on("click", function() {
|
||||||
@ -293,7 +344,7 @@
|
|||||||
for (x = 0; x < parsed.length; x++) {
|
for (x = 0; x < parsed.length; x++) {
|
||||||
var item = parsed[x];
|
var item = parsed[x];
|
||||||
if (item) {
|
if (item) {
|
||||||
addIngredient(item.quantity, item.units, item.name, item.ingredient_id)
|
addIngredient(item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
div.ingredient-editor {
|
div.ingredient-editor {
|
||||||
@include editor;
|
@include editor;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
div.step-editor {
|
div.step-editor {
|
||||||
@ -50,6 +51,19 @@ div#ingredient-list, div#step-list {
|
|||||||
padding-bottom: 15px;
|
padding-bottom: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div#ingredient-list {
|
||||||
|
|
||||||
|
@media (min-width: $screen-md-min) {
|
||||||
|
.ingredient-editor .control-label {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ingredient-editor:first-child .control-label {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
div.recipe-view {
|
div.recipe-view {
|
||||||
|
|
||||||
.source {
|
.source {
|
||||||
|
@ -24,6 +24,7 @@ class RecipesController < ApplicationController
|
|||||||
# GET /recipes/new
|
# GET /recipes/new
|
||||||
def new
|
def new
|
||||||
@recipe = Recipe.new
|
@recipe = Recipe.new
|
||||||
|
@recipe.recipe_ingredients << RecipeIngredient.new
|
||||||
end
|
end
|
||||||
|
|
||||||
# GET /recipes/1/edit
|
# GET /recipes/1/edit
|
||||||
@ -75,6 +76,6 @@ class RecipesController < ApplicationController
|
|||||||
|
|
||||||
# Never trust parameters from the scary internet, only allow the white list through.
|
# Never trust parameters from the scary internet, only allow the white list through.
|
||||||
def recipe_params
|
def recipe_params
|
||||||
params.require(:recipe).permit(:name, :description, :source, :yields, :total_time, :active_time, recipe_ingredients_attributes: [:custom_name, :custom_density, :ingredient_id, :quantity, :units, :sort_order, :id, :_destroy], recipe_steps_attributes: [:step, :sort_order, :id, :_destroy])
|
params.require(:recipe).permit(:name, :description, :source, :yields, :total_time, :active_time, recipe_ingredients_attributes: [:name, :ingredient_id, :quantity, :units, :preparation, :sort_order, :id, :_destroy], recipe_steps_attributes: [:step, :sort_order, :id, :_destroy])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -6,7 +6,7 @@ class RecipeIngredient < ActiveRecord::Base
|
|||||||
validates :sort_order, presence: true
|
validates :sort_order, presence: true
|
||||||
validates :custom_density, density: true, allow_blank: true
|
validates :custom_density, density: true, allow_blank: true
|
||||||
|
|
||||||
def custom_name
|
def name
|
||||||
if self.ingredient_id.present?
|
if self.ingredient_id.present?
|
||||||
self.ingredient.name
|
self.ingredient.name
|
||||||
else
|
else
|
||||||
@ -14,23 +14,15 @@ class RecipeIngredient < ActiveRecord::Base
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def custom_density
|
|
||||||
if self.ingredient_id.present?
|
|
||||||
self.ingredient.density
|
|
||||||
else
|
|
||||||
super
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def display_name
|
def display_name
|
||||||
if quantity.present? && units.present?
|
if quantity.present? && units.present?
|
||||||
"#{quantity} #{units} of #{custom_name}"
|
"#{quantity} #{units} #{name}"
|
||||||
elsif quantity.present?
|
elsif quantity.present?
|
||||||
"#{quantity} #{custom_name}"
|
"#{quantity} #{name}"
|
||||||
elsif units.present?
|
elsif units.present?
|
||||||
"#{units} #{custom_name}"
|
"#{units} #{name}"
|
||||||
else
|
else
|
||||||
custom_name
|
name
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@
|
|||||||
|
|
||||||
|
|
||||||
<h3>Ingredients</h3>
|
<h3>Ingredients</h3>
|
||||||
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#bulk_ingredients_modal">Bulk Add</button>
|
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#bulk_ingredients_modal">Bulk Edit</button>
|
||||||
<div id="ingredient-list">
|
<div id="ingredient-list">
|
||||||
<%= f.fields_for :recipe_ingredients do |ri_form| %>
|
<%= f.fields_for :recipe_ingredients do |ri_form| %>
|
||||||
<%= render partial: 'recipes/editor/ingredient', locals: { f: ri_form } %>
|
<%= render partial: 'recipes/editor/ingredient', locals: { f: ri_form } %>
|
||||||
@ -58,7 +58,7 @@
|
|||||||
|
|
||||||
|
|
||||||
<h3>Steps</h3>
|
<h3>Steps</h3>
|
||||||
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#bulk_steps_modal">Bulk Add</button>
|
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#bulk_steps_modal">Bulk Edit</button>
|
||||||
<div id="step-list">
|
<div id="step-list">
|
||||||
<%= f.fields_for :recipe_steps do |rs_form| %>
|
<%= f.fields_for :recipe_steps do |rs_form| %>
|
||||||
<%= render partial: 'recipes/editor/step', locals: { f: rs_form } %>
|
<%= render partial: 'recipes/editor/step', locals: { f: rs_form } %>
|
||||||
|
@ -11,19 +11,20 @@
|
|||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-xs-6">
|
<div class="col-xs-6">
|
||||||
<div class="form-group">
|
<div class="form-group form-group-lg">
|
||||||
<label for="ingredient_bulk_input" class="control-label">Raw Input</label>
|
<label for="ingredient_bulk_input" class="control-label">Raw Input</label>
|
||||||
<textarea id="ingredient_bulk_input" class="form-control"></textarea>
|
<textarea id="ingredient_bulk_input" class="form-control"></textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-xs-6">
|
<div class="col-xs-6">
|
||||||
<table class="table">
|
<table class="table table-condensed table-bordered">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Quantity</th>
|
<th>#</th>
|
||||||
<th>Unit</th>
|
<th>Unit</th>
|
||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
|
<th>Prep</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody id="ingredient_bulk_parsed_list">
|
<tbody id="ingredient_bulk_parsed_list">
|
||||||
|
@ -6,20 +6,6 @@
|
|||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|
||||||
<div class="col-xs-12 col-md-7">
|
|
||||||
<div class="form-group form-group-sm typeahead-group">
|
|
||||||
<%= f.label :custom_name, "Name", class: "control-label" %>
|
|
||||||
<div class="input-group input-group-sm">
|
|
||||||
<%= f.text_field :custom_name, class: 'form-control ingredient-typeahead custom_name' %>
|
|
||||||
<span class="input-group-btn">
|
|
||||||
<button tabindex="-1" class="btn btn-info ingredient_convert_btn" type="button" data-toggle="modal" data-target="#convert_modal">
|
|
||||||
<span class="glyphicon glyphicon-transfer"></span>
|
|
||||||
</button>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-xs-6 col-sm-6 col-md-2">
|
<div class="col-xs-6 col-sm-6 col-md-2">
|
||||||
<div class="form-group form-group-sm">
|
<div class="form-group form-group-sm">
|
||||||
<%= f.label :quantity, class: "control-label" %>
|
<%= f.label :quantity, class: "control-label" %>
|
||||||
@ -30,10 +16,32 @@
|
|||||||
<div class="col-xs-6 col-sm-6 col-md-3">
|
<div class="col-xs-6 col-sm-6 col-md-3">
|
||||||
<div class="form-group form-group-sm">
|
<div class="form-group form-group-sm">
|
||||||
<%= f.label :units, class: "control-label" %>
|
<%= f.label :units, class: "control-label" %>
|
||||||
|
<div class="input-group input-group-sm">
|
||||||
<%= f.text_field :units, class: 'form-control units' %>
|
<%= f.text_field :units, class: 'form-control units' %>
|
||||||
|
<span class="input-group-btn">
|
||||||
|
<button tabindex="-1" class="btn btn-info ingredient_convert_btn" type="button" data-toggle="modal" data-target="#convert_modal">
|
||||||
|
<span class="glyphicon glyphicon-transfer"></span>
|
||||||
|
</button>
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="col-xs-6 col-md-3">
|
||||||
|
<div class="form-group form-group-sm typeahead-group">
|
||||||
|
<%= f.label :name, class: "control-label" %>
|
||||||
|
<%= f.text_field :name, class: 'form-control ingredient-typeahead custom' %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-xs-6 col-md-4">
|
||||||
|
<div class="form-group form-group-sm">
|
||||||
|
<%= f.label :preparation, class: "control-label" %>
|
||||||
|
<%= f.text_field :preparation, class: 'form-control preparation' %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-xs-2 col-sm-1">
|
<div class="col-xs-2 col-sm-1">
|
||||||
|
9
db/migrate/20160130231838_change_ingredients.rb
Normal file
9
db/migrate/20160130231838_change_ingredients.rb
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
class ChangeIngredients < ActiveRecord::Migration
|
||||||
|
def change
|
||||||
|
change_table :recipe_ingredients do |t|
|
||||||
|
t.remove :custom_density
|
||||||
|
t.rename :custom_name, :name
|
||||||
|
t.text :preparation
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -11,7 +11,7 @@
|
|||||||
#
|
#
|
||||||
# It's strongly recommended that you check this file into your version control system.
|
# It's strongly recommended that you check this file into your version control system.
|
||||||
|
|
||||||
ActiveRecord::Schema.define(version: 20160124231837) do
|
ActiveRecord::Schema.define(version: 20160130231838) do
|
||||||
|
|
||||||
create_table "ingredients", force: :cascade do |t|
|
create_table "ingredients", force: :cascade do |t|
|
||||||
t.string "name"
|
t.string "name"
|
||||||
@ -33,13 +33,13 @@ ActiveRecord::Schema.define(version: 20160124231837) do
|
|||||||
create_table "recipe_ingredients", force: :cascade do |t|
|
create_table "recipe_ingredients", force: :cascade do |t|
|
||||||
t.integer "ingredient_id"
|
t.integer "ingredient_id"
|
||||||
t.integer "recipe_id"
|
t.integer "recipe_id"
|
||||||
t.string "custom_name"
|
t.string "name"
|
||||||
t.string "custom_density"
|
|
||||||
t.integer "sort_order"
|
t.integer "sort_order"
|
||||||
t.string "quantity"
|
t.string "quantity"
|
||||||
t.string "units"
|
t.string "units"
|
||||||
t.datetime "created_at", null: false
|
t.datetime "created_at", null: false
|
||||||
t.datetime "updated_at", null: false
|
t.datetime "updated_at", null: false
|
||||||
|
t.text "preparation"
|
||||||
end
|
end
|
||||||
|
|
||||||
add_index "recipe_ingredients", ["recipe_id"], name: "index_recipe_ingredients_on_recipe_id"
|
add_index "recipe_ingredients", ["recipe_id"], name: "index_recipe_ingredients_on_recipe_id"
|
||||||
|
Loading…
Reference in New Issue
Block a user