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.
Files changed (44) hide show
  1. checksums.yaml +7 -0
  2. data/.editorconfig +10 -0
  3. data/.gitignore +27 -0
  4. data/.travis.yml +22 -0
  5. data/AUTHORS.md +6 -0
  6. data/CONTRIBUTING.md +22 -0
  7. data/Gemfile +7 -0
  8. data/LICENSE.md +23 -0
  9. data/README.md +41 -0
  10. data/Rakefile +6 -0
  11. data/lib/viewable/generators/viewable/controller_generator.rb +21 -0
  12. data/lib/viewable/generators/viewable/css_generator.rb +11 -0
  13. data/lib/viewable/generators/viewable/install_generator.rb +15 -0
  14. data/lib/viewable/generators/viewable/js_generator.rb +16 -0
  15. data/lib/viewable/generators/viewable/resource_model_generator.rb +20 -0
  16. data/lib/viewable/generators/viewable/templates/assets/javascript/calendar-editable.js +6991 -0
  17. data/lib/viewable/generators/viewable/templates/assets/javascript/custom.js +130 -0
  18. data/lib/viewable/generators/viewable/templates/assets/javascript/fullcalendar.js +6110 -0
  19. data/lib/viewable/generators/viewable/templates/assets/stylesheets/custom.css +24 -0
  20. data/lib/viewable/generators/viewable/templates/assets/stylesheets/fullcalendar.css +587 -0
  21. data/lib/viewable/generators/viewable/templates/controllers/resource_controller.rb +50 -0
  22. data/lib/viewable/generators/viewable/templates/controllers/viewing_controller.rb +77 -0
  23. data/lib/viewable/generators/viewable/templates/models/datetime.rb +5 -0
  24. data/lib/viewable/generators/viewable/templates/models/resource.rb +4 -0
  25. data/lib/viewable/generators/viewable/templates/models/viewable.rb +85 -0
  26. data/lib/viewable/generators/viewable/templates/models/viewing.rb +4 -0
  27. data/lib/viewable/generators/viewable/templates/views/_errors.html.erb +13 -0
  28. data/lib/viewable/generators/viewable/templates/views/_form.html.erb +6 -0
  29. data/lib/viewable/generators/viewable/templates/views/edit.html.erb +1 -0
  30. data/lib/viewable/generators/viewable/templates/views/index.html.erb +11 -0
  31. data/lib/viewable/generators/viewable/templates/views/new.html.erb +1 -0
  32. data/lib/viewable/generators/viewable/templates/views/viewings/_errors.html.erb +12 -0
  33. data/lib/viewable/generators/viewable/templates/views/viewings/_form.html.erb +11 -0
  34. data/lib/viewable/generators/viewable/templates/views/viewings/edit.html.erb +9 -0
  35. data/lib/viewable/generators/viewable/templates/views/viewings/index.html.erb +22 -0
  36. data/lib/viewable/generators/viewable/templates/views/viewings/new.html.erb +9 -0
  37. data/lib/viewable/generators/viewable/templates/views/viewings/show.html.erb +6 -0
  38. data/lib/viewable/generators/viewable/viewing_model_generator.rb +25 -0
  39. data/lib/viewable/generators/viewable/views_generator.rb +20 -0
  40. data/lib/viewable/railtie.rb +7 -0
  41. data/lib/viewable/version.rb +3 -0
  42. data/lib/viewable/viewable.rb +2 -0
  43. data/viewable.gemspec +30 -0
  44. 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,5 @@
1
+ class ActiveSupport::HashWithIndifferentAccess
2
+ def to_datetime(name)
3
+ units = select{|k,v| k.match /#{name}\(..\)/}.map{|k,v| v.to_i}
4
+ DateTime.new(*units)
5
+ end
@@ -0,0 +1,4 @@
1
+ class <%= resource_name_camelize.singularize %> < ActiveRecord::Base
2
+ validates :name, presence: true, uniqueness: true
3
+ has_many :viewings
4
+ 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,4 @@
1
+ require_relative './concerns/viewable'
2
+ class Viewing < ActiveRecord::Base
3
+ include Viewable
4
+ 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,6 @@
1
+ <%%= form_for @<%=viewable_views_name.singularize%> do |f| %>
2
+ <%%= render 'errors' %>
3
+ <%%= f.label 'name', 'Name' %>
4
+ <%%= f.text_field 'name', placeholder: 'Name'%>
5
+ <%%= f.submit 'Submit' %>
6
+ <%% 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,9 @@
1
+ <h3>Edit viewing for <%%= @<%=viewable_views_name.singularize%>.name %></h3>
2
+
3
+ <%%= render 'errors' %>
4
+ <%%= render 'form' %>
5
+
6
+ <div class="calendar_container">
7
+ <div id="calendar">
8
+ </div>
9
+ </div>
@@ -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,9 @@
1
+ <h3>Add viewing for <%%= @<%=viewable_views_name.singularize%>.name %></h3>
2
+
3
+ <%%= render 'errors' %>
4
+ <%%= render 'form' %>
5
+
6
+ <div class="calendar_container">
7
+ <div id="calendar">
8
+ </div>
9
+ </div>
@@ -0,0 +1,6 @@
1
+ <h3>Viewing Confirmation</h3>
2
+ <p>Your viewing is confirmed for
3
+ <%%= @<%=viewable_views_name.singularize%>.name %>:
4
+ <%%= @viewing.start_time.strftime('%e %b %Y %H:%M%p') %>
5
+ until
6
+ <%%= (@viewing.calculate_end_time + 60).strftime('%e %b %Y %H:%M%p') %>
@@ -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
@@ -0,0 +1,7 @@
1
+ require 'rails/railtie'
2
+ module Viewable
3
+ class Railtie < Rails::Railtie
4
+ generators do
5
+ require "generators/viewable/install_generator"
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ module Viewable
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1,2 @@
1
+ require 'viewable/version'
2
+ require 'viewable/railtie'
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