diff --git a/app/controllers/admin/call_to_actions_controller.rb b/app/controllers/admin/call_to_actions_controller.rb
new file mode 100644
index 000000000..d95f5bdeb
--- /dev/null
+++ b/app/controllers/admin/call_to_actions_controller.rb
@@ -0,0 +1,61 @@
+class Admin::CallToActionsController < Comfy::Admin::Cms::BaseController
+ before_action :build_cta, :only => [:new, :create]
+ before_action :load_cta, :only => [:show, :edit, :update, :destroy]
+
+ def index
+ @ctas = CallToAction.page(params[:page])
+ end
+
+ def show
+ render
+ end
+
+ def new
+ render
+ end
+
+ def edit
+ render
+ end
+
+ def create
+ @cta.save!
+ flash[:success] = 'Call To Action created'
+ redirect_to action: :show, id: @cta
+ rescue ActiveRecord::RecordInvalid
+ flash.now[:danger] = 'Failed to create Call To Action'
+ render action: :new
+ end
+
+ def update
+ @cta.update_attributes!(cta_params)
+ flash[:success] = 'Call To Action updated'
+ redirect_to action: :show, id: @cta
+ rescue ActiveRecord::RecordInvalid
+ flash.now[:danger] = 'Failed to update Call To Action'
+ render action: :edit
+ end
+
+ def destroy
+ @cta.destroy
+ flash[:success] = 'Call To Action deleted'
+ redirect_to action: :index
+ end
+
+ protected
+
+ def build_cta
+ @cta = CallToAction.new(cta_params)
+ end
+
+ def load_cta
+ @cta = CallToAction.find(params[:id])
+ rescue ActiveRecord::RecordNotFound
+ flash[:danger] = 'Call To Action not found'
+ redirect_to action: :index
+ end
+
+ def cta_params
+ params.fetch(:call_to_action, {}).permit(:css_class, :title, :summary, :url, :updated)
+ end
+end
diff --git a/app/helpers/cms_helper.rb b/app/helpers/cms_helper.rb
index 4f71cd5b4..d4e1a7591 100644
--- a/app/helpers/cms_helper.rb
+++ b/app/helpers/cms_helper.rb
@@ -72,4 +72,12 @@ def get_filtered_pages pages
pages
end
+
+ def cta_api
+ @cta_api ||= CallToAction.find_by_css_class('api')
+ end
+
+ def cta_live_report
+ @cta_live_report ||= CallToAction.find_by_css_class('live-report')
+ end
end
diff --git a/app/models/call_to_action.rb b/app/models/call_to_action.rb
new file mode 100644
index 000000000..768f86b2b
--- /dev/null
+++ b/app/models/call_to_action.rb
@@ -0,0 +1,16 @@
+class CallToAction < ActiveRecord::Base
+ self.table_name = "comfy_cms_call_to_actions"
+
+ validates :title,
+ presence: true,
+ length: {maximum: 75},
+ allow_nil: false
+ validates :summary,
+ presence: true,
+ length: {maximum: 150},
+ allow_nil: false
+ validates :url,
+ presence: true,
+ length: {maximum: 255},
+ allow_nil: false
+end
diff --git a/app/views/admin/call_to_actions/_form.html.erb b/app/views/admin/call_to_actions/_form.html.erb
new file mode 100644
index 000000000..efc2e358f
--- /dev/null
+++ b/app/views/admin/call_to_actions/_form.html.erb
@@ -0,0 +1,10 @@
+
The title may have up to 75 characters and the description may have up to 150.
+
+<%= form.text_field :css_class, maxlength: 75 %>
+<%= form.text_field :title, maxlength: 75 %>
+<%= form.text_field :summary, maxlength: 150 %>
+<%= form.text_field :url, maxlength: 255 %>
+<%= form.check_box :updated %>
+<%= form.form_group class: 'form-actions' do %>
+ <%= form.submit class: 'btn btn-primary' %>
+<% end %>
diff --git a/app/views/admin/call_to_actions/edit.html.erb b/app/views/admin/call_to_actions/edit.html.erb
new file mode 100644
index 000000000..03be5a6a9
--- /dev/null
+++ b/app/views/admin/call_to_actions/edit.html.erb
@@ -0,0 +1,6 @@
+
+<%= comfy_form_with model: @cta, url: {action: :update} do |form| %>
+ <%= render form %>
+<% end %>
diff --git a/app/views/admin/call_to_actions/index.html.erb b/app/views/admin/call_to_actions/index.html.erb
new file mode 100644
index 000000000..eb36abd57
--- /dev/null
+++ b/app/views/admin/call_to_actions/index.html.erb
@@ -0,0 +1,30 @@
+
+
+
+
+ Class (Max characters: 75) |
+ Title (Max characters: 75) |
+ Summary (Max characters: 150) |
+ Url |
+ Updated |
+ |
+
+ <% @ctas.each do |cta| %>
+
+ <%= cta.css_class %> |
+ <%= cta.title %> |
+ <%= cta.summary %> |
+ <%= cta.url %> |
+ <%= cta.updated.to_s %> |
+
+
+ <%= link_to 'Edit', edit_admin_call_to_action_path(cta), :class => 'btn btn-outline-secondary' %>
+ <%= link_to 'Delete', admin_call_to_action_path(cta), :method => :delete, :data => { :confirm => 'Are you sure?' }, :class => 'btn btn-danger' %>
+
+ |
+
+ <% end %>
+
diff --git a/app/views/admin/call_to_actions/new.html.erb b/app/views/admin/call_to_actions/new.html.erb
new file mode 100644
index 000000000..c1ddd25dd
--- /dev/null
+++ b/app/views/admin/call_to_actions/new.html.erb
@@ -0,0 +1,6 @@
+
+<%= comfy_form_with model: @cta, url: {action: :create} do |form| %>
+ <%= render form %>
+<% end %>
diff --git a/app/views/admin/call_to_actions/show.html.erb b/app/views/admin/call_to_actions/show.html.erb
new file mode 100644
index 000000000..af53e89ae
--- /dev/null
+++ b/app/views/admin/call_to_actions/show.html.erb
@@ -0,0 +1,24 @@
+
+
+ CSS Class:
+ <%= @cta.css_class %>
+
+
+ Title:
+ <%= @cta.title %>
+
+
+ Summary:
+ <%= @cta.summary %>
+
+
+ Url:
+ <%= @cta.url %>
+
+
+ Updated:
+ <%= @cta.updated.to_s %>
+
+<%= link_to 'View all', admin_call_to_actions_path, class: 'btn btn-primary' %>
diff --git a/app/views/comfy/admin/cms/partials/_navigation_inner.html.erb b/app/views/comfy/admin/cms/partials/_navigation_inner.html.erb
new file mode 100644
index 000000000..336928c89
--- /dev/null
+++ b/app/views/comfy/admin/cms/partials/_navigation_inner.html.erb
@@ -0,0 +1,5 @@
+
+
+
+ <%= link_to 'Call To Actions', admin_call_to_actions_path, class: 'nav-link', title: 'View Call to Actions' %>
+
\ No newline at end of file
diff --git a/app/views/comfy/admin/cms/partials/_navigation_inner.html.haml b/app/views/comfy/admin/cms/partials/_navigation_inner.html.haml
deleted file mode 100644
index 19c6936cb..000000000
--- a/app/views/comfy/admin/cms/partials/_navigation_inner.html.haml
+++ /dev/null
@@ -1,2 +0,0 @@
-
-%li= active_link_to 'HomeCarouselSlides', admin_home_carousel_slides_path
diff --git a/app/views/partials/ctas/_api.html.erb b/app/views/partials/ctas/_api.html.erb
index 4193e1978..1b8439dda 100644
--- a/app/views/partials/ctas/_api.html.erb
+++ b/app/views/partials/ctas/_api.html.erb
@@ -1,10 +1,10 @@
-
<%= t('ctas.api.title') %>
-
<%= t('ctas.api.intro') %>
-
- <%= link_to t('ctas.api.button'), t('ctas.api.url'), target: '_blank', class: 'button--outline-white' %>
+
<%= cta_api.title %>
+
<%= cta_api.summary %>
+
+ <%= link_to t('ctas.api.button'), cta_api.url, target: '_blank', class: 'button--outline-white' %>
-
\ No newline at end of file
+
diff --git a/app/views/partials/ctas/_live-report.html.erb b/app/views/partials/ctas/_live-report.html.erb
index 0a2bfadeb..086651cd0 100644
--- a/app/views/partials/ctas/_live-report.html.erb
+++ b/app/views/partials/ctas/_live-report.html.erb
@@ -1,14 +1,16 @@
-
+
-
<%= t('global.status.updated') %>
+ <% if cta_live_report.updated %>
+
<%= t('global.status.updated') %>
+ <% end %>
-
<%= t('ctas.live_report.title') %>
-
<%= t('ctas.live_report.intro') %>
+
<%= cta_live_report.title %>
+
<%= cta_live_report.summary %>
- <%= link_to t('ctas.live_report.button'), t('ctas.live_report.url'), target: '_blank', class: 'button--accent' %>
+ <%= link_to t('ctas.live_report.button'), cta_live_report.url, target: '_blank', class: 'button--accent' %>
-
\ No newline at end of file
+
diff --git a/config/routes.rb b/config/routes.rb
index ee8c4ed62..c3f059af2 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,6 +1,7 @@
Rails.application.routes.draw do
namespace :admin do
resources :home_carousel_slides
+ resources :call_to_actions
end
require 'sidekiq/web'
diff --git a/db b/db
index 997bd14cb..2a5852e93 160000
--- a/db
+++ b/db
@@ -1 +1 @@
-Subproject commit 997bd14cbe4411ce5657d8fd0282f6760bffe653
+Subproject commit 2a5852e93ff823eb1f1537e0c10badf35fed8fce
diff --git a/test/controllers/admin/call_to_actions_controller_test.rb b/test/controllers/admin/call_to_actions_controller_test.rb
new file mode 100644
index 000000000..3a8c47673
--- /dev/null
+++ b/test/controllers/admin/call_to_actions_controller_test.rb
@@ -0,0 +1,107 @@
+require_relative '../../test_helper'
+
+class Admin::CallToActionsControllerTest < ActionController::TestCase
+
+ def setup
+ @cta = FactoryGirl.create(:call_to_action)
+ @site = ::Comfy::Cms::Site.create(label: 'test', identifier: 'test', hostname: 'localhost')
+ @request.env["HTTP_AUTHORIZATION"] = "Basic " + Base64::encode64("#{ComfortableMexicanSofa::AccessControl::AdminAuthentication.username}:#{ComfortableMexicanSofa::AccessControl::AdminAuthentication.password}")
+ end
+
+ def test_get_index
+ get :index
+ assert_response :success
+ assert assigns(:ctas)
+ assert_template :index
+ end
+
+ def test_get_show
+ get :show, params: {id: @cta}
+ assert_response :success
+ assert assigns(:cta)
+ assert_template :show
+ end
+
+ def test_get_show_failure
+ get :show, params: {id: 'invalid'}
+ assert_response :redirect
+ assert_redirected_to action: :index
+ assert_equal 'Call To Action not found', flash[:danger]
+ end
+
+ def test_get_new
+ get :new
+ assert_response :success
+ assert assigns(:cta)
+ assert_template :new
+ end
+
+ def test_get_edit
+ get :edit, params: {id: @cta}
+ assert_response :success
+ assert assigns(:cta)
+ assert_template :edit
+ end
+
+ def test_creation
+ assert_difference 'CallToAction.count' do
+ post :create, params: {
+ call_to_action: {
+ title: 'test title',
+ summary: 'test summary',
+ url: 'test url'
+ }
+ }
+ cta = CallToAction.last
+ assert_response :redirect
+ assert_redirected_to admin_call_to_action_path(cta)
+ assert_equal 'Call To Action created', flash[:success]
+ end
+ end
+
+ def test_creation_failure
+ assert_no_difference 'CallToAction.count' do
+ post :create, params: {call_to_action: {}}
+ assert_response :success
+ assert_template :new
+ assert_equal 'Failed to create Call To Action', flash[:danger]
+ end
+ end
+
+ def test_update
+ put :update, params: {
+ id: @cta,
+ call_to_action: {
+ title: 'Updated'
+ }
+ }
+ assert_response :redirect
+ assert_redirected_to action: :show, id: @cta
+ assert_equal 'Call To Action updated', flash[:success]
+ @cta.reload
+ assert_equal 'Updated', @cta.title
+ end
+
+ def test_update_failure
+ put :update, params: {
+ id: @cta,
+ call_to_action: {
+ title: ''
+ }
+ }
+ assert_response :success
+ assert_template :edit
+ assert_equal 'Failed to update Call To Action', flash[:danger]
+ @cta.reload
+ refute_equal '', @cta.title
+ end
+
+ def test_destroy
+ assert_difference 'CallToAction.count', -1 do
+ delete :destroy, params: {id: @cta}
+ assert_response :redirect
+ assert_redirected_to action: :index
+ assert_equal 'Call To Action deleted', flash[:success]
+ end
+ end
+end
diff --git a/test/factories/call_to_action.rb b/test/factories/call_to_action.rb
new file mode 100644
index 000000000..843774cf3
--- /dev/null
+++ b/test/factories/call_to_action.rb
@@ -0,0 +1,9 @@
+FactoryGirl.define do
+ factory :call_to_action do
+ css_class 'css_class'
+ title 'Title'
+ summary 'Summary'
+ url 'URL'
+ updated false
+ end
+end
diff --git a/test/models/call_to_action_test.rb b/test/models/call_to_action_test.rb
new file mode 100644
index 000000000..320a8d7a3
--- /dev/null
+++ b/test/models/call_to_action_test.rb
@@ -0,0 +1,28 @@
+require_relative '../test_helper'
+
+class CallToActionTest < ActiveSupport::TestCase
+
+ def test_fixtures_validity
+ CallToAction.all.each do |cta|
+ assert cta.valid?, cta.errors.inspect
+ end
+ end
+
+ def test_validation
+ cta = CallToAction.new
+ assert cta.invalid?
+ assert_equal [:title, :summary, :url], cta.errors.keys
+ end
+
+ def test_creation
+ assert_difference 'CallToAction.count' do
+ CallToAction.create(
+ css_class: 'css_class',
+ title: 'test title',
+ summary: 'test summary',
+ url: 'test url'
+ )
+ end
+ end
+
+end