viewable 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.editorconfig +10 -0
- data/.gitignore +27 -0
- data/.travis.yml +22 -0
- data/AUTHORS.md +6 -0
- data/CONTRIBUTING.md +22 -0
- data/Gemfile +7 -0
- data/LICENSE.md +23 -0
- data/README.md +41 -0
- data/Rakefile +6 -0
- data/lib/viewable/generators/viewable/controller_generator.rb +21 -0
- data/lib/viewable/generators/viewable/css_generator.rb +11 -0
- data/lib/viewable/generators/viewable/install_generator.rb +15 -0
- data/lib/viewable/generators/viewable/js_generator.rb +16 -0
- data/lib/viewable/generators/viewable/resource_model_generator.rb +20 -0
- data/lib/viewable/generators/viewable/templates/assets/javascript/calendar-editable.js +6991 -0
- data/lib/viewable/generators/viewable/templates/assets/javascript/custom.js +130 -0
- data/lib/viewable/generators/viewable/templates/assets/javascript/fullcalendar.js +6110 -0
- data/lib/viewable/generators/viewable/templates/assets/stylesheets/custom.css +24 -0
- data/lib/viewable/generators/viewable/templates/assets/stylesheets/fullcalendar.css +587 -0
- data/lib/viewable/generators/viewable/templates/controllers/resource_controller.rb +50 -0
- data/lib/viewable/generators/viewable/templates/controllers/viewing_controller.rb +77 -0
- data/lib/viewable/generators/viewable/templates/models/datetime.rb +5 -0
- data/lib/viewable/generators/viewable/templates/models/resource.rb +4 -0
- data/lib/viewable/generators/viewable/templates/models/viewable.rb +85 -0
- data/lib/viewable/generators/viewable/templates/models/viewing.rb +4 -0
- data/lib/viewable/generators/viewable/templates/views/_errors.html.erb +13 -0
- data/lib/viewable/generators/viewable/templates/views/_form.html.erb +6 -0
- data/lib/viewable/generators/viewable/templates/views/edit.html.erb +1 -0
- data/lib/viewable/generators/viewable/templates/views/index.html.erb +11 -0
- data/lib/viewable/generators/viewable/templates/views/new.html.erb +1 -0
- data/lib/viewable/generators/viewable/templates/views/viewings/_errors.html.erb +12 -0
- data/lib/viewable/generators/viewable/templates/views/viewings/_form.html.erb +11 -0
- data/lib/viewable/generators/viewable/templates/views/viewings/edit.html.erb +9 -0
- data/lib/viewable/generators/viewable/templates/views/viewings/index.html.erb +22 -0
- data/lib/viewable/generators/viewable/templates/views/viewings/new.html.erb +9 -0
- data/lib/viewable/generators/viewable/templates/views/viewings/show.html.erb +6 -0
- data/lib/viewable/generators/viewable/viewing_model_generator.rb +25 -0
- data/lib/viewable/generators/viewable/views_generator.rb +20 -0
- data/lib/viewable/railtie.rb +7 -0
- data/lib/viewable/version.rb +3 -0
- data/lib/viewable/viewable.rb +2 -0
- data/viewable.gemspec +30 -0
- metadata +148 -0
@@ -0,0 +1,50 @@
|
|
1
|
+
class <%=resource_name_camelize.singularize.pluralize%>Controller < ApplicationController
|
2
|
+
|
3
|
+
def index
|
4
|
+
@<%=resource_name_underscore.pluralize%> = <%=resource_name_camelize.singularize%>.all
|
5
|
+
end
|
6
|
+
|
7
|
+
def new
|
8
|
+
@<%=resource_name_underscore.singularize%> = <%=resource_name_camelize.singularize%>.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def create
|
12
|
+
@<%=resource_name_underscore.singularize%> = <%=resource_name_camelize.singularize%>.create(<%=resource_name_underscore.singularize%>_params)
|
13
|
+
if @<%=resource_name_underscore.singularize%>.save
|
14
|
+
name = @<%=resource_name_underscore.singularize%>.name
|
15
|
+
redirect_to <%=resource_name_underscore.pluralize%>_path
|
16
|
+
flash[:notice] = "#{name} created"
|
17
|
+
else
|
18
|
+
render 'new'
|
19
|
+
flash[:error] = "Unable to create <%=resource_name_underscore.singularize.gsub(/(_)/, ' ')%>. Please try again"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def destroy
|
24
|
+
@<%=resource_name_underscore.singularize%> = <%= resource_name_camelize.singularize%>.find(params[:id])
|
25
|
+
@<%=resource_name_underscore.singularize%>.destroy
|
26
|
+
redirect_to <%=resource_name_underscore.pluralize%>_path
|
27
|
+
end
|
28
|
+
|
29
|
+
def edit
|
30
|
+
@<%=resource_name_underscore.singularize%> = <%=resource_name_camelize.singularize%>.find(params[:id])
|
31
|
+
end
|
32
|
+
|
33
|
+
def update
|
34
|
+
@<%=resource_name_underscore.singularize%> = <%=resource_name_camelize.singularize%>.find(params[:id])
|
35
|
+
@<%=resource_name_underscore.singularize%>.update <%=resource_name_underscore.singularize%>_params
|
36
|
+
if @<%=resource_name_underscore.singularize%>.save
|
37
|
+
flash[:notice] = "Your <%=resource_name_underscore.singularize.gsub(/(_)/, ' ')%> was updated succesfully"
|
38
|
+
redirect_to root_path
|
39
|
+
else
|
40
|
+
render 'edit'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def <%=resource_name_underscore.singularize%>_params
|
47
|
+
params.require(:<%=resource_name_underscore.singularize%>).permit(:name, :delete)
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
class ViewingsController < ApplicationController
|
2
|
+
respond_to :html, :xml, :json
|
3
|
+
|
4
|
+
before_action :find_<%=resource_name_underscore.singularize%>
|
5
|
+
|
6
|
+
def index
|
7
|
+
@viewings = Viewing.where("<%=resource_name.singularize%>_id = ? AND end_time >= ?", @<%=resource_name.singularize%>.id, Time.now).order(:start_time)
|
8
|
+
respond_with @viewings
|
9
|
+
end
|
10
|
+
|
11
|
+
def new
|
12
|
+
@viewing = Viewing.new(<%=resource_name.singularize%>_id: @<%=resource_name.singularize%>.id)
|
13
|
+
end
|
14
|
+
|
15
|
+
def create
|
16
|
+
@viewing = Viewing.new(params[:viewing].permit(:<%=resource_name.singularize%>_id, :start_time, :length))
|
17
|
+
@viewing.<%=resource_name.singularize%> = @<%=resource_name.singularize%>
|
18
|
+
if @viewing.save
|
19
|
+
redirect_to <%=resource_name.singularize%>_viewings_path(@<%=resource_name.singularize%>, method: :get)
|
20
|
+
else
|
21
|
+
render 'new'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def show
|
26
|
+
@viewing = Viewing.find(params[:id])
|
27
|
+
end
|
28
|
+
|
29
|
+
def destroy
|
30
|
+
@viewing = Viewing.find(params[:id]).destroy
|
31
|
+
if @viewing.destroy
|
32
|
+
flash[:notice] = "Viewing: #{@viewing.start_time.strftime('%e %b %Y %H:%M%p')} to #{@viewing.end_time.strftime('%e %b %Y %H:%M%p')} deleted"
|
33
|
+
redirect_to <%=resource_name.singularize%>_viewings_path(@<%=resource_name.singularize%>)
|
34
|
+
else
|
35
|
+
render 'index'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def edit
|
40
|
+
@viewing = Viewing.find(params[:id])
|
41
|
+
end
|
42
|
+
|
43
|
+
def update
|
44
|
+
@viewing = Viewing.find(params[:id])
|
45
|
+
# @viewing.<%=resource_name%> = @<%=resource_name%>
|
46
|
+
|
47
|
+
if @viewing.update(params[:viewing].permit(:<%=resource_name.singularize%>_id, :start_time, :length))
|
48
|
+
flash[:notice] = 'Your viewing was updated succesfully'
|
49
|
+
|
50
|
+
if request.xhr?
|
51
|
+
render json: {status: :success}.to_json
|
52
|
+
else
|
53
|
+
redirect_to <%=resource_name.singularize%>_viewings_path(@<%=resource_name.singularize%>)
|
54
|
+
end
|
55
|
+
else
|
56
|
+
render 'edit'
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def save viewing
|
63
|
+
if @viewing.save
|
64
|
+
flash[:notice] = 'viewing added'
|
65
|
+
redirect_to <%=resource_name.singularize%>_viewing_path(@<%=resource_name.singularize%>, @viewing)
|
66
|
+
else
|
67
|
+
render 'new'
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def find_<%=resource_name.singularize%>
|
72
|
+
if params[:<%=resource_name.singularize%>_id]
|
73
|
+
@<%=resource_name.singularize%> = <%=resource_name_camelize.singularize%>.find_by_id(params[:<%=resource_name.singularize%>_id])
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
module Viewable
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
included do
|
5
|
+
belongs_to :<%=resource_name_underscore.singularize%>
|
6
|
+
|
7
|
+
validates :start_time, presence: true
|
8
|
+
validates :length, presence: true, numericality: { greater_than: 0 }
|
9
|
+
validate :start_date_cannot_be_in_the_past
|
10
|
+
validate :overlaps
|
11
|
+
|
12
|
+
before_validation :calculate_end_time
|
13
|
+
|
14
|
+
|
15
|
+
scope :time_constraint, ->(c1, f1, c2, f2) do
|
16
|
+
return nil unless f1 && f2
|
17
|
+
where "%s ? AND %s ?" % [c1, c2], f1, f2
|
18
|
+
end
|
19
|
+
|
20
|
+
scope :end_during, ->(start_time, end_time) { time_constraint "end_time >", start_time, "end_time <", end_time }
|
21
|
+
scope :start_during, ->(start_time, end_time) { time_constraint "start_time >", start_time, "start_time <", end_time }
|
22
|
+
scope :happening_during, ->(start_time, end_time) { time_constraint "start_time >", start_time, "end_time <", end_time }
|
23
|
+
scope :enveloping, ->(start_time, end_time) { time_constraint "start_time <", start_time, "end_time >", end_time }
|
24
|
+
scope :identical, ->(start_time, end_time) { time_constraint "start_time =", start_time, "end_time =", end_time }
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
def overlaps
|
29
|
+
overlapping_viewings = [
|
30
|
+
<%=resource_name_underscore.singularize%>.viewings.end_during(start_time, end_time),
|
31
|
+
<%=resource_name_underscore.singularize%>.viewings.start_during(start_time, end_time),
|
32
|
+
<%=resource_name_underscore.singularize%>.viewings.happening_during(start_time, end_time),
|
33
|
+
<%=resource_name_underscore.singularize%>.viewings.enveloping(start_time, end_time),
|
34
|
+
<%=resource_name_underscore.singularize%>.viewings.identical(start_time, end_time)
|
35
|
+
].flatten
|
36
|
+
|
37
|
+
overlapping_viewings.delete self
|
38
|
+
if overlapping_viewings.any?
|
39
|
+
errors.add(:base, 'Slot has already been booked for viewing')
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def start_date_cannot_be_in_the_past
|
44
|
+
if start_time && start_time < DateTime.now + (15.minutes)
|
45
|
+
errors.add(:start_time, 'must be at least 15 minutes from present time')
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def calculate_end_time
|
50
|
+
start_time = validate_start_time
|
51
|
+
length = validate_length
|
52
|
+
if start_time && length
|
53
|
+
self.end_time = start_time + (length.hours - 60)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
def as_json(options = {})
|
59
|
+
{
|
60
|
+
:id => self.id,
|
61
|
+
:start => self.start_time,
|
62
|
+
:end => self.end_time + 60,
|
63
|
+
:recurring => false,
|
64
|
+
:allDay => false
|
65
|
+
}
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
def validate_start_time
|
71
|
+
if !self.start_time.nil?
|
72
|
+
start_time = self.start_time
|
73
|
+
else
|
74
|
+
return nil
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def validate_length
|
79
|
+
if !self.length.nil?
|
80
|
+
length = self.length.to_i
|
81
|
+
else
|
82
|
+
return nil
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<%% if @<%=viewable_views_name.singularize%>.errors.any? %>
|
2
|
+
<div class="errors">
|
3
|
+
<h3>
|
4
|
+
<%%= pluralize(@<%=viewable_views_name.singularize%>.errors.count, 'error') %>
|
5
|
+
prohibited this <%=viewable_views_name.singularize%> from being saved:
|
6
|
+
</h3>
|
7
|
+
<ul>
|
8
|
+
<%% @<%=viewable_views_name.singularize%>.errors.full_messages.each do |message| %>
|
9
|
+
<li><%%= message %></li>
|
10
|
+
<%% end %>
|
11
|
+
</ul>
|
12
|
+
</div>
|
13
|
+
<%% end %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%%= render 'form' %>
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<h3><%=viewable_views_name.pluralize.gsub(/(_)/,' ')%></h3>
|
2
|
+
|
3
|
+
<%% @<%=viewable_views_name.pluralize%>.each do |<%=viewable_views_name.singularize%>| %>
|
4
|
+
<div class="<%=viewable_views_name.singularize%>">
|
5
|
+
<%%= <%=viewable_views_name.singularize%>.name %>
|
6
|
+
<%%= link_to "Show all viewing", <%=viewable_views_name.singularize%>_viewings_path(<%=viewable_views_name.singularize%>) %>
|
7
|
+
<%%= link_to "Delete", <%=viewable_views_name.singularize%>_path(<%=viewable_views_name.singularize%>), data: { confirm: 'Are you sure?' }, method: :delete %>
|
8
|
+
<%%= link_to "Edit", edit_<%=viewable_views_name.singularize%>_path(<%=viewable_views_name.singularize%>) %>
|
9
|
+
<%%= link_to "Add viewing", new_<%=viewable_views_name.singularize%>_viewings_path(<%=viewable_views_name.singularize%>) %>
|
10
|
+
</div>
|
11
|
+
<%% end %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%%= render 'form' %>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<%% if @viewing.errors.any? %>
|
2
|
+
<div class="errors">
|
3
|
+
<h3><%%= pluralize(@viewing.errors.count, 'error') %>
|
4
|
+
prohibited this viewing from being saved:
|
5
|
+
</h3>
|
6
|
+
<ul>
|
7
|
+
<%% @viewing.errors.full_messages.each do |message| %>
|
8
|
+
<li><%%= message %></li>
|
9
|
+
<%% end %>
|
10
|
+
</ul>
|
11
|
+
</div>
|
12
|
+
<%% end %>
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<%%= form_for([@<%=viewable_views_name.singularize%>, @viewing]) do |f| %>
|
2
|
+
<p>
|
3
|
+
<%%= f.label 'start_time', 'Start time' %>
|
4
|
+
<%%= f.datetime_select :start_time, { minute_step: 15 } %>
|
5
|
+
</p>
|
6
|
+
<p>
|
7
|
+
<%%= f.label 'length', 'Length of viewing in hours' %>
|
8
|
+
<%%= f.number_field 'length', min: 1 %>
|
9
|
+
</p>
|
10
|
+
<%%= f.submit 'Submit' %>
|
11
|
+
<%% end %>
|
@@ -0,0 +1,22 @@
|
|
1
|
+
<h3> Viewings for <%%= @<%=viewable_views_name.singularize%>.name %></h3>
|
2
|
+
<table class="viewings_table">
|
3
|
+
<tr>
|
4
|
+
<th>Start</th>
|
5
|
+
<th>End</th>
|
6
|
+
</tr>
|
7
|
+
|
8
|
+
<%% @viewings.each do |viewing| %>
|
9
|
+
<tr>
|
10
|
+
<td>
|
11
|
+
<%%= viewing.start_time.strftime('%e %b %Y %H:%M%p') %>
|
12
|
+
</td>
|
13
|
+
<td>
|
14
|
+
<%%= (viewing.calculate_end_time + 60).strftime('%e %b %Y %H:%M%p') %>
|
15
|
+
</td>
|
16
|
+
<td><%%= link_to "Delete", <%=viewable_views_name.singularize%>_viewing_path(@<%=viewable_views_name.singularize%>, viewing), data: { confirm: 'Are you sure?' }, method: :delete %>
|
17
|
+
</td>
|
18
|
+
<td><%%= link_to "Edit", edit_<%=viewable_views_name.singularize%>_viewing_path(@<%=viewable_views_name.singularize%>, viewing) %>
|
19
|
+
</td>
|
20
|
+
</tr>
|
21
|
+
<%% end %>
|
22
|
+
</table>
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Viewable
|
2
|
+
module Generators
|
3
|
+
class ViewingModelGenerator < Rails::Generators::Base
|
4
|
+
source_root File.expand_path('../templates/models', __FILE__)
|
5
|
+
argument :resource_name, :type => :string, :default => "resource"
|
6
|
+
def generate_viewing_model
|
7
|
+
copy_file "viewing.rb", "app/models/viewing.rb"
|
8
|
+
template "viewable.rb", "app/models/concerns/viewable.rb"
|
9
|
+
end
|
10
|
+
def create_viewing_migration
|
11
|
+
generate "migration CreateViewings start_time:datetime end_time:datetime length:integer #{resource_name_underscore.singularize}:belongs_to"
|
12
|
+
end
|
13
|
+
def generate_datetime_initializer
|
14
|
+
copy_file "datetime.rb", "config/initializers/datetime.rb"
|
15
|
+
end
|
16
|
+
private
|
17
|
+
def resource_name_underscore
|
18
|
+
resource_name.underscore
|
19
|
+
end
|
20
|
+
def resource_name_camelize
|
21
|
+
resource_name.camelize
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Viewable
|
2
|
+
module Generators
|
3
|
+
class ViewsGenerator < Rails::Generators::Base
|
4
|
+
source_root File.expand_path('../templates/views', __FILE__)
|
5
|
+
argument :viewable_views_name, :type => :string, :default => "resources"
|
6
|
+
def generate_viewable_views
|
7
|
+
template "_errors.html.erb", "app/views/#{viewable_views_name.pluralize}/_errors.html.erb"
|
8
|
+
template "_form.html.erb", "app/views/#{viewable_views_name.pluralize}/_form.html.erb"
|
9
|
+
template "edit.html.erb", "app/views/#{viewable_views_name.pluralize}/edit.html.erb"
|
10
|
+
template "index.html.erb", "app/views/#{viewable_views_name.pluralize}/index.html.erb"
|
11
|
+
template "new.html.erb", "app/views/#{viewable_views_name.pluralize}/new.html.erb"
|
12
|
+
template "viewings/_errors.html.erb", "app/views/viewings/_errors.html.erb"
|
13
|
+
template "viewings/_form.html.erb", "app/views/viewings/_form.html.erb"
|
14
|
+
template "viewings/edit.html.erb", "app/views/viewings/edit.html.erb"
|
15
|
+
template "viewings/index.html.erb", "app/views/viewings/index.html.erb"
|
16
|
+
template "viewings/new.html.erb", "app/views/viewings/new.html.erb"
|
17
|
+
template "viewings/show.html.erb", "app/views/viewings/show.html.erb"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/viewable.gemspec
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'viewable/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
# metadata
|
8
|
+
s.name = 'viewable'
|
9
|
+
s.version = Viewable::VERSION
|
10
|
+
s.licenses = ['MIT']
|
11
|
+
s.summary = %q{a viewings calendar gem for rails 4.0}
|
12
|
+
s.description = %q{Viewable is a Rails 4.0 gem that enables you to add resource viewing functionality to your Rails application. A resource can be anything that is viewable e.g. function room, conference hall. }
|
13
|
+
s.authors = ["Tom Cox", "crmis"]
|
14
|
+
s.email = 'tom.jcox@icloud.com'
|
15
|
+
s.homepage = 'https://github.com/crmis/viewable'
|
16
|
+
|
17
|
+
# file settings
|
18
|
+
s.files = `git ls-files`.split($/)
|
19
|
+
s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
20
|
+
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
21
|
+
s.require_paths = ["lib","lib/viewable","lib/viewable/generators", "lib/viewable/generators/viewable"]
|
22
|
+
|
23
|
+
# development dependencies
|
24
|
+
s.add_development_dependency 'bundler', '~> 1.8'
|
25
|
+
s.add_development_dependency 'rake', '~> 10.4'
|
26
|
+
|
27
|
+
# runtime dependencies
|
28
|
+
s.add_dependency 'jbuilder', '~> 1.5'
|
29
|
+
s.add_dependency 'rails_12factor', '~> 0.0.3'
|
30
|
+
end
|