Add support for separate cook/prep time and better validation
This commit is contained in:
parent
974cf8cbb1
commit
601fe5e3fb
@ -73,6 +73,8 @@ sub _build_recipe {
|
||||
});
|
||||
}
|
||||
|
||||
my $time = ($recipe -> {"preptime"} + $recipe -> {"cooktime"}) * 60;
|
||||
|
||||
return $self -> {"template"} -> load_template("list/recipe.tem",
|
||||
{ "%(id)s" => $recipe -> {"id"},
|
||||
"%(url-view)s" => $self -> build_url(block => "view",
|
||||
@ -80,7 +82,7 @@ sub _build_recipe {
|
||||
"%(name)s" => $recipe -> {"name"},
|
||||
"%(type)s" => $recipe -> {"type"},
|
||||
"%(status)s" => $recipe -> {"status"},
|
||||
"%(time)s" => $self -> {"template"} -> humanise_seconds($recipe -> {"timemins"} * 60, 1),
|
||||
"%(time)s" => $self -> {"template"} -> humanise_seconds($time, 1),
|
||||
"%(temp)s" => $temp,
|
||||
"%(tags)s" => join("", map { $self -> _build_tag($_) } @{$recipe -> {"tags"}}),
|
||||
"%(controls)s" => $controls,
|
||||
|
@ -85,17 +85,23 @@ sub _generate_new {
|
||||
my $ingredients = $self -> _build_ingredients($args);
|
||||
|
||||
# Build up the type and status data
|
||||
my $typeopts = $self -> {"template"} -> build_optionlist($self -> {"system"} -> {"entities"} -> {"types"} -> as_options(),
|
||||
my $typeopts = $self -> {"template"} -> build_optionlist($self -> {"system"} -> {"entities"} -> {"types"} -> as_options(1),
|
||||
$args -> {"type"});
|
||||
|
||||
my $statusopts = $self -> {"template"} -> build_optionlist($self -> {"system"} -> {"entities"} -> {"states"} -> as_options(0, visible => {value => 1}),
|
||||
my $statusopts = $self -> {"template"} -> build_optionlist($self -> {"system"} -> {"entities"} -> {"states"} -> as_options(1, visible => {value => 1}),
|
||||
$args -> {"status"});
|
||||
|
||||
# Convert the time fields
|
||||
my ($timemins, $timesecs) = ("", 0);
|
||||
if($args -> {"timemins"}) {
|
||||
$timesecs = $args -> {"timemins"} * 60;
|
||||
$timemins = $self -> _build_timereq($timesecs);
|
||||
my ($preptime, $prepsecs) = ("", 0);
|
||||
if($args -> {"preptime"}) {
|
||||
$prepsecs = $args -> {"preptime"} * 60;
|
||||
$preptime = $self -> _build_timereq($prepsecs);
|
||||
}
|
||||
|
||||
my ($cooktime, $cooksecs) = ("", 0);
|
||||
if($args -> {"cooktime"}) {
|
||||
$cooksecs = $args -> {"cooktime"} * 60;
|
||||
$cooktime = $self -> _build_timereq($cooksecs);
|
||||
}
|
||||
|
||||
# Convert tags - can't use build_optionlist because all of them need to be selected.
|
||||
@ -115,9 +121,11 @@ sub _generate_new {
|
||||
"%(name)s" => $args -> {"name"} // "",
|
||||
"%(source)s" => $args -> {"source"} // "",
|
||||
"%(yield)s" => $args -> {"yield"} // "",
|
||||
"%(timereq)s" => $args -> {"timereq"} // "",
|
||||
"%(timemins)s" => $timemins,
|
||||
"%(timesecs)s" => $timesecs,
|
||||
"%(prepinfo)s" => $args -> {"prepinfo"} // "",
|
||||
"%(preptime)s" => $preptime,
|
||||
"%(prepsecs)s" => $prepsecs,
|
||||
"%(cooktime)s" => $cooktime,
|
||||
"%(cooksecs)s" => $cooksecs,
|
||||
"%(temp)s" => $args -> {"temp"} // "",
|
||||
"%(temptypes)s" => $self -> {"template"} -> build_optionlist($temptypes, $args -> {"temptype"}),
|
||||
"%(types)s" => $typeopts,
|
||||
|
@ -80,6 +80,44 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/recipes": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"recipe"
|
||||
],
|
||||
"summary": "Fetch a list of recipes defined in the system",
|
||||
"description": "Retrieve the list of recipes defined in the system.\n",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "name",
|
||||
"description": "A name to search for recipes with",
|
||||
"in": "query",
|
||||
"type": "string",
|
||||
"required": false
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A list of recipes",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/Recipes"
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"description": "Permission error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/Error"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "Unexpected error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/Error"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/tags": {
|
||||
"get": {
|
||||
"tags": [
|
||||
@ -139,6 +177,15 @@
|
||||
"$ref": "#/definitions/Ingredient"
|
||||
}
|
||||
},
|
||||
"Recipe": {
|
||||
"type": "object"
|
||||
},
|
||||
"Recipes": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/Recipe"
|
||||
}
|
||||
},
|
||||
"Tag": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
@ -43,14 +43,14 @@ paths:
|
||||
summary: Fetch the list of ingredients
|
||||
description: |
|
||||
Retrieve the list of ingredients defined in the system.
|
||||
parameters:
|
||||
parameters:
|
||||
- name: term
|
||||
description: A partial name to search for ingredients with
|
||||
in: query
|
||||
type: string
|
||||
required: false
|
||||
responses:
|
||||
'200':
|
||||
'200':
|
||||
description: A list of ingredients
|
||||
schema:
|
||||
$ref: '#/definitions/Ingredients'
|
||||
@ -62,6 +62,32 @@ paths:
|
||||
description: Unexpected error
|
||||
schema:
|
||||
$ref: '#/definitions/Error'
|
||||
/recipes:
|
||||
get:
|
||||
tags:
|
||||
- recipe
|
||||
summary: Fetch a list of recipes defined in the system
|
||||
description: |
|
||||
Retrieve the list of recipes defined in the system.
|
||||
parameters:
|
||||
- name: name
|
||||
description: A name to search for recipes with
|
||||
in: query
|
||||
type: string
|
||||
required: false
|
||||
responses:
|
||||
'200':
|
||||
description: A list of recipes
|
||||
schema:
|
||||
$ref: '#/definitions/Recipes'
|
||||
'403':
|
||||
description: Permission error
|
||||
schema:
|
||||
$ref: '#/definitions/Error'
|
||||
default:
|
||||
description: Unexpected error
|
||||
schema:
|
||||
$ref: '#/definitions/Error'
|
||||
/tags:
|
||||
get:
|
||||
tags:
|
||||
@ -69,14 +95,14 @@ paths:
|
||||
summary: Fetch a list of tags defined in the system
|
||||
description: |
|
||||
Retrieve the list of tags defined in the system.
|
||||
parameters:
|
||||
parameters:
|
||||
- name: term
|
||||
description: A partial name to search for tags with
|
||||
in: query
|
||||
type: string
|
||||
required: false
|
||||
responses:
|
||||
'200':
|
||||
'200':
|
||||
description: A list of tags
|
||||
schema:
|
||||
$ref: '#/definitions/Tags'
|
||||
@ -102,10 +128,16 @@ definitions:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/definitions/Ingredient'
|
||||
Recipe:
|
||||
type: object
|
||||
Recipes:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/definitions/Recipe'
|
||||
Tag:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
id:
|
||||
type: number
|
||||
description: The ID of the tag in the system
|
||||
text:
|
||||
|
@ -18,9 +18,13 @@ RECIPE_PREPINFO = Prep info
|
||||
RECIPE_PREPINFO_DOC = How much time each step of the recipe take?
|
||||
RECIPE_PREPINFO_PH = 10 min prep + 20 min cook
|
||||
|
||||
RECIPE_TIMEREQ = Time required
|
||||
RECIPE_TIMEREQ_DOC = How long does this recipe take in total?
|
||||
RECIPE_TIMEREQ_PH = 1 hour 10 minutes
|
||||
RECIPE_PREPTIME = Preparation time required
|
||||
RECIPE_PREPTIME_DOC = How long does this recipe take to prepare?
|
||||
RECIPE_PREPTIME_PH = 30 minutes
|
||||
|
||||
RECIPE_COOKTIME = Cooking time required
|
||||
RECIPE_COOKTIME_DOC = How long does this recipe take to cook?
|
||||
RECIPE_COOKTIME_PH = 30 minutes
|
||||
|
||||
RECIPE_OVENTEMP = Oven preheat
|
||||
RECIPE_OVENTEMP_DOC = Initial oven temperature (show changes in method)
|
||||
|
@ -71,6 +71,16 @@ sub new {
|
||||
@_)
|
||||
or return undef;
|
||||
|
||||
# Formats of accepted types
|
||||
$self -> {"formats"} = {
|
||||
"recipename" => '^[-\w,. ]+$',
|
||||
"tags" => '^[-\w ]+$',
|
||||
"quantity" => '^[\d\w./]+$',
|
||||
"sepname" => '^[-\w,. ]{1,255}$',
|
||||
"ingredient" => '^[-\w,. ]{1,255}$',
|
||||
"notes" => '^[-()\w,. ]{1,255}$',
|
||||
};
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
|
@ -273,6 +273,8 @@ sub find_ids {
|
||||
# is no maximum and all possible matched are returned.
|
||||
# - `as`: can be set to `name`, `value`, or `text`. This determines the key
|
||||
# name used for the `name` field of the entities in the results.
|
||||
# - `id`: can be set to `name` or `id`. This determines whether the entity name
|
||||
# or id is used as the id in the data.
|
||||
#
|
||||
# @param args A hash or reference to a hash of search settings.
|
||||
# @return A reference to an array of hashes containing the results, ordered
|
||||
@ -297,7 +299,13 @@ sub find {
|
||||
default { $as = "name"; }
|
||||
}
|
||||
|
||||
my $search = $self -> {"dbh"} -> prepare("SELECT `id`, `refcount`, `name` AS `$as`
|
||||
my $id;
|
||||
given($args -> {"id"}) {
|
||||
when("name") { $id = "name"; }
|
||||
default { $id = "id"; }
|
||||
}
|
||||
|
||||
my $search = $self -> {"dbh"} -> prepare("SELECT `$id` AS `id`, `refcount`, `name` AS `$as`
|
||||
FROM `".$self -> {"settings"} -> {"database"} -> {$self -> {"entity_table"}}."`
|
||||
WHERE `name` LIKE ?
|
||||
ORDER BY `name`,`id`
|
||||
|
@ -17,40 +17,7 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
## @class Recipe
|
||||
# +-------------+--------------------------------+------+-----+----------------+
|
||||
# | Field | Type | Null | Key | Extra |
|
||||
# +-------------+--------------------------------+------+-----+----------------+
|
||||
# | id | int(10) unsigned | NO | PRI | auto_increment |
|
||||
# | prev_id | int(11) | YES | | |
|
||||
# | metadata_id | int(11) | NO | | |
|
||||
# | name | varchar(80) | NO | UNI | |
|
||||
# | method | text | NO | | |
|
||||
# | notes | text | YES | | |
|
||||
# | source | varchar(255) | YES | | |
|
||||
# | yield | varchar(80) | NO | | |
|
||||
# | timereq | varchar(255) | NO | | |
|
||||
# | timemins | int(10) unsigned | NO | MUL | |
|
||||
# | temptype | enum('C','F','Gas mark','N/A') | NO | | |
|
||||
# | temp | smallint(5) unsigned | YES | | |
|
||||
# | type_id | int(10) unsigned | NO | MUL | |
|
||||
# | status_id | int(10) unsigned | NO | MUL | |
|
||||
# | creator_id | int(10) unsigned | NO | | |
|
||||
# | created | int(10) unsigned | NO | MUL | |
|
||||
# | viewed | int(10) unsigned | NO | | |
|
||||
# +-------------+--------------------------------+------+-----+----------------+
|
||||
|
||||
# +-----------+------------------+------+-----+----------------+
|
||||
# | Field | Type | Null | Key | Extra |
|
||||
# +-----------+------------------+------+-----+----------------+
|
||||
# | id | int(10) unsigned | NO | PRI | auto_increment |
|
||||
# | recipe_id | int(10) unsigned | NO | MUL | |
|
||||
# | unit_id | int(10) unsigned | YES | | |
|
||||
# | prep_id | int(10) unsigned | YES | | |
|
||||
# | ingred_id | int(10) unsigned | YES | | |
|
||||
# | quantity | varchar(8) | YES | | |
|
||||
# | notes | varchar(255) | YES | | |
|
||||
# | separator | varchar(255) | YES | | |
|
||||
# +-----------+------------------+------+-----+----------------+
|
||||
# FIXME: corrected table schema here
|
||||
#
|
||||
#
|
||||
|
||||
@ -107,16 +74,14 @@ sub clear {
|
||||
#
|
||||
# - `id`: (optional, avoid) Set the ID to create the recipe with.
|
||||
# This should generally not be specified unless doing edits.
|
||||
# - `previd`: (optional) ID of the recipe this is an edit of. If specified,
|
||||
# the old recipe has its state set to 'edited', and the
|
||||
# metadata context of the new recipe is created as a child of
|
||||
# the old recipe to ensure editing works as expected. Generally
|
||||
# - `origid`: (optional) ID of the recipe this is an edit of. Generally
|
||||
# this will not be specified directly; if editing a recipe,
|
||||
# call edit() to have renumbering handled for you.
|
||||
# - `name`: The name of the recipe
|
||||
# - `source`: (optional) Where did the recipe come from originally?
|
||||
# - `timereq`: (optional) A string describing the time required for the recipe
|
||||
# - `timemins`: How long does the recipe take in minutes, in total?
|
||||
# - `prepinfo`: (optional) A string describing the time required for the recipe
|
||||
# - `preptime`: How long does the recipe take to prepare in minutes?
|
||||
# - `cooktime`: How long does the recipe take to cook in minutes?
|
||||
# - `yield`: A string describing how much stuff the recipe creates
|
||||
# - `temp`: (optional) Oven preheat temperature
|
||||
# - `temptype`: The type of units used: 'C', 'F', 'Gas mark', or 'N/A'
|
||||
@ -170,19 +135,20 @@ sub create {
|
||||
unless($args -> {"created"});
|
||||
|
||||
# We need a metadata context for the recipe
|
||||
my $metadataid = $self -> _create_recipe_metadata($args -> {"previd"});
|
||||
my $metadataid = $self -> _create_recipe_metadata($args -> {"origid"});
|
||||
|
||||
# Do the insert, and fetch the ID of the new row
|
||||
my $newh = $self -> {"dbh"} -> prepare("INSERT INTO `".$self -> {"settings"} -> {"database"} -> {"recipes"}."`
|
||||
(`id`, `metadata_id`, `prev_id`, `name`, `source`, `timereq`, `timemins`, `yield`, `temp`, `temptype`, `method`, `notes`, `type_id`, `status_id`, `creator_id`, `created`, `updater_id`, `updated`)
|
||||
VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ,?)");
|
||||
(`id`, `metadata_id`, `original_id`, `name`, `source`, `prepinfo`, `preptime`, `cooktime`, `yield`, `temp`, `temptype`, `method`, `notes`, `type_id`, `status_id`, `creator_id`, `created`, `updater_id`, `updated`)
|
||||
VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ,?)");
|
||||
my $result = $newh -> execute($args -> {"id"},
|
||||
$metadataid,
|
||||
$args -> {"previd"},
|
||||
$args -> {"origid"},
|
||||
$args -> {"name"},
|
||||
$args -> {"source"},
|
||||
$args -> {"timereq"},
|
||||
$args -> {"timemins"},
|
||||
$args -> {"prepinfo"},
|
||||
$args -> {"preptime"},
|
||||
$args -> {"cooktime"},
|
||||
$args -> {"yield"},
|
||||
$args -> {"temp"},
|
||||
$args -> {"temptype"},
|
||||
@ -200,7 +166,8 @@ sub create {
|
||||
return $self -> self_error("No rows added when inserting recipe.")
|
||||
if($result eq "0E0");
|
||||
|
||||
my $newid = $self -> {"dbh"} -> {"mysql_insertid"};
|
||||
# If we explicitly set an ID above, use it here rather than looking it up
|
||||
my $newid = $args -> {"id"} // $self -> {"dbh"} -> {"mysql_insertid"};
|
||||
|
||||
return $self -> self_error("Unable to obtain id for new recipe")
|
||||
if(!$newid);
|
||||
@ -228,7 +195,7 @@ sub create {
|
||||
# updated recipe overwrites the data at the old ID).
|
||||
#
|
||||
# @param args This should be a reference to a hash containing the same
|
||||
# elements as the args hash for create(), except previd is
|
||||
# elements as the args hash for create(), except origid is
|
||||
# required here. This should also contain the field
|
||||
# `updaterid` containing the ID of the user doing the edit.
|
||||
# @return The recipe Id on success, undef on error.
|
||||
@ -238,15 +205,16 @@ sub edit {
|
||||
|
||||
$self -> clear_error();
|
||||
|
||||
return $self -> self_error("edit called without previous recipe ID")
|
||||
unless($args -> {"previd"});
|
||||
return $self -> self_error("edit called without master recipe ID")
|
||||
unless($args -> {"origid"});
|
||||
|
||||
# Move the old recipe to the end of the table, but keep a record
|
||||
# of its current ID
|
||||
$args -> {"id"} = $args -> {"previd"};
|
||||
my $renumbered = $self -> _renumber_recipe($args -> {"id"});
|
||||
# We want the new recipe to get the same ID as the old one, so record it
|
||||
$args -> {"id"} = $args -> {"origid"};
|
||||
|
||||
# Create a new one at the old ID
|
||||
# Now move the old recipe out of the way so the new one can use its ID
|
||||
my $renumbered = $self -> _renumber_recipe($args -> {"id"});
|
||||
|
||||
# Create the new recipe at the old ID
|
||||
$self -> create($args)
|
||||
or return undef;
|
||||
|
||||
@ -256,6 +224,8 @@ sub edit {
|
||||
$args -> {"updaterid"})
|
||||
or return undef;
|
||||
|
||||
|
||||
|
||||
return $args -> {"id"};
|
||||
}
|
||||
|
||||
@ -296,6 +266,31 @@ sub set_status {
|
||||
}
|
||||
|
||||
|
||||
## @method $ set_viewed($recipeid, $viewerid)
|
||||
# Update the 'viewed' timestamp for a recipe to show that a user has
|
||||
# viewed it.
|
||||
#
|
||||
# @param recipeid The ID of the recipe that has been viewed.
|
||||
# @param viewerid The ID of the user doing the viewing.
|
||||
# @return true on success, undef on error.
|
||||
sub set_viewed {
|
||||
my $self = shift;
|
||||
my $recipeid = shift;
|
||||
my $viewerid = shift;
|
||||
|
||||
$self -> clear_error();
|
||||
|
||||
my $updateh = $self -> {"dbh"} -> prepare("UPDATE `".$self -> {"settings"} -> {"database"} -> {"recipes"}."`
|
||||
SET `viewed` = UNIX_TIMESTAMP()
|
||||
WHERE `id` = ?");
|
||||
my $result = $updateh -> execute($recipeid);
|
||||
return $self -> self_error("Update of recipe failed: ".$self -> {"dbh"} -> errstr) if(!$result);
|
||||
return $self -> self_error("Recipe update failed: no rows updated") if($result eq "0E0");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# Recipe retrieval
|
||||
|
||||
@ -474,6 +469,8 @@ sub load_recipe_relations {
|
||||
# - `tagmatch`: control how tag searching works. As with `ingredmatch`, this
|
||||
# may be "all" or "any", with corresponding behaviour.
|
||||
# - `limit`: how many recipies may be returned by the find()
|
||||
# - `original`: if set to true (the default) only search the most recent versions
|
||||
# of recipes. If false, include edits.
|
||||
# - `offset`: offset from the start of the query results.
|
||||
# - `order`: optional ordering of results. Allowed values are 'added', 'updated',
|
||||
# 'viewed', or 'name' (the default).
|
||||
@ -561,7 +558,16 @@ sub find {
|
||||
}
|
||||
|
||||
# Squish all the where conditions into a string
|
||||
my $wherecond = join(($args -> {"searchmode"} eq "any" ? "\nOR " : "\nAND "), @where) || "1";
|
||||
my $wherecond = join(($args -> {"searchmode"} eq "any" ? "\nOR " : "\nAND "), @where);
|
||||
|
||||
# Unless `original` is false, we can only match the most recent edits
|
||||
unless(defined($args -> {"original"}) && !$args -> {"original"}) {
|
||||
$wherecond .= "\nAND" if($wherecond);
|
||||
$wherecond .= "`r`.`original_id` IS NULL";
|
||||
}
|
||||
|
||||
# Allow for no search criteria
|
||||
$wherecond = "1" unless($wherecond);
|
||||
|
||||
# Construct the limit term when limit (and optionally offset) are
|
||||
# specified by the caller
|
||||
@ -666,7 +672,7 @@ sub _add_ingredients {
|
||||
}
|
||||
|
||||
# Likewise for preparation methods
|
||||
if($ingred -> {"prep"} && lc($ingred -> {"units"}) ne "none") {
|
||||
if($ingred -> {"prep"} && lc($ingred -> {"prep"}) ne "none") {
|
||||
$prepid = $self -> {"entities"} -> {"prep"} -> get_id($ingred -> {"prep"})
|
||||
or return $self -> self_error("Unable to get preparation method ID for '".$ingred -> {"prep"}."': ".$self -> {"entities"} -> {"prep"} -> errstr());
|
||||
|
||||
@ -814,8 +820,8 @@ sub _renumber_recipe {
|
||||
|
||||
# Duplicate the source recipe at the end of the table
|
||||
my $moveh = $self -> {"dbh"} -> prepare("INSERT INTO `".$self -> {"settings"} -> {"database"} -> {"recipes"}."`
|
||||
(`metadata_id`, `prev_id`, `name`, `method`, `notes`, `source`, `yield`, `timereq`, `timemins`, `temptype`, `temp`, `type_id`, `status_id`, `creator_id`, `created`, `viewed`)
|
||||
SELECT `metadata_id`, `prev_id`, `name`, `method`, `notes`, `source`, `yield`, `timereq`, `timemins`, `temptype`, `temp`, `type_id`, `status_id`, `creator_id`, `created`, `viewed`
|
||||
(`metadata_id`, `name`, `method`, `notes`, `source`, `yield`, `prepinfo`, `preptime`, `cooktime`, `temptype`, `temp`, `type_id`, `status_id`, `creator_id`, `created`, `viewed`)
|
||||
SELECT `metadata_id`, `name`, `method`, `notes`, `source`, `yield`, `prepinfo`, `preptime`, `cooktime`, `temptype`, `temp`, `type_id`, `status_id`, `creator_id`, `created`, `viewed`
|
||||
FROM `".$self -> {"settings"} -> {"database"} -> {"recipes"}."`
|
||||
WHERE `id` = ?");
|
||||
my $rows = $moveh -> execute($sourceid);
|
||||
@ -826,6 +832,7 @@ sub _renumber_recipe {
|
||||
my $newid = $self -> {"dbh"} -> {"mysql_insertid"}
|
||||
or return $self -> self_error("Unable to obtain id for new recipe");
|
||||
|
||||
# Move all the old ingredient and tage relations to the copy we've just made
|
||||
$self -> _fix_recipe_relations($sourceid, $newid)
|
||||
or return undef;
|
||||
|
||||
@ -870,6 +877,13 @@ sub _fix_recipe_relations {
|
||||
$moveh -> execute($destid, $sourceid)
|
||||
or return $self -> self_error("Ingredient relation fixup failed: ".$self -> {"dbh"} -> errstr());
|
||||
|
||||
# And set the original ID in the renumbered recipe
|
||||
my $origh = $self -> {"dbh"} -> prepare("UPDATE `".$self -> {"settings"} -> {"database"} -> {"recipes"}."`
|
||||
SET `original_id` = ?
|
||||
WHERE `id` = ?");
|
||||
$origh -> execute($sourceid, $destid)
|
||||
or return $self -> self_error("Ingredient origin fixup failed: ".$self -> {"dbh"} -> errstr());
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -1029,4 +1043,9 @@ sub _where_fragment {
|
||||
|
||||
return $frag;
|
||||
}
|
||||
|
||||
|
||||
sub _multi_where_fragment {
|
||||
my $self = shift;
|
||||
}
|
||||
1;
|
||||
|
@ -11,6 +11,42 @@ use Webperl::ConfigMicro;
|
||||
use ORB::System;
|
||||
use Data::Dumper;
|
||||
|
||||
## @fn void clear_target_tables($dbh, $settings)
|
||||
# Empty out tables in the new ORB database to allow easier reimport.
|
||||
#
|
||||
# @param dbh A reference to the new ORB database handle.
|
||||
sub clear_target_tables {
|
||||
my $dbh = shift;
|
||||
my $settings = shift;
|
||||
|
||||
# The tables to truncate
|
||||
my @truncate = (
|
||||
'convert',
|
||||
'ingredients',
|
||||
'prep',
|
||||
'recipes',
|
||||
'recipeing',
|
||||
'recipetags',
|
||||
'states',
|
||||
'tags',
|
||||
'types',
|
||||
'units'
|
||||
);
|
||||
|
||||
foreach my $table (@truncate) {
|
||||
$dbh -> do("TRUNCATE `".$settings -> {"database"} -> {$table}."`")
|
||||
or die "Truncate failed: ".$dbh -> errstr."\n";
|
||||
}
|
||||
|
||||
$dbh -> do("DELETE FROM `".$settings -> {"database"} -> {"metadata"}."`
|
||||
WHERE `id` > 1")
|
||||
or die "Metadata cleanup failed: ".$dbh -> errstr."\n";
|
||||
|
||||
$dbh -> do("ALTER TABLE `".$settings -> {"database"} -> {"metadata"}."`
|
||||
AUTO_INCREMENT = 2")
|
||||
or die "Metadata autoinc set failed: ".$dbh -> errstr."\n";
|
||||
}
|
||||
|
||||
|
||||
## @fn $ get_source_recipeids($dbh, $settings, $logger)
|
||||
# Fetch a list of recipie IDs in the source ORB database.
|
||||
@ -174,8 +210,10 @@ sub convert_recipe {
|
||||
$recipe -> {"created"} = $recipe -> {"updated"};
|
||||
|
||||
# And fix up fields that need to do name mapping
|
||||
$recipe -> {"type"} = $recipe -> {"typename"};
|
||||
$recipe -> {"status"} = $recipe -> {"statusname"};
|
||||
$recipe -> {"type"} = $recipe -> {"typename"};
|
||||
$recipe -> {"status"} = $recipe -> {"statusname"};
|
||||
$recipe -> {"prepinfo"} = $recipe -> {"timereq"};
|
||||
$recipe -> {"cooktime"} = $recipe -> {"timemins"};
|
||||
|
||||
# And go through the list of ingredients tweaking as needed
|
||||
foreach my $ingred (@{$recipe -> {"ingredients"}}) {
|
||||
@ -189,6 +227,9 @@ sub convert_recipe {
|
||||
}
|
||||
}
|
||||
|
||||
# Nuke the source id
|
||||
delete $recipe -> {"id"};
|
||||
|
||||
return $recipe;
|
||||
}
|
||||
|
||||
@ -222,6 +263,8 @@ my $system = ORB::System -> new(dbh => $newdbh,
|
||||
$system -> init()
|
||||
or $logger -> die_log(undef, $system -> errstr());
|
||||
|
||||
clear_target_tables($newdbh, $targetcfg);
|
||||
|
||||
my $rows = get_source_recipeids($olddbh, $legacycfg, $logger);
|
||||
|
||||
foreach my $recipeid (@{$rows}) {
|
||||
|
@ -65,7 +65,8 @@ div.off-canvas .user {
|
||||
|
||||
.pagemenu > li > a {
|
||||
width: 2rem;
|
||||
padding: 0.75rem 0.75rem;
|
||||
padding: 0.25rem 0.25rem;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.pagemenu > li.active > a {
|
||||
@ -99,4 +100,8 @@ div.time-duration-picker-content td select {
|
||||
|
||||
.spacer {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
div.topspace {
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
@ -2,7 +2,3 @@
|
||||
div.contextlink {
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
|
||||
div.topspace {
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
div.recipe {
|
||||
margin: 0px 1.5rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
div.recipe h4 {
|
||||
@ -8,6 +9,7 @@ div.recipe h4 {
|
||||
|
||||
div.title {
|
||||
font-weight: bold;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
div.ingredients ul {
|
||||
@ -24,6 +26,7 @@ div.ingredients ul li.ingredient {
|
||||
}
|
||||
|
||||
div.ingredients ul li.separator {
|
||||
margin-left: 1rem;
|
||||
font-weight: bold;
|
||||
border-bottom: 1px solid #ccc;
|
||||
}
|
||||
|
@ -1,3 +1,21 @@
|
||||
var CKCONFIG = {
|
||||
font_names: 'Arial/Arial, Helvetica, sans-serif;' +
|
||||
'Book Antiqua/Book Antiqua, serif;'+
|
||||
'Cambria/Cambria, serif;'+
|
||||
'Courier New/Courier New, Courier, monospace;' +
|
||||
'Georgia/Georgia, serif;' +
|
||||
'Lucida Sans Unicode/Lucida Sans Unicode, Lucida Grande, sans-serif;' +
|
||||
'Tahoma/Tahoma, Geneva, sans-serif;' +
|
||||
'Times New Roman/Times New Roman, Times, serif;' +
|
||||
'Trebuchet MS/Trebuchet MS, Helvetica, sans-serif;' +
|
||||
'Verdana/Verdana, Geneva, sans-serif'
|
||||
};
|
||||
|
||||
function check_name()
|
||||
{
|
||||
var $name = $('#name').val();
|
||||
|
||||
}
|
||||
|
||||
|
||||
function add_separator()
|
||||
@ -22,8 +40,43 @@ function add_ingredient(count)
|
||||
}
|
||||
|
||||
|
||||
function build_ingdata()
|
||||
{
|
||||
var values = new Array();
|
||||
|
||||
// Go through all the children of the ingredient list
|
||||
// storing the value therein in elements of the values list
|
||||
$('#ingredients').children().each(function() {
|
||||
|
||||
// Is this a separator row?
|
||||
if($(this).hasClass('separator')) {
|
||||
var name = $(this).find('input.separator').val();
|
||||
|
||||
values.push({ "separator": true,
|
||||
"name": name });
|
||||
} else {
|
||||
var quantity = $(this).find('input.quantity').val();
|
||||
var units = $(this).find('select.units').val();
|
||||
var prep = $(this).find('select.preps').val();
|
||||
var name = $(this).find('input.ingredient').val();
|
||||
var notes = $(this).find('input.notes').val();
|
||||
|
||||
values.push({ "separator": false,
|
||||
"quantity": quantity,
|
||||
"units": units,
|
||||
"prep": prep,
|
||||
"name": name,
|
||||
"notes": notes });
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
$('#ingdata').val(JSON.stringify({ "ingredients": values }));
|
||||
}
|
||||
|
||||
|
||||
$(function() {
|
||||
$('#timemins').timeDurationPicker({
|
||||
$('#preptime').timeDurationPicker({
|
||||
lang: 'en_US',
|
||||
seconds: false,
|
||||
minutes: true,
|
||||
@ -32,8 +85,22 @@ $(function() {
|
||||
months: false,
|
||||
years: false,
|
||||
onSelect: function(element, seconds, humanDuration) {
|
||||
$('#timemins').val(humanDuration);
|
||||
$('#timesecs').val(seconds);
|
||||
$('#preptime').val(humanDuration);
|
||||
$('#prepsecs').val(seconds);
|
||||
console.log(seconds, humanDuration);
|
||||
}
|
||||
});
|
||||
$('#cooktime').timeDurationPicker({
|
||||
lang: 'en_US',
|
||||
seconds: false,
|
||||
minutes: true,
|
||||
hours: true,
|
||||
days: true,
|
||||
months: false,
|
||||
years: false,
|
||||
onSelect: function(element, seconds, humanDuration) {
|
||||
$('#cooktime').val(humanDuration);
|
||||
$('#cooksecs').val(seconds);
|
||||
console.log(seconds, humanDuration);
|
||||
}
|
||||
});
|
||||
@ -51,8 +118,8 @@ $(function() {
|
||||
}
|
||||
});
|
||||
|
||||
CKEDITOR.replace('method');
|
||||
CKEDITOR.replace('notes');
|
||||
CKEDITOR.replace('method', CKCONFIG);
|
||||
CKEDITOR.replace('notes', CKCONFIG);
|
||||
|
||||
$('#ingredients').sortable({
|
||||
placeholder: "ui-state-highlight"
|
||||
@ -71,4 +138,7 @@ $(function() {
|
||||
$('.deletectrl').on('click', function() {
|
||||
$(this).parents('li').fadeOut(300, function() { $(this).remove(); });
|
||||
});
|
||||
|
||||
// Build the ingredient list before submitting
|
||||
$('#newrecipe').on('submit', function() { build_ingdata(); return true });
|
||||
});
|
||||
|
@ -1,4 +1,4 @@
|
||||
<div class="small-8 small-centered columns">
|
||||
<div class="topspace cell small-8 small-offset-2">
|
||||
<!-- Start messagebox core -->
|
||||
<div class="messagebox callout %(class)s">
|
||||
<h4>%(title)s</h4>
|
||||
|
@ -19,13 +19,19 @@
|
||||
</div>
|
||||
<div>
|
||||
<label>{L_RECIPE_PREPINFO}
|
||||
<input maxlength="255" data-tooltip aria-haspopup="true" class="has-tip top" data-disable-hover="false" title="{L_RECIPE_PREPINFO_DOC}" type="text" id="timereq" name="timereq" value="%(timereq)s" placeholder="{L_RECIPE_PREPINFO_PH}" required />
|
||||
<input maxlength="255" data-tooltip aria-haspopup="true" class="has-tip top" data-disable-hover="false" title="{L_RECIPE_PREPINFO_DOC}" type="text" id="prepinfo" name="prepinfo" value="%(prepinfo)s" placeholder="{L_RECIPE_PREPINFO_PH}" required />
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<label>{L_RECIPE_TIMEREQ}
|
||||
<input data-tooltip aria-haspopup="true" class="has-tip top" data-disable-hover="false" title="{L_RECIPE_TIMEREQ_DOC}" type="text" id="timemins" name="timemins" value="%(timemins)s" placeholder="{L_RECIPE_TIMEREQ_PH}" />
|
||||
<input type="hidden" name="timesecs" id="timesecs" value="%(timesecs)s" />
|
||||
<label>{L_RECIPE_PREPTIME}
|
||||
<input data-tooltip aria-haspopup="true" class="has-tip top" data-disable-hover="false" title="{L_RECIPE_PREPTIME_DOC}" type="text" id="preptime" name="preptime" value="%(preptime)s" placeholder="{L_RECIPE_PREPTIME_PH}" autocomplete="off" />
|
||||
<input type="hidden" name="prepsecs" id="prepsecs" value="%(prepsecs)s" />
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<label>{L_RECIPE_COOKTIME}
|
||||
<input data-tooltip aria-haspopup="true" class="has-tip top" data-disable-hover="false" title="{L_RECIPE_COOKTIME_DOC}" type="text" id="cooktime" name="cooktime" value="%(cooktime)s" placeholder="{L_RECIPE_COOKTIME_PH}" autocomplete="off" />
|
||||
<input type="hidden" name="cooksecs" id="cooksecs" value="%(cooksecs)s" />
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
|
@ -2,7 +2,7 @@
|
||||
<div class="top-bar-left">
|
||||
<ul class="menu">
|
||||
<li><button id="menubtn" class="menu-icon dark" type="button" data-open="offCanvas"></button></li>
|
||||
<li><form action="%(url-search)s" method="POST"><input type="search" placeholder="Search"></form></li>
|
||||
<li><form action="%(url-search)s" method="POST"><input type="search" name="search" id="search" placeholder="Search"></form></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="top-bar-right show-for-medium">
|
||||
|
Loading…
x
Reference in New Issue
Block a user