Commit f3b286ef authored by Tyler R Lemburg's avatar Tyler R Lemburg
Browse files

Download links for .ICS for reservations and events

Also includes various bugfixes
parent 3e1e6cb3
......@@ -11,6 +11,7 @@ gem 'unicorn'
gem 'pony'
gem 'rest-client'
gem 'rack-cas'
gem 'icalendar'
group :development do
gem 'shotgun'
......
......@@ -44,6 +44,7 @@ GEM
http-cookie (1.0.2)
domain_name (~> 0.5)
i18n (0.7.0)
icalendar (2.4.1)
json (1.8.3)
kgio (2.10.0)
less (2.6.0)
......@@ -138,6 +139,7 @@ DEPENDENCIES
bcrypt
guard
guard-less
icalendar
mysql
pony
rack-cas
......
......@@ -22,7 +22,7 @@ Using local resources
Quick Tutorial
==============
1. Service spaces refer to different silos of the University that will utilize resources. E.g. the math department, the Honors program, or University Communications.
1. Service spaces refer to different silos of the University that will utilize resources. E.g. the math department, the Honors program, or University Communication.
2. Super Admins of a space can do anything, including giving others access and privileges to the space.
3. Resources are created, and then may be reserved by anyone who has the User Access privilege in the space.
4. Events *may* include a resource reservation but do not have to.
......
......@@ -69,4 +69,21 @@ class Event < ActiveRecord::Base
self.imagedata = nil
self.save
end
def to_ics
calendar = Icalendar::Calendar.new
ical = Icalendar::Event.new
ical.dtstart = self.start_time.in_time_zone.strftime("%Y%m%dT%H%M%S")
ical.dtend = self.end_time.in_time_zone.strftime("%Y%m%dT%H%M%S")
ical.summary = self.title
ical.description = self.description
ical.location = self.location.name
ical.uid = "unl_resource_scheduler_#{ENV['RACK_ENV']}_event_#{self.id}"
calendar.add_event(ical)
calendar.to_ical
end
def download_link
"/#{service_space.url_name}/events/#{id}/event.ics"
end
end
\ No newline at end of file
require 'active_record'
require 'models/resource'
require 'icalendar'
class Reservation < ActiveRecord::Base
belongs_to :resource
......@@ -25,4 +26,21 @@ class Reservation < ActiveRecord::Base
end
((end_time - start_time) / 60).to_i
end
def to_ics
calendar = Icalendar::Calendar.new
ical = Icalendar::Event.new
ical.dtstart = self.start_time.in_time_zone.strftime("%Y%m%dT%H%M%S")
ical.dtend = self.end_time.in_time_zone.strftime("%Y%m%dT%H%M%S")
ical.summary = self.title
ical.description = self.description
ical.location = self.resource.name
ical.uid = "unl_resource_scheduler_#{ENV['RACK_ENV']}_reservation_#{self.id}"
calendar.add_event(ical)
calendar.to_ical
end
def download_link
"/#{resource.service_space.url_name}/resources/#{resource.id}/reservation/#{id}/reservation.ics"
end
end
\ No newline at end of file
......@@ -6,6 +6,7 @@ require 'models/resource_field'
require 'models/resource_field_data'
class Resource < ActiveRecord::Base
belongs_to :service_space
has_many :reservations, dependent: :destroy
has_many :resource_approvers, dependent: :destroy
has_many :resource_authorizations, dependent: :destroy
......
This diff is collapsed.
......@@ -72,9 +72,9 @@ post '/:service_space_url_name/admin/events/create/?' do
end
event = Event.new
event.service_space_id = @space.id
event.set_image_data(params)
event.set_data(params)
event.service_space_id = @space.id
if params.has_key?('reserve_resource') && params['reserve_resource'] == 'on'
# we need to create a reservation for the resource on the appropriate time
......
......@@ -3,6 +3,7 @@ require 'models/space_hour'
get '/:service_space_url_name/calendar/?' do
load_service_space
check_login
@breadcrumbs << {:text => "#{@space.name} Calendar"}
......
......@@ -55,6 +55,19 @@ post '/:service_space_url_name/events/:event_id/sign_up/?' do
end
end
get '/:service_space_url_name/events/:event_id/event.ics' do
require_login
load_service_space
event = Event.find_by(:service_space_id => @space.id, :id => params[:event_id])
if event.nil?
raise Sinatra::NotFound
end
attachment "#{event.title}.ics"
event.to_ics
end
post '/:service_space_url_name/events/:event_id/remove_signup/?' do
require_login
load_service_space
......@@ -67,7 +80,7 @@ post '/:service_space_url_name/events/:event_id/remove_signup/?' do
if signup.nil?
flash :alert, 'Not Found', 'That signup was not found.'
redirect '/home/'
redirect "#{params[:service_space_url_name]}"
end
signup.delete
......
......@@ -442,7 +442,6 @@ post '/:service_space_url_name/resources/:resource_id/reserve/?' do
redirect "/#{@space.url_name}/resources/#{resource.id}/calendar/#{params[:kiosk_mode] ? '?kiosk_mode=true' : ''}"
end
get '/:service_space_url_name/resources/:resource_id/edit_reservation/:reservation_id/?' do
require_login
load_service_space
......@@ -658,4 +657,20 @@ post '/:service_space_url_name/resources/:resource_id/cancel_all/:recurring_refe
redirect back
end
get '/:service_space_url_name/resources/:resource_id/reservation/:reservation_id/reservation.ics' do
require_login
load_service_space
resource = Resource.find_by(:service_space_id => @space.id, :id => params[:resource_id])
if resource.nil?
raise Sinatra::NotFound
end
reservation = Reservation.find_by(:resource_id => resource.id, :id => params[:reservation_id])
if reservation.nil?
raise Sinatra::NotFound
end
attachment "#{reservation.title}.ics"
reservation.to_ics
end
......@@ -23,6 +23,10 @@
float: right;
}
.wdn-button-small {
font-size: 80%;
}
.tooltip {
> div {
position: absolute;
......@@ -127,7 +131,7 @@
display: none;
text-align: center;
font-size: 0.85em;
line-height: 1.6em;
line-height: 1.3em;
position: absolute;
font-size: .8125rem;
ul li {
......@@ -222,13 +226,9 @@ label.day-header {
position: relative;
z-index: 1;
background-color: #d8d8d8;
<<<<<<< HEAD
padding: .5em 30px 0 5em;
=======
padding: .5em 46px 0 10%;
@media only screen and (min-width : 900px) {padding: .5em 46px 0 7.5%;}
@media only screen and (min-width : 1200px) {padding: .5em 46px 0 5%;}
>>>>>>> e7707fbcac10915ccb82fe9215a45a3d672b3168
}
.calendar {
......
......@@ -14,14 +14,6 @@ EIGHT_PM_MINUTES = 1200 # end time of calendar
</h3>
</div>
<!-- <div style="margin-bottom: 16px;">
<h4 style="text-align: center; margin: 0;">
<%= month = sunday.strftime('%B %Y') %><%= (month2 = (sunday+6.days).strftime('%B %Y')) == month ? '' : " - #{month2}" %>
</h4>
<a href="/<%= @space.url_name %>/calendar/?date=<%= (date-7.days).strftime('%Y-%m-%d') %>" class="wdn-button wdn-button-triad" id="prev-week">&lt; PREV</a>
<a href="/<%= @space.url_name %>/calendar/?date=<%= (date+7.days).strftime('%Y-%m-%d') %>" class="wdn-button wdn-button-triad" style="float: right;" id="next-week">NEXT &gt;</a>
</div> -->
<div class="calendar">
<div class="calendar-header">
<a href="/<%= @space.url_name %>/calendar/?date=<%= (date-7.days).strftime('%Y-%m-%d') %><%= defined?(kiosk_mode) && kiosk_mode == 'true' ? '&kiosk_mode=true' : ''%>" id="prev-week" class="schedulericon-angle-circled-left"><span class="wdn-text-hidden">Previous Week</span></a>
......@@ -41,7 +33,7 @@ EIGHT_PM_MINUTES = 1200 # end time of calendar
<div class="time-chart">
<% (12..39).each do |j| %>
<div class="calendar-half-hour">
<label><%= "#{(j / 2) % 12 + (j==24?12:0)} #{j>=24?'PM':'AM'}" if j % 2 == 0 %></label>
<label><%= "#{(j / 2) % 12 + (j==24 ? 12 : 0)} #{j>=24 ? 'PM': 'AM'}" if j % 2 == 0 %></label>
</div>
<% end %>
</div>
......@@ -165,8 +157,8 @@ EIGHT_PM_MINUTES = 1200 # end time of calendar
<div class="tooltip <%= top >= 50 ? "hang-above" : "hang-below" %> <%= day.strftime("%^a") == "FRI" ? "hang-left" : "hang-right" %>">
<div>
<h6 style="margin-top: 0px; margin-bottom: .25em;"><%= res.title ? (res.title.empty? ? 'Reserved' : res.title) : 'Reserved' %></h6>
<p class="eventicon-clock"><%= res.start_time.in_time_zone.strftime('%I:%M %p') %> - <%= res.end_time.in_time_zone.strftime('%I:%M %p') %></p>
<p>Reserved by: <span class="italic"><%= res.user.full_name rescue nil %></span></p>
<p style="margin-bottom: 10px;" class="eventicon-clock"><%= res.start_time.in_time_zone.strftime('%I:%M %p') %> - <%= res.end_time.in_time_zone.strftime('%I:%M %p') %></p>
<p style="margin-bottom: 10px;"><a href="<%= res.info_link %>"" class="wdn-button wdn-button-brand wdn-button-small">View</a> <a href="<%= res.download_link %>" class="download-ics wdn-button wdn-button-triad wdn-button-small">Download</a></p>
<div class="close"><a href="#">&times;</a></div>
</div>
</div>
......@@ -207,11 +199,6 @@ require(['jquery', '/js/functions.js', '/js/jquery.mousewheel.min.js', '/js/jque
if($tooltip.hasClass("hang-below")){
$tooltip.css("margin-bottom", ($tooltip.find("div").height()+35)*-1);
}
$(document).one("click",function(){
$tooltip.show().hide();
$eventContainer.css('z-index', closedZ);
})
});
$('.tooltip div.close a').click(function (click) {
......@@ -228,7 +215,7 @@ require(['jquery', '/js/functions.js', '/js/jquery.mousewheel.min.js', '/js/jque
},
setTop: "95px"
}
);
);
});
function tick(){
......
......@@ -38,14 +38,14 @@
<% elsif @user %>
<% # the user is logged in but not signed up %>
<% if event.max_signups.nil? || event.signups.count < event.max_signups %>
<form action="/<%= @space.url_name %>/events/<%= event.id %>/sign_up/" method="POST">
<form action="/<%= @space.url_name %>/events/<%= event.id %>/sign_up/" class="delete-form" method="POST">
<button type="submit" class="wdn-button wdn-button-brand">
<% if event.type.description == 'Free Event' %>
Note event on my homepage
<% else %>
Sign up for this event
<% end %>
</a>
</button>
</form>
<% else %>
All slots for this event are filled.
......@@ -54,9 +54,10 @@
<% # a non user. May still sign up for the event UNLESS it is a tool training %>
<% if event.type.description != 'Machine Training' %>
<% if event.max_signups.nil? || event.signups.count < event.max_signups %>
<a class="wdn-button wdn-button-brand" href="/<%= @space.url_name %>/events/<%= event.id %>/sign_up_as_non_member/">Sign up for this event</a>
<a class="wdn-button wdn-button-brand" href="/<%= @space.url_name %>/events/<%= event.id %>/sign_up_as_non_member/">Sign up for this event</a>
<% else %>
All slots for this event are filled.
<% end %>
<% end %>
<% end %>
\ No newline at end of file
<% end %>
<a href="<%= event.download_link %>" class="download-ics wdn-button wdn-button-triad">Download</a>
\ No newline at end of file
......@@ -47,7 +47,7 @@ EIGHT_PM_MINUTES = 1200 # end time of calendar
<div class="time-chart">
<% (12..39).each do |j| %>
<div class="calendar-half-hour">
<label><%= "#{(j / 2) % 12 + (j==24?12:0)} #{j>=24? 'PM':'AM'}" if j % 2 == 0 %></label>
<label><%= "#{(j / 2) % 12 + (j==24?12:0)} #{j >= 24 ? 'PM' : 'AM'}" if j % 2 == 0 %></label>
</div>
<% end %>
</div>
......@@ -171,8 +171,9 @@ EIGHT_PM_MINUTES = 1200 # end time of calendar
<div class="tooltip <%= top >= 50 ? "hang-above" : "hang-below" %> <%= day.strftime("%^a") == "FRI" ? "hang-left" : "hang-right" %>">
<div>
<h6 style="margin-top: 0px; margin-bottom: .25em;"><%= res.title ? (res.title.empty? ? 'Reserved' : res.title) : 'Reserved' %></h6>
<p class="eventicon-clock"><%= res.start_time.in_time_zone.strftime('%I:%M %p') %> - <%= res.end_time.in_time_zone.strftime('%I:%M %p') %></p>
<p>Reserved by: <span class="italic"><%= res.user.full_name rescue nil %></span></p>
<p style="margin-bottom: 10px;" class="eventicon-clock"><%= res.start_time.in_time_zone.strftime('%I:%M %p') %> - <%= res.end_time.in_time_zone.strftime('%I:%M %p') %><br>
Reserved by: <span class="italic"><%= res.user.full_name rescue nil %></span></p>
<p style="margin-bottom: 10px;"><a href="<%= res.download_link %>" class="download-ics wdn-button wdn-button-triad wdn-button-small">Download</a></p>
<div class="close"><a href="#">&times;</a></div>
</div>
</div>
......@@ -210,14 +211,10 @@ require(['jquery', '/js/functions.js', '/js/jquery.mousewheel.min.js', '/js/jque
var $tooltip = $(this).next(".tooltip");
$tooltip.show();
if($tooltip.hasClass("hang-below")){
if ($tooltip.hasClass("hang-below")){
$tooltip.css("margin-bottom", ($tooltip.find("div").height()+35)*-1);
}
$(document).one("click",function(){
$tooltip.show().hide();
$eventContainer.css('z-index', closedZ);
})
});
$('.tooltip div.close a').click(function (click) {
......
......@@ -34,6 +34,7 @@ You have no upcoming reservations. You can view upcoming trainings to get certif
<%= reservation.length %> minutes
</td>
<td class="table-actions">
<a href="<%= reservation.download_link %>" class="wdn-button wdn-button-triad">Download</a>
<a href="/<%= @space.url_name %>/resources/<%= reservation.resource.id %>/edit_reservation/<%= reservation.id %>/" class="wdn-button wdn-button-brand">Edit</a>
<form method="POST" action="/<%= @space.url_name %>/resources/<%= reservation.resource.id %>/cancel/<%= reservation.id %>/" class="delete-form">
<button class="wdn-button" type="submit">Remove</button>
......@@ -109,7 +110,8 @@ You have not signed up for any upcoming events. Why not check out the calendar t
<%= event.location.name %>
</td>
<td class="table-actions">
<form action="/events/<%= event.id %>/remove_signup/" method="POST" class="delete-form">
<a href="<%= event.download_link %>" class="wdn-button wdn-button-triad">Download</a>
<form action="/<%= @space.url_name %>/events/<%= event.id %>/remove_signup/" method="POST" class="delete-form">
<button class="wdn-button" type="submit">
Remove
</button>
......
......@@ -2,7 +2,7 @@
<div class="bp960-wdn-col-two-thirds">
<div class="wdn-footer-module">
<span role="heading" class="wdn-footer-heading">About UNL Resource Scheduler</span>
This application is developed and maintained by <a href="http://iim.unl.edu">Internet and Interactive Media (IIM)</a>, which is a partnership with University Communications and Information Technology Services.
This application is developed and maintained by <a href="http://iim.unl.edu">Internet and Interactive Media (IIM)</a>, which is a partnership with University Communication and Information Technology Services.
</div>
</div>
<div class="bp960-wdn-col-one-third">
......@@ -11,7 +11,7 @@
<ul class="wdn-related-links-v1">
<li><a href="http://wdn.unl.edu/">Web Developer Network</a></li>
<li><a href="http://iim.unl.edu/">Internet and Interactive Media</a></li>
<li><a href="http://ucomm.unl.edu/">University Communications</a></li>
<li><a href="http://ucomm.unl.edu/">University Communication</a></li>
<li><a href="http://its.unl.edu/">Information Technology Services</a></li>
</ul>
</div>
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment