[deploy] Seed profile fields (#9605)

* Fix schema.rb

* Add service objects for base and link fields

* Add link fields to seeds

* Make placeholder a keyword argument

* Add work fields

* Add explanation column to profile fields

* Add coding fields

* Switch from inheritance to mixin

* Add email checkbox to base fields

* Add branding fields

* Add spec for ProfileFields::FieldDefinition

* Move migration back into correct location

* Rename column from explanation to description

* Rename attribute in mixin

* chore: rename from explanation to description

* Add ProfileFields::ImportFromCsv

* Simplify ProfileFields::ImportFromCsv

* Add comment about disabled cop to spec

* Add TODO comment to Rake task

* Document mixin

* Add groups to profile fields

Co-authored-by: Ridhwana <ridhwana.khan16@gmail.com>
This commit is contained in:
Michael Kohl 2020-08-05 21:11:30 +07:00 committed by GitHub
parent 06a8172cd8
commit c2d23cfc4d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 215 additions and 2 deletions

View file

@ -0,0 +1,13 @@
module ProfileFields
class AddBaseFields
include FieldDefinition
group "Basic" do
field "Display email on profile", :check_box
field "Name", :text_field, placeholder: "John Doe"
field "Website URL", :text_field, placeholder: "https://yoursite.com"
field "Summary", :text_area, placeholder: "A short bio..."
field "Location", :text_field, placeholder: "Halifax, Nova Scotia"
end
end
end

View file

@ -0,0 +1,13 @@
module ProfileFields
class AddBrandingFields
include FieldDefinition
group "Branding" do
field "Brand color 1", :color_field, placeholder: "#000000", description: "Used for backgrounds, borders etc."
field "Brand color 2",
:color_field,
placeholder: "#000000",
description: "Used for texts (usually put on Brand color 1)."
end
end
end

View file

@ -0,0 +1,19 @@
module ProfileFields
class AddLinkFields
include FieldDefinition
group "Links" do
field "Facebook profile URL", :text_field, placeholder: "https://facebook.com/..."
field "Youtube URL", :text_field, placeholder: "https://www.youtube.com/channel/..."
field "StackOverflow profile URL", :text_field, placeholder: "https://stackoverflow.com/users/..."
field "LinkedIn profile URL", :text_field, placeholder: "https://www.linkedin.com/in/..."
field "Behance profile URL", :text_field, placeholder: "https://..."
field "Dribble profile URL", :text_field, placeholder: "https://dribble.com/..."
field "Medium profile URL", :text_field, placeholder: "https://..."
field "GitLab profile URL", :text_field, placeholder: "https://..."
field "Instagram profile URL", :text_field, placeholder: "https://..."
field "Mastodon profile URL", :text_field, placeholder: "https://..."
field "Twitch profile URL", :text_field, placeholder: "https://..."
end
end
end

View file

@ -0,0 +1,15 @@
module ProfileFields
class AddWorkFields
include FieldDefinition
group "Work" do
field "Education", :text_field
field "Employer name", :text_field, placeholder: "Acme Inc."
field "Employer URL", :text_field, placeholder: "https://dev.com"
field "Employment title", :text_field, placeholder: "Junior Frontend Engineer"
field "Looking for work", :check_box
field 'Display "looking for work" on profile', :check_box
field "Recruiters can contact me about job opportunities", :check_box
end
end
end

View file

@ -0,0 +1,38 @@
module ProfileFields
# This module defines a tiny DSL for declarative profile field seeders.
module FieldDefinition
extend ActiveSupport::Concern
class_methods do
def call
new.add_fields
end
def group(group = nil)
@group = group
yield if block_given?
@group = nil
end
def fields
@fields ||= []
end
private
def field(label, input_type, placeholder: nil, description: nil, group: @group)
fields << {
label: label,
input_type: input_type,
placeholder_text: placeholder,
description: description,
group: group
}.compact
end
end
def add_fields
self.class.fields.each { |field| ProfileField.create(field) }
end
end
end

View file

@ -0,0 +1,11 @@
module ProfileFields
class ImportFromCsv
HEADERS = %i[label input_type placeholder_text description group].freeze
def self.call(file)
CSV.foreach(file, headers: HEADERS, skip_blanks: true) do |row|
ProfileField.create(row.to_h)
end
end
end
end

View file

@ -33,7 +33,8 @@ chdir APP_ROOT do
puts "\n== Preparing Test Elasticsearch =="
system! 'RAILS_ENV="test" bin/rails search:setup'
system! "bin/rails app_initializer:setup"
puts "\n== Initializing the application =="
system! "bin/rails app_initializer:setup forem:setup"
puts "\n== Removing old logs and tempfiles =="
system! "bin/rails log:clear tmp:clear"

View file

@ -0,0 +1,5 @@
class AddDescriptionToProfileFields < ActiveRecord::Migration[6.0]
def change
add_column :profile_fields, :description, :string
end
end

View file

@ -0,0 +1,5 @@
class AddGroupToProfileFields < ActiveRecord::Migration[6.0]
def change
add_column :profile_fields, :group, :string
end
end

View file

@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 2020_07_31_041554) do
ActiveRecord::Schema.define(version: 2020_08_05_050048) do
# These are extensions that must be enabled in order to support this database
enable_extension "citext"
@ -924,6 +924,8 @@ ActiveRecord::Schema.define(version: 2020_07_31_041554) do
create_table "profile_fields", force: :cascade do |t|
t.boolean "active", default: true, null: false
t.datetime "created_at", precision: 6, null: false
t.string "description"
t.string "group"
t.integer "input_type", default: 0, null: false
t.citext "label", null: false
t.string "placeholder_text"

View file

@ -492,6 +492,18 @@ seeder.create_if_none(Page) do
end
##############################################################################
seeder.create_if_none(ProfileField) do
ProfileFields::AddBaseFields.call
ProfileFields::AddLinkFields.call
ProfileFields::AddWorkFields.call
coding_fields_csv = Rails.root.join("lib/data/coding_profile_fields.csv")
ProfileFields::ImportFromCsv.call(coding_fields_csv)
ProfileFields::AddBrandingFields.call
end
##############################################################################
puts <<-ASCII
```````````````````````````````````````````````````````````````````````````

View file

@ -0,0 +1,4 @@
Skills/Languages,text_area,,What tools and languages are you most experienced with? Are you specialized or more of a generalist?,Coding
I'm getting into,text_area,,What are you learning right now? What are the new tools and languages you're picking up right now?,Coding
My projects and hacks,text_area,,What projects are currently occupying most of your time?,Coding
Available for,text_area,,What kinds of collaborations or discussions are you available for? What's a good reason to say Hey! to you these days?,Coding
1 Skills/Languages text_area What tools and languages are you most experienced with? Are you specialized or more of a generalist? Coding
2 I'm getting into text_area What are you learning right now? What are the new tools and languages you're picking up right now? Coding
3 My projects and hacks text_area What projects are currently occupying most of your time? Coding
4 Available for text_area What kinds of collaborations or discussions are you available for? What's a good reason to say Hey! to you these days? Coding

9
lib/tasks/forem.rake Normal file
View file

@ -0,0 +1,9 @@
namespace :forem do
desc "Performs basic setup for new Forem instances"
task setup: :environment do
puts "\n== Setting up profile fields =="
# TODO: [@forem/oss] Remove the destroy_all call
ProfileField.destroy_all
ProfileFields::AddBaseFields.call
end
end

View file

@ -0,0 +1,4 @@
Name,text_field,John Doe,,Basic
Skills/Languages,text_area,,Programming languages,Coding
Color,color_field,#000000,"Used for backgrounds, borders etc.",Branding
1 Name text_field John Doe Basic
2 Skills/Languages text_area Programming languages Coding
3 Color color_field #000000 Used for backgrounds, borders etc. Branding

View file

@ -0,0 +1,24 @@
require "rails_helper"
RSpec.describe ProfileFields::FieldDefinition, type: :service do
let(:test_class) do
Class.new do
include ProfileFields::FieldDefinition
group "Test" do
field "Test 1", :text_area, placeholder: "Test", description: "For testing"
field "Test 2", :check_box
end
end
end
context "when adding fields" do
it "creates all the profile fields in the DB", :aggregate_failures do
expect do
test_class.call
end.to change(ProfileField, :count).by(2)
expect(ProfileField.pluck(:label)).to match_array(["Test 1", "Test 2"])
expect(ProfileField.pluck(:group)).to match_array(%w[Test Test])
end
end
end

View file

@ -0,0 +1,38 @@
require "rails_helper"
RSpec.describe ProfileFields::ImportFromCsv do
# Importing is slow, so we only do it once and then clean up after outselves.
# rubocop:disable RSpec/BeforeAfterAll
before(:all) { described_class.call(file_fixture("profile_fields.csv")) }
after(:all) { ProfileField.destroy_all }
# rubocop:enable RSpec/BeforeAfterAll
it "ignores empty lines" do
expect(ProfileField.count).to eq 3
end
it "handles missing descriptions", :aggregate_failures do
field = ProfileField.find_by!(label: "Name")
expect(field.input_type).to eq "text_field"
expect(field.placeholder_text).to eq "John Doe"
expect(field.description).to be_nil
expect(field.group).to eq "Basic"
end
it "handles missing placeholder_texts", :aggregate_failures do
field = ProfileField.find_by!(label: "Skills/Languages")
expect(field.input_type).to eq "text_area"
expect(field.placeholder_text).to be_nil
expect(field.description).to eq "Programming languages"
expect(field.group).to eq "Coding"
end
it "handles commas in correctly quoted fields", :aggregate_failures do
field = ProfileField.find_by!(label: "Color")
expect(field.input_type).to eq "color_field"
expect(field.placeholder_text).to eq "#000000"
expect(field.description).to eq "Used for backgrounds, borders etc."
expect(field.group).to eq "Branding"
end
end