viewable 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|