diff --git a/app/controllers/impact_stories_controller.rb b/app/controllers/impact_stories_controller.rb
new file mode 100644
index 00000000..14d2f49b
--- /dev/null
+++ b/app/controllers/impact_stories_controller.rb
@@ -0,0 +1,45 @@
+class ImpactStoriesController < ApplicationController
+ before_action :authenticate_user!
+
+ def index
+ @impact_stories = current_partner.impact_stories.sort_by(&:created_at).reverse
+ end
+
+ def show
+ @impact_story = current_partner.impact_stories.find(params[:id])
+ end
+
+ def new
+ @impact_story = current_partner.impact_stories.new
+ end
+
+ def create
+ @impact_story = current_partner.impact_stories.new(impact_story_params)
+
+ if @impact_story.save
+ redirect_to @impact_story, notice: "Impact Story was successfully created."
+ else
+ render :new
+ end
+ end
+
+ def edit
+ @impact_story = current_partner.impact_stories.find(params[:id])
+ end
+
+ def update
+ @impact_story = current_partner.impact_stories.find(params[:id])
+
+ if @impact_story.update(impact_story_params)
+ redirect_to @impact_story, notice: "Impact Story was successfully updated."
+ else
+ render :edit
+ end
+ end
+
+ private
+
+ def impact_story_params
+ params.require(:impact_story).permit(:title, :content)
+ end
+end
diff --git a/app/models/impact_story.rb b/app/models/impact_story.rb
new file mode 100644
index 00000000..bb3e22c6
--- /dev/null
+++ b/app/models/impact_story.rb
@@ -0,0 +1,21 @@
+# == Schema Information
+#
+# Table name: impact_stories
+#
+# id :bigint(8) not null, primary key
+# partner_id :bigint(8)
+# title :string not null
+# content :text not null
+# created_at :datetime not null
+# updated_at :datetime not null
+#
+
+class ImpactStory < ApplicationRecord
+ belongs_to :partner
+
+ validates :title, :content, presence: true
+
+ def blurb(limit)
+ content.truncate(limit, separator: ' ')
+ end
+end
diff --git a/app/models/partner.rb b/app/models/partner.rb
index 5272d70f..15ca7fe2 100644
--- a/app/models/partner.rb
+++ b/app/models/partner.rb
@@ -99,6 +99,8 @@ class Partner < ApplicationRecord
has_many :children, through: :families
has_many :authorized_family_members, through: :families
+ has_many :impact_stories, dependent: :destroy
+
has_many :partner_requests, dependent: :destroy
has_many :family_requests, dependent: :destroy
has_one :partner_form, primary_key: :diaper_bank_id, foreign_key: :diaper_bank_id, dependent: :destroy
diff --git a/app/views/impact_stories/_form.html.erb b/app/views/impact_stories/_form.html.erb
new file mode 100644
index 00000000..7462c58e
--- /dev/null
+++ b/app/views/impact_stories/_form.html.erb
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+ <%= simple_form_for impact_story, html: {role: 'form', class: 'form-horizontal'} do |f| %>
+ <%= f.input :title, label: "Story Title", class: "form-control", wrapper: :input_group %>
+
+ <%= f.text_area :content, label: "Story Content", class: "form-control", wrapper: :input_group %>
+
+
+ <% end %>
+
+
+
+
We're working on adding image upload. Watch this space for updates!
+
+
+
+
+
\ No newline at end of file
diff --git a/app/views/impact_stories/_list.html.erb b/app/views/impact_stories/_list.html.erb
new file mode 100644
index 00000000..f8d2e2d9
--- /dev/null
+++ b/app/views/impact_stories/_list.html.erb
@@ -0,0 +1,21 @@
+
+
+
+ | Story Title |
+ Date Created |
+ Content |
+
+ |
+
+
+
+ <% @impact_stories.each do |story| %>
+
+ | <%= story.title %> |
+ <%= story.created_at.strftime("%B %-d %Y") %> |
+ <%= story.blurb(40) %> |
+ <%= link_to 'View Story', story, class: "btn btn-sm btn-info pull-right" %> |
+ <%= link_to 'Edit Story Details', edit_impact_story_path(story), class: "btn btn-sm btn-success pull-right" %> |
+ <% end %>
+
+
diff --git a/app/views/impact_stories/edit.html.erb b/app/views/impact_stories/edit.html.erb
new file mode 100644
index 00000000..bc9bfa67
--- /dev/null
+++ b/app/views/impact_stories/edit.html.erb
@@ -0,0 +1,27 @@
+
+
+<%= render 'form', impact_story: @impact_story %>
\ No newline at end of file
diff --git a/app/views/impact_stories/index.html.erb b/app/views/impact_stories/index.html.erb
new file mode 100644
index 00000000..33277f72
--- /dev/null
+++ b/app/views/impact_stories/index.html.erb
@@ -0,0 +1,64 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ <%= render(
+ partial: 'impact_stories/list',
+ locals: {impact_stories: @impact_stories}
+ ) %>
+
+
+
+
+
+
+
+
diff --git a/app/views/impact_stories/new.html.erb b/app/views/impact_stories/new.html.erb
new file mode 100644
index 00000000..e99f3a91
--- /dev/null
+++ b/app/views/impact_stories/new.html.erb
@@ -0,0 +1,25 @@
+
+
+<%= render 'form', impact_story: @impact_story %>
\ No newline at end of file
diff --git a/app/views/impact_stories/show.html.erb b/app/views/impact_stories/show.html.erb
new file mode 100644
index 00000000..b4794d1c
--- /dev/null
+++ b/app/views/impact_stories/show.html.erb
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+ - Story Title:
+ - <%= @impact_story.title %>
+
+ - Story Content:
+ - <%= simple_format(h(@impact_story.content)) %>
+
+
+
+
+
+
+
+
diff --git a/app/views/layouts/_sidebar.html.erb b/app/views/layouts/_sidebar.html.erb
index 61ce9690..aaf6f7a9 100644
--- a/app/views/layouts/_sidebar.html.erb
+++ b/app/views/layouts/_sidebar.html.erb
@@ -41,5 +41,11 @@
<% end %>
+
+ <%= link_to(impact_stories_path, class: "nav-link #{"active" if current_page?(impact_stories_path)}") do %>
+
+ Share Our Impact
+ <% end %>
+
\ No newline at end of file
diff --git a/config/routes.rb b/config/routes.rb
index d3ff5a2e..6f3bd4cd 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -66,6 +66,8 @@
end
end
+ resources :impact_stories, except: [:destroy]
+
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
get "pages/:name", to: "static#page", as: "static_page"
root "static#index"
diff --git a/db/migrate/20200905195722_create_impact_stories.rb b/db/migrate/20200905195722_create_impact_stories.rb
new file mode 100644
index 00000000..0d590011
--- /dev/null
+++ b/db/migrate/20200905195722_create_impact_stories.rb
@@ -0,0 +1,11 @@
+class CreateImpactStories < ActiveRecord::Migration[6.0]
+ def change
+ create_table :impact_stories do |t|
+ t.string :title, null: false
+ t.text :content, null: false
+ t.references :partner, index: true, foreign_key: true
+
+ t.timestamps
+ end
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 307fd9c3..8b4ac860 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 2020_05_18_010905) do
+ActiveRecord::Schema.define(version: 2020_09_05_195722) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -119,6 +119,15 @@
t.index ["feature_key", "key", "value"], name: "index_flipper_gates_on_feature_key_and_key_and_value", unique: true
end
+ create_table "impact_stories", force: :cascade do |t|
+ t.string "title", null: false
+ t.text "content", null: false
+ t.bigint "partner_id"
+ t.datetime "created_at", precision: 6, null: false
+ t.datetime "updated_at", precision: 6, null: false
+ t.index ["partner_id"], name: "index_impact_stories_on_partner_id"
+ end
+
create_table "item_requests", force: :cascade do |t|
t.string "name"
t.string "quantity"
@@ -273,6 +282,7 @@
add_foreign_key "child_item_requests", "item_requests"
add_foreign_key "children", "families"
add_foreign_key "families", "partners"
+ add_foreign_key "impact_stories", "partners"
add_foreign_key "item_requests", "partner_requests"
add_foreign_key "users", "partners"
end
diff --git a/spec/factories/impact_stories.rb b/spec/factories/impact_stories.rb
new file mode 100644
index 00000000..72fdd39f
--- /dev/null
+++ b/spec/factories/impact_stories.rb
@@ -0,0 +1,19 @@
+# == Schema Information
+#
+# Table name: impact_stories
+#
+# id :bigint(8) not null, primary key
+# partner_id :bigint(8)
+# title :string not null
+# content :text not null
+# created_at :datetime not null
+# updated_at :datetime not null
+#
+
+FactoryBot.define do
+ factory :impact_story do
+ title { Faker::Lorem.word }
+ content { Faker::Lorem.paragraph }
+ partner
+ end
+end
diff --git a/spec/features/impact_story_feature_spec.rb b/spec/features/impact_story_feature_spec.rb
new file mode 100644
index 00000000..a70fec43
--- /dev/null
+++ b/spec/features/impact_story_feature_spec.rb
@@ -0,0 +1,35 @@
+require "rails_helper"
+
+describe ImpactStory, type: :feature, include_shared: true, js: true do
+ let(:partner) { create(:partner, :verified, id: 3) }
+ let(:user) { create(:user, partner: partner) }
+
+ before do
+ Flipper[:impact_story_requests].enable(partner)
+ sign_in(user)
+ visit(root_path)
+ end
+
+ scenario "User can see a list of impact stories" do
+ diaper_type = "Magic diaper"
+ stub_request(:any, "#{ENV["DIAPERBANK_ENDPOINT"]}/partner_requests/#{partner.id}")
+ .to_return(body: [{ id: 1, name: diaper_type }].to_json, status: 200)
+
+ impact_stories = [
+ create(:impact_story, title: "Title1", content: "Content 1", partner: partner),
+ create(:impact_story, title: "Title2", content: "Content 2", partner: partner)
+ ].reverse
+
+ click_link "Share Our Impact"
+ impact_stories.each.with_index do |story, index|
+ within "tbody" do
+ expect(find("tr:nth-child(#{index + 1}) td:nth-child(1)"))
+ .to have_text(story.title)
+ expect(find("tr:nth-child(#{index + 1}) td:nth-child(2)"))
+ .to have_text(story.created_at.strftime("%B %-d %Y"))
+ expect(find("tr:nth-child(#{index + 1}) td:nth-child(3)"))
+ .to have_text(story.content)
+ end
+ end
+ end
+end
diff --git a/spec/models/impact_story_spec.rb b/spec/models/impact_story_spec.rb
new file mode 100644
index 00000000..abba4129
--- /dev/null
+++ b/spec/models/impact_story_spec.rb
@@ -0,0 +1,21 @@
+require 'rails_helper'
+
+RSpec.describe ImpactStory, type: :model do
+ describe 'associations' do
+ it { should belong_to(:partner).class_name('Partner') }
+ end
+
+ describe 'validations' do
+ it { should validate_presence_of(:title) }
+ it { should validate_presence_of(:content) }
+ end
+
+ describe '#blurb' do
+ subject { impact_story.blurb(10) }
+ let(:impact_story) { create(:impact_story, title: Faker::Lorem.word, content: Faker::Lorem.paragraph) }
+
+ it "returns truncates the content to less than or equal to 10 characters" do
+ expect(subject.length).to be <= 20
+ end
+ end
+end
diff --git a/spec/requests/impact_stories_request_spec.rb b/spec/requests/impact_stories_request_spec.rb
new file mode 100644
index 00000000..2a79a7c2
--- /dev/null
+++ b/spec/requests/impact_stories_request_spec.rb
@@ -0,0 +1,48 @@
+require 'rails_helper'
+
+RSpec.describe "ImpactStories", type: :request do
+ let(:partner) { create(:partner) }
+ let!(:user) { create(:user, partner: partner) }
+
+ before do
+ sign_in user
+ end
+
+ describe "GET #index" do
+ it "return http sucess" do
+ get impact_stories_path
+
+ expect(response).to have_http_status(:ok)
+ end
+ end
+
+ describe "GET #new" do
+ it "should return status code 200" do
+ get new_impact_story_path
+
+ expect(response).to have_http_status :ok
+ end
+ end
+
+ describe "POST #create" do
+ it "should create and redirect to impact_story_path" do
+ post impact_stories_path, params: { impact_story: attributes_for(:impact_story) }
+
+ impact_story = ImpactStory.select(:id).last
+
+ expect(response).to redirect_to(impact_story_path(impact_story.id))
+ expect(request.flash[:notice]).to eql "Impact Story was successfully created."
+ end
+ end
+
+ describe "PUT #update" do
+ let(:impact_story) { create(:impact_story, partner: partner) }
+
+ it "should update and redirect to impact_story_path" do
+ put impact_story_path(impact_story), params: { impact_story: attributes_for(:impact_story) }
+
+ expect(response).to redirect_to(impact_story_path(impact_story.id))
+ expect(request.flash[:notice]).to eql "Impact Story was successfully updated."
+ end
+ end
+end