I would like to display an agenda that shows who is available for roster for the next seven days, with the following logic:
Looping through each of the 7 days, for each day:
If the leave starts today, show Starts %H:%M
If the leave finishes today, show Finishes %H:%M
If the leave starts and finishes today, show %H:%M - %H:%M
If the leave doesn't start or finish today but spans over today, show all day
Should include leave that start or finish outside of the 7 days but span the 7 days being displayed.
I am hoping for someone to point me in the right direction preferably using Rails and Postgres. I am not against doing the queries for each day since at most there will only be 30 days displayed, but also looking for reasonably performant code since there could be 100+ leave records per day.
First example that does not fulfill the criteria outlined above.
<% #dates.each do |d| %>
<h5><%= d.strftime("%A %d %b") %></h5>
<% #leave = Leave.where('(start_at BETWEEN ? AND ?) OR (end_at BETWEEN ? AND ?)', d.beginning_of_day, d.end_of_day, d.beginning_of_day, d.end_of_day) %>
<% #leave = #leave.where.not('end_at < ?', Time.current) %>
<% if #leave.any? %>
<ul>
<% #leave.each do |leave| %>
<% if leave.single_day? && leave.start_at.to_date == d %>
<li>
<label class="label label-danger"><%= leave.start_at.strftime('%H:%M') %> - <%= leave.end_at.strftime('%H:%M') %></label>
<%= leave.user.name %>
</li>
<% elsif !leave.single_day? %>
<% if leave.start_at.to_date == d %>
<li>
<label class="label label-danger">From <%= leave.start_at.strftime('%H:%M') %></label>
<%= leave.user.name %>
</li>
<% elsif leave.end_at.to_date == d %>
<li>
<label class="label label-danger">Until <%= leave.end_at.strftime('%H:%M') %></label>
<%= leave.user.name %>
</li>
<% else %>
<li>
<label class="label label-danger">All Day</label>
<%= leave.user.name %>
</li>
<% end %>
<% end %>
<% end %>
</ul>
<br/>
<span class="label label-success" style="margin-right: 10px;">
<span class="glyphicon glyphicon-ok"></span>
</span>
<%= current_account.users.active.where.not(id: #leave.map(&:user_id)).count %> Available
<% else %>
<span class="label label-success" style="margin-right: 10px;">
<span class="glyphicon glyphicon-ok"></span>
</span>
<%= current_account.users.active.count %> Available
<% end %>
<br />
<br />
<% end %>
I would start with something like this:
In the model:
def starts_on?(date)
start_at.to_date == date
end
def ends_on?(date)
end_at.to_date = date
end
def covers?(date)
leave.start_at.to_date <= date && leave.end_at.to_date >= date
end
def starts_and_ends_on?(date)
starts_on?(date) && ends_on?(date)
end
In the controller:
#dates = # define the date range like you already do, I assume it is an array
#leaves = Leave.includes(:user).
where('start_at =< ? AND end_at >= ?', dates.max, dates.min)
In the helper:
def relevant_leaves_for_date(date, leaves)
leaves.select { |leave| leave.covers?(date) }
end
def leave_description_for_date(leave, date)
if leave.starts_and_ends_on?(date)
"#{leave.start_at.strftime('%H:%M')} - #{leave.end_at.strftime('%H:%M')}"
elsif leave.starts_on?(date)
"From #{leave.start_at.strftime('%H:%M')}"
elsif leave.ends_on?(date)
"Until #{leave.end_at.strftime('%H:%M')}"
else
'All day'
end
end
def available_users(leaves)
current_account.users.active.count - leaves.size
end
In the view:
<% #dates.each do |date| %>
<h5><%= date.strftime("%A %d %b") %></h5>
<% leaves = relevant_leaves_for_date(date, #leaves) %>
<% if leaves.any? %>
<ul>
<% leaves.each do |leave| %>
<li>
<label class="label label-danger">
<%= leave_description_for_date(leave, date) %>
</label>
<%= leave.user.name %>
</li>
<% end %>
</ul>
<% end %>
<span class="label label-success">
<span class="glyphicon glyphicon-ok"></span>
</span>
<%= available_users(leaves) %> Available
<% end %>
You might notice that I remove the <br> and style tags from the html. Please do not use <br> for styling or style attributes in the html. Add class the the tags and style them in your css file.
The reason why case 4 & 5 are not working is you are not fetching the leaves which started before the beginning of day or which are going to end after the end of day. So you can fetch all leaves which have not ended yet.
<% #leave = Leave.where('(end_at >= ?', d.beginning_of_day) %>
And then in application_helper.rb, you can have a function like this,
def check_for_leave(leave,d)
msg = ""
if leave.single_day? && leave.start_at.to_date == d
msg = "#{leave.start_at.strftime('%H:%M')} - #{leave.end_at.strftime('%H:%M')}"
elsif !leave.single_day?
if leave.start_at.to_date == d
msg = "From #{leave.start_at.strftime('%H:%M')}"
elsif leave.end_at.to_date == d
msg = "Until #{leave.end_at.strftime('%H:%M')}"
else
msg = "All Day"
end
return msg
end
In html.erb file
<% #dates.each do |d| %>
<h5><%= d.strftime("%A %d %b") %></h5>
<% #leave = Leave.where('(end_at >= ?', d.beginning_of_day) %>
<% if #leave.any? %>
<ul>
<% #leave.each do |leave| %>
<li>
<label class="label label-danger">
<%= check_for_leave(leave, d) %>
</label>
<%= leave.user.name %>
</li>
<% end %>
</ul>
<br/>
<span class="label label-success" style="margin-right: 10px;">
<span class="glyphicon glyphicon-ok"></span>
</span>
<%= current_account.users.active.where.not(id: #leave.map(&:user_id)).count %> Available
<% else %>
<span class="label label-success" style="margin-right: 10px;">
<span class="glyphicon glyphicon-ok"></span>
</span>
<%= current_account.users.active.count %> Available
<% end %>
<br />
<br />
<% end %>
Related
I have a simple application which made with Rails 5 and I'm using sunspot solr for facet searching, everything is OK but facet not working my code is below:
model.rb
searchable do
text :full_name, :interested_topics,:interested_job, :city, :email, :username, :publish_month
text :city
time :created_at
string :publish_month
string :interested_job
end
def publish_month
created_at.strftime("%B %Y")
end
def full_name
first_name + ' ' + last_name
end
controller.rb
#search = User.search do |searcher|
fields = [:full_name, :interested_topics, :interested_job, :city, :email, :username, :publish_month]
cities = [:city]
searcher.any do
fulltext params[:search], :fields => fields
fulltext params[:city], :fields => cities
end
searcher.with(:created_at).less_than(Time.zone.now)
searcher.with(:publish_month, params[:month]) if params[:month].present?
searcher.with(:interested_job, params[:position]) if params[:position].present?
searcher.paginate(:page => params[:page], :per_page => 15)
end
#users = #search.results
index.html.erb
<div id="facets">
<%= render partial: "filter" %>
</div>
index.js.erb
$('#facets').html('<%= escape_javascript(render("filter")) %>');
_filter.html.erb
<h4>Browse by Publish</h4>
<ul class="list-group">
<% for row in #search.facet(:publish_month).rows -%>
<li class="list-group-item">
<input type="checkbox" class="facet-check-box-month" name="month" value="<%= row.value %>" <%= params[:month] == row.value ? "checked" : "" %>>
<%= row.value %>
(<%= row.count %>)
</li>
<% end -%>
</ul>
<h4>Browse by Interest</h4>
<ul class="list-group">
<% for row in #search.facet(:interested_job).rows -%>
<li class="list-group-item">
<input type="checkbox" class="facet-check-box-position" name="position" value="<%= row.value %>" <%= params[:position] == row.value ? "checked" : "" %>>
<%= row.value %>
(<%= row.count %>)
</li>
<% end -%>
</ul>
Checkbox showing well for facet but when I clicking than not querying.
What I'm doing wrong?
Thanks in advance.
You have missed facet calling like on the controller you can add that two lines into User block above the last line like searcher.paginate(:page => params[:page], :per_page => 15)
searcher.facet(:publish_month)
searcher.facet(:interested_job)
Then restart your sunspot:solr server, I think it will work.
For more nicer, on the filter partial use unless #search.nil? for when not found any results than not will show the checkbox like after modified
<% unless #search.nil? %>
<h4>Browse by Publish</h4>
<ul class="list-group">
<% for row in #search.facet(:publish_month).rows -%>
<li class="list-group-item">
<input type="checkbox" class="facet-check-box-month" name="month" value="<%= row.value %>" <%= params[:month] == row.value ? "checked" : "" %>>
<%= row.value %>
(<%= row.count %>)
</li>
<% end -%>
</ul>
<h4>Browse by Interest</h4>
<ul class="list-group">
<% for row in #search.facet(:interested_job).rows -%>
<li class="list-group-item">
<input type="checkbox" class="facet-check-box-position" name="position" value="<%= row.value %>" <%= params[:position] == row.value ? "checked" : "" %>>
<%= row.value %>
(<%= row.count %>)
</li>
<% end -%>
</ul>
<% end %>
Hope it helps
For example I have this file:
_goal.html.erb
<table>
<tr>
<%= goal.name %>
<span class="label label-info"><%= goal.deadline.strftime("%d %b %Y") %></span>
</tr>
</table>
It is being rendered from the home page:
<h1><b>Goals</b></h1>
<%= render #unaccomplished_goals %>
<%= render #accomplished_goals %>
<% end %>
How can we wrap an accomplished goal with <span class="label label-info-success"> but if it is an unaccomplished goal keep it <span class="label label-info">?
In the controller:
#accomplished_goals = current_user.goals.accomplished
#unaccomplished_goals = current_user.goals.unaccomplished
Here was my latest attempt, which just made them all -info:
<% if #unaccomplished_goals == true %>
<span class="label label-info"><%= goal.deadline.strftime("%d %b %Y") %></span>
<% else #accomplished_goals == true %>
<span class="label label-warning"><%= goal.deadline.strftime("%d %b %Y") %></span>
<% end %>
Maybe you'll have more luck :)
Thank you so much.
Create a helper method that returns the correct classes for the goal's status. In application_helper.rb:
def deadline_label_class(goal)
if goal.accomplished?
'label label-info'
else
'label label-warning'
end
end
This assumes that Goal has an instance method called accomplished? which returns true/false. You may have to write that method if it doesn't exist or use some other criteria.
Then use the helper in the _goal.html.erb template:
<table>
<tr>
<%= goal.name %>
<span class="<%= deadline_label_class(goal) %>">
<%= goal.deadline.strftime("%d %b %Y") %>
</span>
</tr>
</table>
I have the following code:
<span class="bookings">
<span class="col-md-2">
<h4><%= time_tag(Date.today + 1.days) %></h4>
<% #booking.each do |b| %>
<% if b.date == Date.today + 1.days && b.type == "Hot Desk" %>
<% if b.desk == #hotdesk.code %>
<span class="glyphicon glyphicon-remove booked-show"></span>
<% end %>
<% end %>
<% end %>
</span>
</span>
<span class="bookings">
<span class="col-md-2">
<h4><%= time_tag(Date.today + 2.days) %></h4>
<% #booking.each do |b| %>
<% if b.date == Date.today + 2.days && b.type == "Hot Desk" %>
<% if b.desk == #hotdesk.code %>
<span class="glyphicon glyphicon-remove booked-show"></span>
<% end %>
<% end %>
<% end %>
</span>
</span>
Which extends on to however many days I want to display availability of bookings for. What I would like to achieve is writing only one of these blocks of codes out and having it loop through where it says Date.today + 1.days and increase the value of the days by 1 each loop up to 20 or so times.
Any ideas on a way to do this to save me writing this code over and over again?
<span class="bookings">
<% 1.upto(YOUR_COUNT.to_i).each do |day_count| %>
<span class="col-md-2">
<h4><%= time_tag(Date.today + day_count.days) %></h4>
<% #booking.each do |b| %>
<% if b.date == Date.today + day_count.days && b.type == "Hot Desk" %>
<% if b.desk == #hotdesk.code %>
<span class="glyphicon glyphicon-remove booked-show"></span>
<% end %>
<% end %>
<% end %>
</span>
<% end %>
</span>
I have the following Code on a partial that dynamically generates a list of associated steps to a pin. Both pins and steps have image(s). Users are able to add multiple steps to a pin and then this view dynamically generates a view of these steps. For each step there are associated image(s) which I'd like to pop-up as a modal. The challenge is I keep getting the following error:
"undefined local variable or method `step' for #<#:0x00000102f498d8>"
When I stub out rendering the partial, the modal appears basically blank but works. Any ideas How do I do this?
<div class="col-md-6">
<% (0..(Step.where("pin_id = ?", params[:id]).count)-1).each do |step| %>
<div class="col-md-12">
<div class="well">
<ul class="nav pull-right">
<% if current_user == #pin.user %>
<%= link_to edit_step_path((Step.where("pin_id = ?", params[:id]).fetch(step)), :pin_id => #pin.id) do %>
<span class="glyphicon glyphicon-edit"></span>
Edit
<% end %> |
<%= link_to Step.where("pin_id = ?", params[:id]).fetch(step), method: :delete, data: { confirm: 'Are you sure?' } do %>
<span class="glyphicon glyphicon-trash"></span>
Delete
<% end %> |
<%= link_to new_step_image_path(:step_id => Step.where("pin_id = ?", params[:id]).fetch(step), :pin_id => #pin.id) do %>
Add
<span class="glyphicon glyphicon-picture"></span>
<% end %>
<% end %>
<% if StepImage.where("step_id = ?", Step.where("pin_id = ?", params[:id]).pluck(:id).fetch(step)).count == 0 %>
<% else %>
| <a href="#StepImageModal" data-toggle="modal">
<span class="glyphicon glyphicon-picture"></span> (<%= StepImage.where("step_id = ?", Step.where("pin_id = ?", params[:id]).pluck(:id).fetch(step)).count %> ) </strong>
</a>
<% end %>
</ul>
<strong> Step <%= step+1 %>
<p>
<%= Step.where("pin_id = ?", params[:id]).pluck(:description).fetch(step) %>
</p>
</div>
</div>
<%end %>
</div>
<div class="modal fade" id="StepImageModal">
<div class="modal-header">
<a class="close" data-dismiss="modal">×</a>
<h3>Modal Header</h3>
</div>
<div class="modal-body">
<%= render :partial => 'pins/step_images',
:locals => { :step => step } %>
</div>
<div class="modal-footer">
Close
</div>
</div>
I don't get what you're trying to do here
Loop
As mentioned in the comments, you've got a loop which goes through your steps. However, outside the loop, you want to display the partial
The solution to your woes will either be to set an instance variable (not desired), or use another persistent data type. I'd do this:
#app/controllers/steps_controller.rb
def action
#step = {}
end
#app/views/steps/action.html.erb
<% (0..(Step.where("pin_id = ?", params[:id]).count)-1).each do |step| %>
<% #step[step.id.to_sym] = step.details %>
<% end %>
<%= render :partial => 'pins/step_images', :locals => { :step => #step } %>
unless
Some refactoring for you:
<% unless StepImage.where("step_id = ?", Step.where("pin_id = ?", params[:id]).pluck(:id).fetch(step)).count == 0 %>
| <%= link_to "#StepImageModal", data: { toggle: "modal"} do %>
<span class="glyphicon glyphicon-picture"></span>(<%= StepImage.where("step_id = ?", Step.where("pin_id = ?", params[:id]).pluck(:id).fetch(step)).count %> ) </strong>
<% end %>
<% end %>
I have a problem with my each loop. The line that prints programdetail.name and programdetail.bodypart doesn't print the value. Also do you know how can I make this loop a little bit more efficient? I want to print first 2 items with class "odd" and the other 2 with non-class. So and so forth.
<% #counter = 0 %>
<% #program.programdetails.each do |programdetail| %>
<% #counter = #counter + 1 %>
<% #counter = #counter % 3 %>
<% if (#counter == 0)
#counter -= 1
end %>
<%= '<h3 class="odd"><span class="moduleLabel"> #{programdetail.name}</span><span class="moduleDescription">#{programdetail.bodypart}</span></h3>' if #counter != 0 %>
<%= '<h3><span class="moduleLabel">#{programdetail.name}</span><span class="moduleDescription">#{programdetail.bodypart}</span></h3>' if #counter != 0 %>
<% end %>
cycle helper could have worked, if you wanted odd/even combo, or over a collection:
<% #program.programdetails.each do |programdetail| %>
<h3 class="<%= cycle("odd", "odd", "", "") %>
<span class="moduleLabel"><%= programdetail.name %></span>
<span class="moduleDescription"><%= programdetail.bodypart %></span>
</h3>
<% end %>
To fix your code:
<% #counter = 0 %>
<% #program.programdetails.each do |programdetail| %>
<% #counter = (#counter % 4) + 1 %>
<h3 class="<%= ((1..2).cover?(#counter))? 'odd': '' %>">
<span class="moduleLabel"><%= programdetail.name %></span>
<span class="moduleDescription"><%= programdetail.bodypart %></span>
</h3>
<% end %>