bookingsync_portal 0.0.1

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 (52) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +47 -0
  4. data/Rakefile +28 -0
  5. data/app/assets/javascripts/bookingsync_portal/admin/application.js +20 -0
  6. data/app/assets/javascripts/bookingsync_portal/admin/handle_remote_errors.js.coffee +3 -0
  7. data/app/assets/javascripts/bookingsync_portal/admin/live_updates.js.coffee +7 -0
  8. data/app/assets/javascripts/bookingsync_portal/admin/rentals.js.coffee +77 -0
  9. data/app/assets/javascripts/bookingsync_portal/admin/templates/rentals/connected_rental.hbs +8 -0
  10. data/app/assets/stylesheets/bookingsync_portal/admin/application.css.scss +120 -0
  11. data/app/controllers/bookingsync_portal/admin/base_controller.rb +19 -0
  12. data/app/controllers/bookingsync_portal/admin/remote_accounts_controller.rb +24 -0
  13. data/app/controllers/bookingsync_portal/admin/rentals_controller.rb +64 -0
  14. data/app/controllers/bookingsync_portal/admin_api/base_controller.rb +13 -0
  15. data/app/controllers/bookingsync_portal/admin_api/connections_controller.rb +6 -0
  16. data/app/controllers/bookingsync_portal/admin_api/remote_rentals_controller.rb +18 -0
  17. data/app/controllers/bookingsync_portal/admin_api/rentals_controller.rb +18 -0
  18. data/app/controllers/bookingsync_portal/application_controller.rb +4 -0
  19. data/app/helpers/bookingsync_portal/admin/rentals_helper.rb +34 -0
  20. data/app/models/bookingsync_portal/account.rb +10 -0
  21. data/app/models/bookingsync_portal/connection.rb +21 -0
  22. data/app/models/bookingsync_portal/remote_account.rb +9 -0
  23. data/app/models/bookingsync_portal/remote_rental.rb +27 -0
  24. data/app/models/bookingsync_portal/rental.rb +15 -0
  25. data/app/resources/bookingsync_portal/admin_api/connection_resource.rb +22 -0
  26. data/app/resources/bookingsync_portal/admin_api/remote_account_resource.rb +14 -0
  27. data/app/resources/bookingsync_portal/admin_api/remote_rental_resource.rb +14 -0
  28. data/app/resources/bookingsync_portal/admin_api/rental_resource.rb +14 -0
  29. data/app/views/bookingsync_portal/admin/remote_accounts/_form.html.erb +11 -0
  30. data/app/views/bookingsync_portal/admin/remote_accounts/_how_to_connect.html.erb +1 -0
  31. data/app/views/bookingsync_portal/admin/remote_accounts/new.html.erb +5 -0
  32. data/app/views/bookingsync_portal/admin/rentals/_connected_rental.html.erb +27 -0
  33. data/app/views/bookingsync_portal/admin/rentals/_remote_rental.html.erb +9 -0
  34. data/app/views/bookingsync_portal/admin/rentals/_rental.html.erb +17 -0
  35. data/app/views/bookingsync_portal/admin/rentals/index.html.erb +58 -0
  36. data/app/views/bookingsync_portal/admin/rentals/show.js.erb +6 -0
  37. data/app/views/layouts/bookingsync_portal/admin.html.erb +13 -0
  38. data/config/locales/en.yml +58 -0
  39. data/config/routes.rb +19 -0
  40. data/db/migrate/20150222172825_create_accounts.rb +13 -0
  41. data/db/migrate/20150222173413_create_rentals.rb +14 -0
  42. data/db/migrate/20150222173711_create_remote_accounts.rb +10 -0
  43. data/db/migrate/20150222174023_create_remote_rentals.rb +12 -0
  44. data/db/migrate/20150222174234_create_connections.rb +9 -0
  45. data/lib/bookingsync_portal.rb +77 -0
  46. data/lib/bookingsync_portal/engine.rb +9 -0
  47. data/lib/bookingsync_portal/mash_serializer.rb +9 -0
  48. data/lib/bookingsync_portal/version.rb +3 -0
  49. data/lib/generators/bookingsync_portal/install_generator.rb +15 -0
  50. data/lib/generators/templates/bookingsync_portal.rb +46 -0
  51. data/lib/tasks/bookingsync_portal_tasks.rake +4 -0
  52. metadata +374 -0
@@ -0,0 +1,13 @@
1
+ module BookingsyncPortal
2
+ module AdminApi
3
+ class BaseController < BookingsyncApplication::Admin::BaseController
4
+
5
+ private
6
+
7
+ def messagebus_channel
8
+ "/account-#{current_account.id}"
9
+ end
10
+ helper_method :messagebus_channel
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,6 @@
1
+ module BookingsyncPortal
2
+ module AdminApi
3
+ class ConnectionsController < BookingsyncPortal::AdminApi::BaseController
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,18 @@
1
+ module BookingsyncPortal
2
+ module AdminApi
3
+ class RemoteRentalsController < BookingsyncPortal::AdminApi::BaseController
4
+ prepend_before_action :set_resource_klass_name
5
+ before_action :fetch_remote_rentals, only: :index
6
+
7
+ private
8
+
9
+ def fetch_remote_rentals
10
+ BookingsyncPortal.fetch_remote_rentals(current_account)
11
+ end
12
+
13
+ def set_resource_klass_name
14
+ @resource_klass_name = BookingsyncPortal.remote_rental_resource
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ module BookingsyncPortal
2
+ module AdminApi
3
+ class RentalsController < BookingsyncPortal::AdminApi::BaseController
4
+ prepend_before_action :set_resource_klass_name
5
+ before_action :synchronize_rentals, only: :index
6
+
7
+ private
8
+
9
+ def synchronize_rentals
10
+ BookingsyncPortal.rental_model.constantize.synchronize(scope: current_account)
11
+ end
12
+
13
+ def set_resource_klass_name
14
+ @resource_klass_name = BookingsyncPortal.rental_resource
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,4 @@
1
+ module BookingsyncPortal
2
+ class ApplicationController < ::ApplicationController
3
+ end
4
+ end
@@ -0,0 +1,34 @@
1
+ module BookingsyncPortal
2
+ module Admin
3
+ module RentalsHelper
4
+ def rental_details(rental)
5
+ scope = 'bookingsync_portal.admin.rentals.rental'
6
+
7
+ details = Array.new
8
+ if rental.sleeps.to_i > 0
9
+ if rental.sleeps_max.to_i > 0 && rental.sleeps_max.to_i > rental.sleeps.to_i
10
+ details << t(:sleeps_html, scope: scope,
11
+ count: "#{rental.sleeps.to_i}-#{rental.sleeps_max.to_i}")
12
+ else
13
+ details << t(:sleeps_html, scope: scope,
14
+ count: rental.sleeps.to_i)
15
+ end
16
+ end
17
+ if rental.bedrooms_count.to_i > 0
18
+ details << t(:bedrooms_html, scope: scope,
19
+ count: rental.bedrooms_count.to_i)
20
+ end
21
+ if rental.bathrooms_count.to_i > 0
22
+ details << t(:bathrooms_html, scope: scope,
23
+ count: rental.bathrooms_count.to_i)
24
+ end
25
+ if rental.surface.to_i > 0
26
+ details << t(:surface_html, scope: scope,
27
+ count: rental.surface.to_i)
28
+ end
29
+
30
+ safe_join(details, ', ')
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,10 @@
1
+ class BookingsyncPortal::Account < ActiveRecord::Base
2
+ self.table_name = 'accounts'
3
+
4
+ include BookingSync::Engine::Model
5
+
6
+ has_many :remote_accounts, class_name: BookingsyncPortal.remote_account_model, dependent: :destroy
7
+ has_many :remote_rentals, class_name: BookingsyncPortal.remote_rental_model, through: :remote_accounts
8
+ has_many :rentals, class_name: BookingsyncPortal.rental_model, dependent: :destroy
9
+ has_many :connections, class_name: BookingsyncPortal.connection_model, through: :rentals
10
+ end
@@ -0,0 +1,21 @@
1
+ class BookingsyncPortal::Connection < ActiveRecord::Base
2
+ self.table_name = 'connections'
3
+
4
+ belongs_to :remote_rental, class_name: BookingsyncPortal.remote_rental_model
5
+ belongs_to :rental, class_name: BookingsyncPortal.rental_model
6
+
7
+ validates :remote_rental, presence: true
8
+ validates :rental, presence: true
9
+
10
+ validate :matching_accounts, if: -> { rental && remote_rental }
11
+
12
+ private
13
+
14
+ def matching_accounts?
15
+ rental.account == remote_rental.remote_account.account
16
+ end
17
+
18
+ def matching_accounts
19
+ errors.add(:base, :not_matching_accounts) unless matching_accounts?
20
+ end
21
+ end
@@ -0,0 +1,9 @@
1
+ class BookingsyncPortal::RemoteAccount < ActiveRecord::Base
2
+ self.table_name = 'remote_accounts'
3
+
4
+ belongs_to :account, class_name: BookingsyncPortal.account_model
5
+ has_many :remote_rentals, class_name: BookingsyncPortal.remote_rental_model, dependent: :destroy
6
+
7
+ validates :uid, presence: true, uniqueness: true
8
+ validates :account, presence: true
9
+ end
@@ -0,0 +1,27 @@
1
+ require 'bookingsync_portal/mash_serializer'
2
+
3
+ class BookingsyncPortal::RemoteRental < ActiveRecord::Base
4
+ self.table_name = 'remote_rentals'
5
+
6
+ belongs_to :remote_account, class_name: BookingsyncPortal.remote_account_model
7
+ has_one :account, class_name: BookingsyncPortal.account_model, through: :remote_account
8
+ has_one :connection, class_name: BookingsyncPortal.connection_model, dependent: :destroy
9
+ has_one :rental, class_name: BookingsyncPortal.rental_model, through: :connection
10
+
11
+ serialize :remote_data, BookingsyncPortal::MashSerializer
12
+
13
+ validates :uid, presence: true, uniqueness: true
14
+ validates :remote_account, presence: true
15
+
16
+ scope :ordered, -> { order(created_at: :desc) }
17
+ scope :connected, -> { joins(:rental) }
18
+ scope :not_connected, -> { includes(:rental).where(rentals: { id: nil }) }
19
+
20
+ def connected?
21
+ rental.present?
22
+ end
23
+
24
+ def synchronized?
25
+ synchronized_at.present?
26
+ end
27
+ end
@@ -0,0 +1,15 @@
1
+ class BookingsyncPortal::Rental < ActiveRecord::Base
2
+ self.table_name = 'rentals'
3
+
4
+ belongs_to :account, class_name: BookingsyncPortal.account_model
5
+ has_one :connection, class_name: BookingsyncPortal.connection_model, dependent: :destroy
6
+ has_one :remote_rental, class_name: BookingsyncPortal.remote_rental_model, through: :connection
7
+
8
+ scope :ordered, -> { order(created_at: :desc) }
9
+ scope :connected, -> { joins(:remote_rental) }
10
+ scope :not_connected, -> { includes(:connection).where(connections: { remote_rental_id: nil }) }
11
+
12
+ def connected?
13
+ remote_rental.present?
14
+ end
15
+ end
@@ -0,0 +1,22 @@
1
+ module BookingsyncPortal
2
+ module AdminApi
3
+ class ConnectionResource < JSONAPI::Resource
4
+ model_name BookingsyncPortal.connection_model
5
+
6
+ attributes :id, :rental_id, :remote_rental_id
7
+
8
+ def self.records(options = {})
9
+ context = options[:context]
10
+ context[:current_account].connections
11
+ end
12
+
13
+ def save
14
+ unless context[:current_account].id == @model.rental.account_id &&
15
+ context[:current_account].id == @model.remote_rental.account.id
16
+ raise JSONAPI::Exceptions::RecordNotFound.new(@model.rental_id)
17
+ end
18
+ super
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,14 @@
1
+ module BookingsyncPortal
2
+ module AdminApi
3
+ class RemoteAccountResource < JSONAPI::Resource
4
+ model_name BookingsyncPortal.remote_account_model
5
+
6
+ attributes :id, :uid
7
+
8
+ def self.records(options = {})
9
+ context = options[:context]
10
+ context[:current_account].remote_accounts
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ module BookingsyncPortal
2
+ module AdminApi
3
+ class RemoteRentalResource < JSONAPI::Resource
4
+ model_name BookingsyncPortal.remote_rental_model
5
+
6
+ attributes :id
7
+
8
+ def self.records(options = {})
9
+ context = options[:context]
10
+ context[:current_account].remote_rentals
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ module BookingsyncPortal
2
+ module AdminApi
3
+ class RentalResource < JSONAPI::Resource
4
+ model_name BookingsyncPortal.rental_model
5
+
6
+ attributes :id
7
+
8
+ def self.records(options = {})
9
+ context = options[:context]
10
+ context[:current_account].rentals
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,11 @@
1
+ <div class="col-sm-offset-4 col-sm-4 form-group">
2
+ <%= simple_form_for [:admin, remote_account] do |f| -%>
3
+ <div class="form-group">
4
+ <%= f.input :uid, input_html: { class: 'input-lg form-control' } -%>
5
+ </div>
6
+
7
+ <div class="form-group">
8
+ <%= f.submit t('.submit_new'), class: "btn btn-primary btn-lg btn-block" %>
9
+ </div>
10
+ <%- end -%>
11
+ </div>
@@ -0,0 +1 @@
1
+ <p class="lead">Info on how to connect with remote account, modify app/views/bookingsync_portal/admin/remote_accounts/_how_to_connect.html.erb</p>
@@ -0,0 +1,5 @@
1
+ <div class="text-center">
2
+ <h1><%=t '.title' %></h1>
3
+ <%= render 'how_to_connect' %>
4
+ <%= render 'form', remote_account: @remote_account %>
5
+ </div>
@@ -0,0 +1,27 @@
1
+ <div
2
+ class="panel panel-connected <%= "pending" unless remote_rental.synchronized? %>"
3
+ id="<%= dom_id rental %>">
4
+ <div class="panel-heading" title="<%= RemoteRental.human_attribute_name(:uid) %>
5
+ <%= remote_rental.uid %>">
6
+ <%= rental.name %>
7
+ <%= link_to t('.disconnect_rental'),
8
+ bookingsync_portal.disconnect_admin_rental_path(rental),
9
+ class: "btn btn-default btn-xs remove-connection",
10
+ data: {disable_with: t('.disconnecting_rental')},
11
+ method: :put %>
12
+ </div>
13
+ <% if rental.remote_rental.synchronized? %>
14
+ <div class="panel-body-grid">
15
+ <div class="panel-body-grid-photo">
16
+ <%- if rental.ordered_photos.first -%>
17
+ <%= image_tag rental.ordered_photos.first.thumb_url, class: "img-responsive" %>
18
+ <%- end -%>
19
+ </div>
20
+ <div class="panel-body-grid-text">
21
+ <%= rental_details(rental) %>
22
+ </div>
23
+ </div>
24
+ <% else %>
25
+ <div class="panel-body"><%= icon('spinner fa-spin', t('.synchronizing')) %></div>
26
+ <% end %>
27
+ </div>
@@ -0,0 +1,9 @@
1
+ <div class="panel panel-remote not-connected-remote-rental" id="<%= dom_id remote_rental %>"
2
+ data-uid="<%= remote_rental.uid %>">
3
+ <div class="panel-heading" title="<%= RemoteRental.human_attribute_name(:uid) %>
4
+ <%= remote_rental.uid %>">
5
+ <%= remote_rental.name.presence || t('.no_name') %><br/>
6
+ </div>
7
+ <div class="panel-body">
8
+ </div>
9
+ </div>
@@ -0,0 +1,17 @@
1
+ <div class="panel panel-bookingsync bookingsync-rental"
2
+ id="<%= dom_id rental %>"
3
+ data-connect-url="<%= connect_admin_rental_url(rental) %>">
4
+ <div class="panel-heading">
5
+ <%= rental.name.presence || t('.no_name') %>
6
+ </div>
7
+ <div class="panel-body-grid">
8
+ <div class="panel-body-grid-photo">
9
+ <%- if rental.ordered_photos.first -%>
10
+ <%= image_tag rental.ordered_photos.first.thumb_url, class: "img-responsive" %>
11
+ <%- end -%>
12
+ </div>
13
+ <div class="panel-body-grid-text">
14
+ <%= rental_details rental %>
15
+ </div>
16
+ </div>
17
+ </div>
@@ -0,0 +1,58 @@
1
+ <div class="rentals-container row-fluid">
2
+ <div class="bookingsync-rentals-list rentals-list col-xs-4">
3
+ <div class="rentals-list-header">
4
+ <legend><%=t '.bookingsync_header', account_name: current_account.name %></legend>
5
+ </div>
6
+ <div class="rentals-list-scroll">
7
+ <%- if @not_connected_rentals.length > 0 -%>
8
+ <% @not_connected_rentals.each do |rental| %>
9
+ <%= render rental %>
10
+ <% end %>
11
+ <%- else -%>
12
+ <div class="lead text-center well">
13
+ <p class=""><%= icon 'thumbs-up fa-lg' %></p>
14
+ <p><%=t '.all_synchronized' %></p>
15
+ </div>
16
+ <%- end -%>
17
+ </div>
18
+ </div>
19
+
20
+ <% if @remote_accounts.any? %>
21
+ <% @remote_accounts.each do |remote_account| %>
22
+ <div class="remote-rentals-list rentals-list col-xs-4">
23
+ <div class="rentals-list-header">
24
+ <legend><%=t '.remote_header', account_name: remote_account.name %></legend>
25
+ </div>
26
+
27
+ <div class="rentals-list-scroll">
28
+ <%- if @remote_account_not_registered %>
29
+ <div class="lead text-center well">
30
+ <p class=""><%= icon 'warning fa-lg' %></p>
31
+ <%= render 'bookingsync_portal/admin/remote_accounts/how_to_connect' %>
32
+ </div>
33
+ <%- elsif Array(@remote_rentals_by_account[remote_account]).length > 0 -%>
34
+ <% Array(@remote_rentals_by_account[remote_account]).each do |remote_rental| %>
35
+ <% if remote_rental.connected? %>
36
+ <%= render "connected_rental", remote_rental: remote_rental, rental: remote_rental.rental %>
37
+ <% else %>
38
+ <%= render "remote_rental", remote_rental: remote_rental %>
39
+ <% end %>
40
+ <% end %>
41
+ <%- else -%>
42
+ <div class="lead text-center well">
43
+ <p class=""><%= icon 'info fa-lg' %></p>
44
+ <p><%=t '.create_listings_first' %></p>
45
+ </div>
46
+ <%- end -%>
47
+ </div>
48
+ </div>
49
+ <% end %>
50
+ <% else %>
51
+ <div class="rentals-list col-xs-4">
52
+ <legend><%=t '.connect' %></legend>
53
+ <%= link_to new_admin_remote_account_path, class: "btn btn-primary btn-lg btn-block" do %>
54
+ <%= icon "plus-circle" %> <%= t '.connect_accounts' %>
55
+ <% end %>
56
+ </div>
57
+ <% end %>
58
+ </div>
@@ -0,0 +1,6 @@
1
+ $("#<%= dom_id @rental %>").replaceWith(
2
+ <%- if @rental.connected? %>
3
+ "<%=j render 'connected_rental', rental: @rental, remote_rental: @rental.remote_rental %>");
4
+ <%- else %>
5
+ "<%=j render 'rental', rental: @rental %>");
6
+ <%- end %>
@@ -0,0 +1,13 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>BookingSync - HolidayLettings integration</title>
5
+ <%= stylesheet_link_tag 'admin/application', media: 'all', 'data-turbolinks-track' => true %>
6
+ <%= csrf_meta_tags %>
7
+ </head>
8
+ <body data-messagebus-channel="<%= messagebus_channel %>">
9
+ <%= yield %>
10
+ <%= javascript_include_tag 'admin/application', 'data-turbolinks-track' => true %>
11
+ <div class="footer"></div>
12
+ </body>
13
+ </html>
@@ -0,0 +1,58 @@
1
+ en:
2
+ activerecord:
3
+ attributes:
4
+ remote_account:
5
+ uid: Remote account ID
6
+ errors:
7
+ messages:
8
+ not_matching_accounts: Different ownership of rental and remote_rental
9
+
10
+ bookingsync_portal:
11
+ admin:
12
+ remote_accounts:
13
+ new:
14
+ title: Connect A New Remote Account
15
+ form:
16
+ submit_new: Connect This Remote Account
17
+
18
+ remote_rentals:
19
+ show:
20
+ listing_id: "Listing #%{id}"
21
+
22
+ rentals:
23
+ index:
24
+ connect: Connect
25
+ bookingsync_header: "BookingSync: %{account_name}"
26
+ all_synchronized: Perfect! All your rentals are synchronized.
27
+ create_listings_first: You must create your rentals on Remote Account before you can synchronize them automatically.
28
+ connect_accounts: Add External Portal Account
29
+ remote_header: "Remote Account: %{account_name}"
30
+ rental:
31
+ bedrooms_html:
32
+ one: '<strong>1</strong> Bedroom'
33
+ other: '<strong>%{count}</strong> Bedrooms'
34
+ bathrooms_html:
35
+ one: '<strong>1</strong> Bathroom'
36
+ other: '<strong>%{count}</strong> Bathrooms'
37
+ sleeps_html:
38
+ one: '<strong>%{count}</strong> Person'
39
+ other: '<strong>%{count}</strong> People'
40
+ surface_html:
41
+ zero: ''
42
+ other: '<span>Surface</span> <strong>%{count}m²</strong>'
43
+ no_name: Unnamed rental
44
+ remote_rental:
45
+ no_name: Unnamed remote rental
46
+ connected_rental:
47
+ disconnect_rental: 'Disconnect'
48
+ disconnecting_rental: 'Disconnecting...'
49
+ synchronizing: 'Synchronizing...'
50
+
51
+ simple_form:
52
+ "yes": 'Yes'
53
+ "no": 'No'
54
+ required:
55
+ text: 'required'
56
+ mark: '*'
57
+ error_notification:
58
+ default_message: "Please review the problems below:"