viewable 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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