diff --git a/app/controllers/targets_controller.rb b/app/controllers/targets_controller.rb index 0a4077b..d5804f4 100644 --- a/app/controllers/targets_controller.rb +++ b/app/controllers/targets_controller.rb @@ -5,14 +5,14 @@ class TargetsController < ApplicationController include Concerns::Finders - before_action :find_project_by_project_id, only: [:index] + before_action :find_project_by_project_id, only: [:index, :new] def index prepare_targets end def new - @target = @project.targets.new + @target = (@goal || @project.goals.binding).targets.new @target.arity.times { @target.thresholds.new } end diff --git a/app/helpers/body_trackers_helper.rb b/app/helpers/body_trackers_helper.rb index 16964c3..ef383ab 100644 --- a/app/helpers/body_trackers_helper.rb +++ b/app/helpers/body_trackers_helper.rb @@ -32,6 +32,12 @@ module BodyTrackersHelper options_for_select(options, disabled: 0) end + def quantity_options(domain = :all) + nested_set_options(@project.quantities.send(domain)) do |q| + raw("#{' ' * q.level}#{q.name}") + end + end + def unit_options @project.units.map do |u| [u.shortname, u.id] diff --git a/app/helpers/foods_helper.rb b/app/helpers/foods_helper.rb index 8940039..156fd28 100644 --- a/app/helpers/foods_helper.rb +++ b/app/helpers/foods_helper.rb @@ -1,10 +1,4 @@ module FoodsHelper - def quantity_options - nested_set_options(@project.quantities.diet) do |q| - raw("#{' ' * q.level}#{q.name}") - end - end - def visibility_options(selected) options = [["visible", 1], ["hidden", 0]] options_for_select(options, selected) diff --git a/app/helpers/measurements_helper.rb b/app/helpers/measurements_helper.rb index 77d646d..5bff5b0 100644 --- a/app/helpers/measurements_helper.rb +++ b/app/helpers/measurements_helper.rb @@ -5,12 +5,6 @@ module MeasurementsHelper .html_safe end - def quantity_options - nested_set_options(@project.quantities.measurement) do |q| - raw("#{' ' * q.level}#{q.name}") - end - end - def source_options @project.sources.map do |s| [s.name, s.id] diff --git a/app/helpers/targets_helper.rb b/app/helpers/targets_helper.rb new file mode 100644 index 0000000..e695f23 --- /dev/null +++ b/app/helpers/targets_helper.rb @@ -0,0 +1,13 @@ +module TargetsHelper + def condition_options + Target::CONDITIONS.each_with_index.to_a + end + + def action_links(m) + link_to(l(:button_retake), retake_measurement_path(m, @view_params), + {remote: true, class: "icon icon-reload"}) + + link_to(l(:button_edit), edit_measurement_path(m, @view_params), + {remote: true, class: "icon icon-edit"}) + + delete_link(measurement_path(m), {remote: true, data: {}}) + end +end diff --git a/app/models/target.rb b/app/models/target.rb index 402271e..ac9a008 100644 --- a/app/models/target.rb +++ b/app/models/target.rb @@ -1,5 +1,7 @@ class Target < ActiveRecord::Base - belongs_to :goal, inverse_of: :targets + CONDITIONS = [:<, :<=, :>, :>=, :==] + + belongs_to :goal, inverse_of: :targets, required: true belongs_to :item, polymorphic: true, inverse_of: :targets has_many :thresholds, as: :registry, inverse_of: :target, dependent: :destroy, validate: true @@ -7,19 +9,25 @@ class Target < ActiveRecord::Base validates :thresholds, presence: true accepts_nested_attributes_for :thresholds, allow_destroy: true, reject_if: proc { |attrs| attrs['quantity_id'].blank? && attrs['value'].blank? } - # TODO: validate thresholds count according to condition type - validates :condition, inclusion: {in: [:<, :<=, :>, :>=, :==]} + validate do + errors.add(:thresholds, :count_mismatch) unless thresholds.count == arity + errors.add(:thresholds, :quantity_mismatch) if thresholds.to_a.uniq(&:quantity) != 1 + end + validates :condition, inclusion: {in: CONDITIONS } validates :scope, inclusion: {in: [:day], if: -> { thresholds.first.domain == :diet }} - validates :effective_from, presence: {unless: -> { goal.present? }}, - absence: {if: -> { goal.present? }} + validates :effective_from, presence: {unless: :is_binding?}, absence: {if: :is_binding?} after_initialize do if new_record? - self.condition = :< + self.condition = CONDITIONS.first end end def arity BigDecimal.method(condition).arity end + + def is_binding? + goal == goal.project.goals.binding + end end diff --git a/app/views/foods/_form.html.erb b/app/views/foods/_form.html.erb index 58caaf5..55af5ba 100644 --- a/app/views/foods/_form.html.erb +++ b/app/views/foods/_form.html.erb @@ -25,7 +25,7 @@ <%= f.fields_for 'nutrients_attributes', n, index: '' do |ff| %>
<%= ff.hidden_field :id %> - <%= ff.select :quantity_id, quantity_options, + <%= ff.select :quantity_id, quantity_options(:diet), {include_blank: true, required: true, label: (index > 0 ? '' : :field_nutrients)} %> <%= ff.number_field :amount, {size: 8, min: 0, step: :any, label: ''} %> <%= ff.select :unit_id, unit_options, {label: ''} %> diff --git a/app/views/goals/_form.html.erb b/app/views/goals/_form.html.erb new file mode 100644 index 0000000..ce32e44 --- /dev/null +++ b/app/views/goals/_form.html.erb @@ -0,0 +1,13 @@ +
+ + <%= ff.text_field :name, required: true, style: "width: 95%;" %> +
++ + <%= ff.text_area :description, cols: 40, rows: 3, style: "width: 95%;" %> +
+ <% end %> ++ + <%= ff.select :id, + options_from_collection_for_select(@project.goals, :id, :name, goal.id), + {required: true}, autocomplete: 'off', + onchange: "var goal_id = $('#target_goal_attributes_id').val(); + $.ajax({ + url: '#{goal_path(id: :goal_id)}'.replace('goal_id', goal_id), + dataType: 'script' + }); + return false;" %> + <%= link_to l(:button_edit), '#', + onclick: "var goal_id = $('#target_goal_attributes_id').val(); + $.ajax({ + url: '#{edit_goal_path(id: :goal_id)}'.replace('goal_id', goal_id), + dataType: 'script' + }); + return false;", + class: 'icon icon-edit' %> +
+<% end %> +<% if goal.description? %> +<%= goal.description %>
+<% end %> +<%= routine.description %>
<% end %> diff --git a/app/views/measurements/_form.html.erb b/app/views/measurements/_form.html.erb index 58e32d0..c76c209 100644 --- a/app/views/measurements/_form.html.erb +++ b/app/views/measurements/_form.html.erb @@ -30,7 +30,7 @@ <%= f.fields_for 'readouts_attributes', r, index: '' do |ff| %><%= ff.hidden_field :id %> - <%= ff.select :quantity_id, quantity_options, + <%= ff.select :quantity_id, quantity_options(:measurement), {include_blank: true, required: true, label: (index > 0 ? '' : :field_readouts)} %> <%= ff.number_field :value, {size: 8, step: :any, label: ''} %> <%= ff.select :unit_id, unit_options, {label: ''} %> diff --git a/app/views/targets/_form.html.erb b/app/views/targets/_form.html.erb new file mode 100644 index 0000000..250a6b1 --- /dev/null +++ b/app/views/targets/_form.html.erb @@ -0,0 +1,65 @@ +<%= error_messages_for @target %> + +
+ <% @target.thresholds.each_with_index do |t, index| %> + <%= f.fields_for 'thresholds_attributes', t, index: '' do |ff| %> + <% if index == 0 %> + <%= ff.select :quantity_id, quantity_options, + {include_blank: true, required: true, label: :field_target} %> + <%= f.select :condition, condition_options, required: true %> + <% end %> + <%= ff.hidden_field :id %> + <%= ff.number_field :value, {size: 8, step: :any, label: ''} %> + <% if index == 0 %> + <%= ff.select :unit_id, unit_options, {label: ''} %> + <% end %> + <% end %> + <% end %> + <%= link_to t(".button_delete_target"), '#', + class: 'icon icon-del', + onclick: "deleteTarget(); return false;" %> +
+ <%= link_to t(".button_new_target"), '#', + class: 'icon icon-add', + onclick: 'newTarget(); return false;' %> ++ <%= submit_tag l(:button_create) %> + <%= link_to l(:button_cancel), "#", + onclick: '$("#new-target").empty(); return false;' %> +
+