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",
|
return $self -> {"template"} -> load_template("list/recipe.tem",
|
||||||
{ "%(id)s" => $recipe -> {"id"},
|
{ "%(id)s" => $recipe -> {"id"},
|
||||||
"%(url-view)s" => $self -> build_url(block => "view",
|
"%(url-view)s" => $self -> build_url(block => "view",
|
||||||
@ -80,7 +82,7 @@ sub _build_recipe {
|
|||||||
"%(name)s" => $recipe -> {"name"},
|
"%(name)s" => $recipe -> {"name"},
|
||||||
"%(type)s" => $recipe -> {"type"},
|
"%(type)s" => $recipe -> {"type"},
|
||||||
"%(status)s" => $recipe -> {"status"},
|
"%(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,
|
"%(temp)s" => $temp,
|
||||||
"%(tags)s" => join("", map { $self -> _build_tag($_) } @{$recipe -> {"tags"}}),
|
"%(tags)s" => join("", map { $self -> _build_tag($_) } @{$recipe -> {"tags"}}),
|
||||||
"%(controls)s" => $controls,
|
"%(controls)s" => $controls,
|
||||||
|
@ -85,17 +85,23 @@ sub _generate_new {
|
|||||||
my $ingredients = $self -> _build_ingredients($args);
|
my $ingredients = $self -> _build_ingredients($args);
|
||||||
|
|
||||||
# Build up the type and status data
|
# 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"});
|
$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"});
|
$args -> {"status"});
|
||||||
|
|
||||||
# Convert the time fields
|
# Convert the time fields
|
||||||
my ($timemins, $timesecs) = ("", 0);
|
my ($preptime, $prepsecs) = ("", 0);
|
||||||
if($args -> {"timemins"}) {
|
if($args -> {"preptime"}) {
|
||||||
$timesecs = $args -> {"timemins"} * 60;
|
$prepsecs = $args -> {"preptime"} * 60;
|
||||||
$timemins = $self -> _build_timereq($timesecs);
|
$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.
|
# 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"} // "",
|
"%(name)s" => $args -> {"name"} // "",
|
||||||
"%(source)s" => $args -> {"source"} // "",
|
"%(source)s" => $args -> {"source"} // "",
|
||||||
"%(yield)s" => $args -> {"yield"} // "",
|
"%(yield)s" => $args -> {"yield"} // "",
|
||||||
"%(timereq)s" => $args -> {"timereq"} // "",
|
"%(prepinfo)s" => $args -> {"prepinfo"} // "",
|
||||||
"%(timemins)s" => $timemins,
|
"%(preptime)s" => $preptime,
|
||||||
"%(timesecs)s" => $timesecs,
|
"%(prepsecs)s" => $prepsecs,
|
||||||
|
"%(cooktime)s" => $cooktime,
|
||||||
|
"%(cooksecs)s" => $cooksecs,
|
||||||
"%(temp)s" => $args -> {"temp"} // "",
|
"%(temp)s" => $args -> {"temp"} // "",
|
||||||
"%(temptypes)s" => $self -> {"template"} -> build_optionlist($temptypes, $args -> {"temptype"}),
|
"%(temptypes)s" => $self -> {"template"} -> build_optionlist($temptypes, $args -> {"temptype"}),
|
||||||
"%(types)s" => $typeopts,
|
"%(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": {
|
"/tags": {
|
||||||
"get": {
|
"get": {
|
||||||
"tags": [
|
"tags": [
|
||||||
@ -139,6 +177,15 @@
|
|||||||
"$ref": "#/definitions/Ingredient"
|
"$ref": "#/definitions/Ingredient"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"Recipe": {
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"Recipes": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/Recipe"
|
||||||
|
}
|
||||||
|
},
|
||||||
"Tag": {
|
"Tag": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
@ -62,6 +62,32 @@ paths:
|
|||||||
description: Unexpected error
|
description: Unexpected error
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/Error'
|
$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:
|
/tags:
|
||||||
get:
|
get:
|
||||||
tags:
|
tags:
|
||||||
@ -102,6 +128,12 @@ definitions:
|
|||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
$ref: '#/definitions/Ingredient'
|
$ref: '#/definitions/Ingredient'
|
||||||
|
Recipe:
|
||||||
|
type: object
|
||||||
|
Recipes:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/definitions/Recipe'
|
||||||
Tag:
|
Tag:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
|
@ -18,9 +18,13 @@ RECIPE_PREPINFO = Prep info
|
|||||||
RECIPE_PREPINFO_DOC = How much time each step of the recipe take?
|
RECIPE_PREPINFO_DOC = How much time each step of the recipe take?
|
||||||
RECIPE_PREPINFO_PH = 10 min prep + 20 min cook
|
RECIPE_PREPINFO_PH = 10 min prep + 20 min cook
|
||||||
|
|
||||||
RECIPE_TIMEREQ = Time required
|
RECIPE_PREPTIME = Preparation time required
|
||||||
RECIPE_TIMEREQ_DOC = How long does this recipe take in total?
|
RECIPE_PREPTIME_DOC = How long does this recipe take to prepare?
|
||||||
RECIPE_TIMEREQ_PH = 1 hour 10 minutes
|
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 = Oven preheat
|
||||||
RECIPE_OVENTEMP_DOC = Initial oven temperature (show changes in method)
|
RECIPE_OVENTEMP_DOC = Initial oven temperature (show changes in method)
|
||||||
|
@ -71,6 +71,16 @@ sub new {
|
|||||||
@_)
|
@_)
|
||||||
or return undef;
|
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;
|
return $self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -273,6 +273,8 @@ sub find_ids {
|
|||||||
# is no maximum and all possible matched are returned.
|
# is no maximum and all possible matched are returned.
|
||||||
# - `as`: can be set to `name`, `value`, or `text`. This determines the key
|
# - `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.
|
# 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.
|
# @param args A hash or reference to a hash of search settings.
|
||||||
# @return A reference to an array of hashes containing the results, ordered
|
# @return A reference to an array of hashes containing the results, ordered
|
||||||
@ -297,7 +299,13 @@ sub find {
|
|||||||
default { $as = "name"; }
|
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"}}."`
|
FROM `".$self -> {"settings"} -> {"database"} -> {$self -> {"entity_table"}}."`
|
||||||
WHERE `name` LIKE ?
|
WHERE `name` LIKE ?
|
||||||
ORDER BY `name`,`id`
|
ORDER BY `name`,`id`
|
||||||
|
@ -17,40 +17,7 @@
|
|||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
## @class Recipe
|
## @class Recipe
|
||||||
# +-------------+--------------------------------+------+-----+----------------+
|
# FIXME: corrected table schema here
|
||||||
# | 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 | | |
|
|
||||||
# +-----------+------------------+------+-----+----------------+
|
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
|
||||||
@ -107,16 +74,14 @@ sub clear {
|
|||||||
#
|
#
|
||||||
# - `id`: (optional, avoid) Set the ID to create the recipe with.
|
# - `id`: (optional, avoid) Set the ID to create the recipe with.
|
||||||
# This should generally not be specified unless doing edits.
|
# This should generally not be specified unless doing edits.
|
||||||
# - `previd`: (optional) ID of the recipe this is an edit of. If specified,
|
# - `origid`: (optional) ID of the recipe this is an edit of. Generally
|
||||||
# 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
|
|
||||||
# this will not be specified directly; if editing a recipe,
|
# this will not be specified directly; if editing a recipe,
|
||||||
# call edit() to have renumbering handled for you.
|
# call edit() to have renumbering handled for you.
|
||||||
# - `name`: The name of the recipe
|
# - `name`: The name of the recipe
|
||||||
# - `source`: (optional) Where did the recipe come from originally?
|
# - `source`: (optional) Where did the recipe come from originally?
|
||||||
# - `timereq`: (optional) A string describing the time required for the recipe
|
# - `prepinfo`: (optional) A string describing the time required for the recipe
|
||||||
# - `timemins`: How long does the recipe take in minutes, in total?
|
# - `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
|
# - `yield`: A string describing how much stuff the recipe creates
|
||||||
# - `temp`: (optional) Oven preheat temperature
|
# - `temp`: (optional) Oven preheat temperature
|
||||||
# - `temptype`: The type of units used: 'C', 'F', 'Gas mark', or 'N/A'
|
# - `temptype`: The type of units used: 'C', 'F', 'Gas mark', or 'N/A'
|
||||||
@ -170,19 +135,20 @@ sub create {
|
|||||||
unless($args -> {"created"});
|
unless($args -> {"created"});
|
||||||
|
|
||||||
# We need a metadata context for the recipe
|
# 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
|
# Do the insert, and fetch the ID of the new row
|
||||||
my $newh = $self -> {"dbh"} -> prepare("INSERT INTO `".$self -> {"settings"} -> {"database"} -> {"recipes"}."`
|
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`)
|
(`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(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ,?)");
|
VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ,?)");
|
||||||
my $result = $newh -> execute($args -> {"id"},
|
my $result = $newh -> execute($args -> {"id"},
|
||||||
$metadataid,
|
$metadataid,
|
||||||
$args -> {"previd"},
|
$args -> {"origid"},
|
||||||
$args -> {"name"},
|
$args -> {"name"},
|
||||||
$args -> {"source"},
|
$args -> {"source"},
|
||||||
$args -> {"timereq"},
|
$args -> {"prepinfo"},
|
||||||
$args -> {"timemins"},
|
$args -> {"preptime"},
|
||||||
|
$args -> {"cooktime"},
|
||||||
$args -> {"yield"},
|
$args -> {"yield"},
|
||||||
$args -> {"temp"},
|
$args -> {"temp"},
|
||||||
$args -> {"temptype"},
|
$args -> {"temptype"},
|
||||||
@ -200,7 +166,8 @@ sub create {
|
|||||||
return $self -> self_error("No rows added when inserting recipe.")
|
return $self -> self_error("No rows added when inserting recipe.")
|
||||||
if($result eq "0E0");
|
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")
|
return $self -> self_error("Unable to obtain id for new recipe")
|
||||||
if(!$newid);
|
if(!$newid);
|
||||||
@ -228,7 +195,7 @@ sub create {
|
|||||||
# updated recipe overwrites the data at the old ID).
|
# updated recipe overwrites the data at the old ID).
|
||||||
#
|
#
|
||||||
# @param args This should be a reference to a hash containing the same
|
# @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
|
# required here. This should also contain the field
|
||||||
# `updaterid` containing the ID of the user doing the edit.
|
# `updaterid` containing the ID of the user doing the edit.
|
||||||
# @return The recipe Id on success, undef on error.
|
# @return The recipe Id on success, undef on error.
|
||||||
@ -238,15 +205,16 @@ sub edit {
|
|||||||
|
|
||||||
$self -> clear_error();
|
$self -> clear_error();
|
||||||
|
|
||||||
return $self -> self_error("edit called without previous recipe ID")
|
return $self -> self_error("edit called without master recipe ID")
|
||||||
unless($args -> {"previd"});
|
unless($args -> {"origid"});
|
||||||
|
|
||||||
# Move the old recipe to the end of the table, but keep a record
|
# We want the new recipe to get the same ID as the old one, so record it
|
||||||
# of its current ID
|
$args -> {"id"} = $args -> {"origid"};
|
||||||
$args -> {"id"} = $args -> {"previd"};
|
|
||||||
my $renumbered = $self -> _renumber_recipe($args -> {"id"});
|
|
||||||
|
|
||||||
# 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)
|
$self -> create($args)
|
||||||
or return undef;
|
or return undef;
|
||||||
|
|
||||||
@ -256,6 +224,8 @@ sub edit {
|
|||||||
$args -> {"updaterid"})
|
$args -> {"updaterid"})
|
||||||
or return undef;
|
or return undef;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return $args -> {"id"};
|
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
|
# Recipe retrieval
|
||||||
|
|
||||||
@ -474,6 +469,8 @@ sub load_recipe_relations {
|
|||||||
# - `tagmatch`: control how tag searching works. As with `ingredmatch`, this
|
# - `tagmatch`: control how tag searching works. As with `ingredmatch`, this
|
||||||
# may be "all" or "any", with corresponding behaviour.
|
# may be "all" or "any", with corresponding behaviour.
|
||||||
# - `limit`: how many recipies may be returned by the find()
|
# - `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.
|
# - `offset`: offset from the start of the query results.
|
||||||
# - `order`: optional ordering of results. Allowed values are 'added', 'updated',
|
# - `order`: optional ordering of results. Allowed values are 'added', 'updated',
|
||||||
# 'viewed', or 'name' (the default).
|
# 'viewed', or 'name' (the default).
|
||||||
@ -561,7 +558,16 @@ sub find {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Squish all the where conditions into a string
|
# 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
|
# Construct the limit term when limit (and optionally offset) are
|
||||||
# specified by the caller
|
# specified by the caller
|
||||||
@ -666,7 +672,7 @@ sub _add_ingredients {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Likewise for preparation methods
|
# 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"})
|
$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());
|
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
|
# Duplicate the source recipe at the end of the table
|
||||||
my $moveh = $self -> {"dbh"} -> prepare("INSERT INTO `".$self -> {"settings"} -> {"database"} -> {"recipes"}."`
|
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`)
|
(`metadata_id`, `name`, `method`, `notes`, `source`, `yield`, `prepinfo`, `preptime`, `cooktime`, `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`
|
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"}."`
|
FROM `".$self -> {"settings"} -> {"database"} -> {"recipes"}."`
|
||||||
WHERE `id` = ?");
|
WHERE `id` = ?");
|
||||||
my $rows = $moveh -> execute($sourceid);
|
my $rows = $moveh -> execute($sourceid);
|
||||||
@ -826,6 +832,7 @@ sub _renumber_recipe {
|
|||||||
my $newid = $self -> {"dbh"} -> {"mysql_insertid"}
|
my $newid = $self -> {"dbh"} -> {"mysql_insertid"}
|
||||||
or return $self -> self_error("Unable to obtain id for new recipe");
|
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)
|
$self -> _fix_recipe_relations($sourceid, $newid)
|
||||||
or return undef;
|
or return undef;
|
||||||
|
|
||||||
@ -870,6 +877,13 @@ sub _fix_recipe_relations {
|
|||||||
$moveh -> execute($destid, $sourceid)
|
$moveh -> execute($destid, $sourceid)
|
||||||
or return $self -> self_error("Ingredient relation fixup failed: ".$self -> {"dbh"} -> errstr());
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1029,4 +1043,9 @@ sub _where_fragment {
|
|||||||
|
|
||||||
return $frag;
|
return $frag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
sub _multi_where_fragment {
|
||||||
|
my $self = shift;
|
||||||
|
}
|
||||||
1;
|
1;
|
||||||
|
@ -11,6 +11,42 @@ use Webperl::ConfigMicro;
|
|||||||
use ORB::System;
|
use ORB::System;
|
||||||
use Data::Dumper;
|
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)
|
## @fn $ get_source_recipeids($dbh, $settings, $logger)
|
||||||
# Fetch a list of recipie IDs in the source ORB database.
|
# Fetch a list of recipie IDs in the source ORB database.
|
||||||
@ -174,8 +210,10 @@ sub convert_recipe {
|
|||||||
$recipe -> {"created"} = $recipe -> {"updated"};
|
$recipe -> {"created"} = $recipe -> {"updated"};
|
||||||
|
|
||||||
# And fix up fields that need to do name mapping
|
# And fix up fields that need to do name mapping
|
||||||
$recipe -> {"type"} = $recipe -> {"typename"};
|
$recipe -> {"type"} = $recipe -> {"typename"};
|
||||||
$recipe -> {"status"} = $recipe -> {"statusname"};
|
$recipe -> {"status"} = $recipe -> {"statusname"};
|
||||||
|
$recipe -> {"prepinfo"} = $recipe -> {"timereq"};
|
||||||
|
$recipe -> {"cooktime"} = $recipe -> {"timemins"};
|
||||||
|
|
||||||
# And go through the list of ingredients tweaking as needed
|
# And go through the list of ingredients tweaking as needed
|
||||||
foreach my $ingred (@{$recipe -> {"ingredients"}}) {
|
foreach my $ingred (@{$recipe -> {"ingredients"}}) {
|
||||||
@ -189,6 +227,9 @@ sub convert_recipe {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Nuke the source id
|
||||||
|
delete $recipe -> {"id"};
|
||||||
|
|
||||||
return $recipe;
|
return $recipe;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,6 +263,8 @@ my $system = ORB::System -> new(dbh => $newdbh,
|
|||||||
$system -> init()
|
$system -> init()
|
||||||
or $logger -> die_log(undef, $system -> errstr());
|
or $logger -> die_log(undef, $system -> errstr());
|
||||||
|
|
||||||
|
clear_target_tables($newdbh, $targetcfg);
|
||||||
|
|
||||||
my $rows = get_source_recipeids($olddbh, $legacycfg, $logger);
|
my $rows = get_source_recipeids($olddbh, $legacycfg, $logger);
|
||||||
|
|
||||||
foreach my $recipeid (@{$rows}) {
|
foreach my $recipeid (@{$rows}) {
|
||||||
|
@ -65,7 +65,8 @@ div.off-canvas .user {
|
|||||||
|
|
||||||
.pagemenu > li > a {
|
.pagemenu > li > a {
|
||||||
width: 2rem;
|
width: 2rem;
|
||||||
padding: 0.75rem 0.75rem;
|
padding: 0.25rem 0.25rem;
|
||||||
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pagemenu > li.active > a {
|
.pagemenu > li.active > a {
|
||||||
@ -100,3 +101,7 @@ div.time-duration-picker-content td select {
|
|||||||
.spacer {
|
.spacer {
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div.topspace {
|
||||||
|
margin-top: 0.5rem;
|
||||||
|
}
|
||||||
|
@ -2,7 +2,3 @@
|
|||||||
div.contextlink {
|
div.contextlink {
|
||||||
font-size: 0.75rem;
|
font-size: 0.75rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.topspace {
|
|
||||||
margin-top: 0.5rem;
|
|
||||||
}
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
div.recipe {
|
div.recipe {
|
||||||
margin: 0px 1.5rem;
|
margin: 0px 1.5rem;
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.recipe h4 {
|
div.recipe h4 {
|
||||||
@ -8,6 +9,7 @@ div.recipe h4 {
|
|||||||
|
|
||||||
div.title {
|
div.title {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.ingredients ul {
|
div.ingredients ul {
|
||||||
@ -24,6 +26,7 @@ div.ingredients ul li.ingredient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
div.ingredients ul li.separator {
|
div.ingredients ul li.separator {
|
||||||
|
margin-left: 1rem;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
border-bottom: 1px solid #ccc;
|
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()
|
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() {
|
$(function() {
|
||||||
$('#timemins').timeDurationPicker({
|
$('#preptime').timeDurationPicker({
|
||||||
lang: 'en_US',
|
lang: 'en_US',
|
||||||
seconds: false,
|
seconds: false,
|
||||||
minutes: true,
|
minutes: true,
|
||||||
@ -32,8 +85,22 @@ $(function() {
|
|||||||
months: false,
|
months: false,
|
||||||
years: false,
|
years: false,
|
||||||
onSelect: function(element, seconds, humanDuration) {
|
onSelect: function(element, seconds, humanDuration) {
|
||||||
$('#timemins').val(humanDuration);
|
$('#preptime').val(humanDuration);
|
||||||
$('#timesecs').val(seconds);
|
$('#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);
|
console.log(seconds, humanDuration);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -51,8 +118,8 @@ $(function() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
CKEDITOR.replace('method');
|
CKEDITOR.replace('method', CKCONFIG);
|
||||||
CKEDITOR.replace('notes');
|
CKEDITOR.replace('notes', CKCONFIG);
|
||||||
|
|
||||||
$('#ingredients').sortable({
|
$('#ingredients').sortable({
|
||||||
placeholder: "ui-state-highlight"
|
placeholder: "ui-state-highlight"
|
||||||
@ -71,4 +138,7 @@ $(function() {
|
|||||||
$('.deletectrl').on('click', function() {
|
$('.deletectrl').on('click', function() {
|
||||||
$(this).parents('li').fadeOut(300, function() { $(this).remove(); });
|
$(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 -->
|
<!-- Start messagebox core -->
|
||||||
<div class="messagebox callout %(class)s">
|
<div class="messagebox callout %(class)s">
|
||||||
<h4>%(title)s</h4>
|
<h4>%(title)s</h4>
|
||||||
|
@ -19,13 +19,19 @@
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label>{L_RECIPE_PREPINFO}
|
<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>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label>{L_RECIPE_TIMEREQ}
|
<label>{L_RECIPE_PREPTIME}
|
||||||
<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 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="timesecs" id="timesecs" value="%(timesecs)s" />
|
<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>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<div class="top-bar-left">
|
<div class="top-bar-left">
|
||||||
<ul class="menu">
|
<ul class="menu">
|
||||||
<li><button id="menubtn" class="menu-icon dark" type="button" data-open="offCanvas"></button></li>
|
<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>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="top-bar-right show-for-medium">
|
<div class="top-bar-right show-for-medium">
|
||||||
|
Loading…
x
Reference in New Issue
Block a user