We're contacting you to notify you that your password has been changed.
4 |
--------------------------------------------------------------------------------
/test/fixtures/like_logs.yml:
--------------------------------------------------------------------------------
1 | # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
2 |
3 | one:
4 | gate:
5 |
6 | two:
7 | gate:
8 |
--------------------------------------------------------------------------------
/test/models/like_log_test.rb:
--------------------------------------------------------------------------------
1 | require 'test_helper'
2 |
3 | class LikeLogTest < ActiveSupport::TestCase
4 | # test "the truth" do
5 | # assert true
6 | # end
7 | end
8 |
--------------------------------------------------------------------------------
/db/migrate/20180625015132_add_role_to_users.rb:
--------------------------------------------------------------------------------
1 | class AddRoleToUsers < ActiveRecord::Migration[5.2]
2 | def change
3 | add_column :users, :role, :integer
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20180621062526_add_server_to_gates.rb:
--------------------------------------------------------------------------------
1 | class AddServerToGates < ActiveRecord::Migration[5.2]
2 | def change
3 | add_column :gates, :server, :string
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20180625011954_drop_table_to_admins.rb:
--------------------------------------------------------------------------------
1 | class DropTableToAdmins < ActiveRecord::Migration[5.2]
2 | def change
3 | drop_table :admins, if_exists: true
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20180625012358_drop_table_to_users.rb:
--------------------------------------------------------------------------------
1 | class DropTableToUsers < ActiveRecord::Migration[5.2]
2 | def change
3 | drop_table :users, if_exists: true
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20180625014756_create_table_users.rb:
--------------------------------------------------------------------------------
1 | class CreateTableUsers < ActiveRecord::Migration[5.2]
2 | def change
3 | create_table :users do |t|
4 | end
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/db/migrate/20180625082359_add_user_id_to_gates.rb:
--------------------------------------------------------------------------------
1 | class AddUserIdToGates < ActiveRecord::Migration[5.2]
2 | def change
3 | add_column :gates, :user_id, :integer
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/config.ru:
--------------------------------------------------------------------------------
1 | # This file is used by Rack-based servers to start the application.
2 |
3 | require_relative 'config/environment'
4 | require 'bootstrap-sass'
5 |
6 |
7 | run Rails.application
8 |
--------------------------------------------------------------------------------
/db/migrate/20180621062645_add_like_to_gates.rb:
--------------------------------------------------------------------------------
1 | class AddLikeToGates < ActiveRecord::Migration[5.2]
2 | def change
3 | add_column :gates, :like, :integer ,default:0
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/app/models/like_log.rb:
--------------------------------------------------------------------------------
1 | class LikeLog < ApplicationRecord
2 | belongs_to :gate
3 | belongs_to :user, foreign_key: 'who_liked'
4 |
5 | scope :by, ->(user) { where(user: user) }
6 | end
--------------------------------------------------------------------------------
/app/views/admin/_header.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
<%= link_to '檢視網站', root_path %>
4 |
<%= sign_button %>
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # README
2 |
3 | MoonGate is a Discord sharing web app. let discord users could easily join and share discord server.
4 |
5 | Now the app is serving on https://moongateapp.herokuapp.com/
6 |
--------------------------------------------------------------------------------
/app/views/admin/gates/new.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 | <% if @resource.try(:unconfirmed_email?) %>
4 |
We're contacting you to notify you that your email is being changed to <%= @resource.unconfirmed_email %>.
5 | <% else %>
6 |
We're contacting you to notify you that your email has been changed to <%= @resource.email %>.
7 | <% end %>
8 |
--------------------------------------------------------------------------------
/app/assets/javascripts/admin.js:
--------------------------------------------------------------------------------
1 | function toggle_checkall(field_name, state) {
2 | var checkboxes = document.getElementsByTagName('input');
3 | var count = checkboxes.length;
4 | for (var i = 0; i< count; i++) {
5 | if (checkboxes[i].type == "checkbox" && checkboxes[i].name == field_name + "_ids[]") {
6 | checkboxes[i].checked = state;
7 | };
8 | };
9 | };
--------------------------------------------------------------------------------
/app/controllers/admin/base_controller.rb:
--------------------------------------------------------------------------------
1 | module Admin
2 | class BaseController < ApplicationController
3 | layout 'admin'
4 | before_action :authenticate_user!
5 | before_action :verify_admin
6 |
7 | private
8 |
9 | def verify_admin
10 | return if current_user.admin?
11 | redirect_to root_path, alert: "Your are not admin!"
12 | end
13 | end
14 | end
15 |
--------------------------------------------------------------------------------
/test/fixtures/users.yml:
--------------------------------------------------------------------------------
1 | # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
2 |
3 | # This model initially had no columns defined. If you add columns to the
4 | # model remove the '{}' from the fixture names and add the columns immediately
5 | # below each fixture, per the syntax in the comments below
6 | #
7 | one: {}
8 | # column: value
9 | #
10 | two: {}
11 | # column: value
12 |
--------------------------------------------------------------------------------
/app/assets/javascripts/cable.js:
--------------------------------------------------------------------------------
1 | // Action Cable provides the framework to deal with WebSockets in Rails.
2 | // You can generate new channels where WebSocket features live using the `rails generate channel` command.
3 | //
4 | //= require action_cable
5 | //= require_self
6 | //= require_tree ./channels
7 |
8 | (function() {
9 | this.App || (this.App = {});
10 |
11 | App.cable = ActionCable.createConsumer();
12 |
13 | }).call(this);
14 |
--------------------------------------------------------------------------------
/config/initializers/backtrace_silencers.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
4 | # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
5 |
6 | # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
7 | # Rails.backtrace_cleaner.remove_silencers!
8 |
--------------------------------------------------------------------------------
/app/views/devise/mailer/reset_password_instructions.html.erb:
--------------------------------------------------------------------------------
1 |
Hello <%= @resource.email %>!
2 |
3 |
Someone has requested a link to change your password. You can do this through the link below.
4 |
5 |
<%= link_to 'Change my password', edit_password_url(@resource, reset_password_token: @token) %>
6 |
7 |
If you didn't request this, please ignore this email.
8 |
Your password won't change until you access the link above and create a new one.
14 | <% end %>
15 |
16 | <%= render "devise/shared/links" %>
17 |
--------------------------------------------------------------------------------
/config/routes.rb:
--------------------------------------------------------------------------------
1 | Rails.application.routes.draw do
2 | root to: 'gates#index'
3 |
4 | devise_for :users
5 | # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
6 | resources :gates do
7 | collection do
8 | get :search_tag
9 | get :manage
10 | get :join_server
11 | end
12 | resource :like, only: [:create, :destroy]
13 | end
14 |
15 |
16 | namespace :admin do
17 | resources :gates
18 | resources :users
19 | root action: 'dashboard'
20 | get :manage_gates
21 | get :manage_users
22 | delete :destroy_mutiple
23 | delete :destroy_mutiple_user
24 | end
25 | end
26 |
--------------------------------------------------------------------------------
/config/database.yml:
--------------------------------------------------------------------------------
1 | # SQLite version 3.x
2 | # gem install sqlite3
3 | #
4 | # Ensure the SQLite 3 gem is defined in your Gemfile
5 | # gem 'sqlite3'
6 | #
7 | default: &default
8 | adapter: postgresql
9 | pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
10 | timeout: 5000
11 |
12 | development:
13 | <<: *default
14 | database: db/development
15 |
16 | # Warning: The database defined as "test" will be erased and
17 | # re-generated from your development database when you run "rake".
18 | # Do not set this db to the same as development or production.
19 | test:
20 | <<: *default
21 | database: db/test
22 |
23 | production:
24 | <<: *default
25 | database: db/production
26 |
--------------------------------------------------------------------------------
/app/assets/javascripts/gates.coffee:
--------------------------------------------------------------------------------
1 | # Place all the behaviors and hooks related to the matching controller here.
2 | # All this logic will automatically be available in application.js.
3 | # You can use CoffeeScript in this file: http://coffeescript.org/
4 |
5 |
6 | # $(document).on 'turbolinks:before-cache', ->
7 | # $('body').hide()
8 |
9 | # $(document).on "turbolinks:load", ->
10 | # $('body').hide().delay(300).fadeIn('slow')
11 |
12 |
13 | $(window).scroll ->
14 | url = $('.pagination .next a').attr('href')
15 |
16 | if url && $(window).scrollTop() > $(document).height() - $(window).height() - 600
17 | $('.pagination').text("Loading...")
18 | $.getScript(url)
19 |
--------------------------------------------------------------------------------
/config/initializers/assets.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Version of your assets, change this if you want to expire all your assets.
4 | Rails.application.config.assets.version = '1.0'
5 |
6 | # Add additional assets to the asset load path.
7 | # Rails.application.config.assets.paths << Emoji.images_path
8 | # Add Yarn node_modules folder to the asset load path.
9 | Rails.application.config.assets.paths << Rails.root.join('node_modules')
10 |
11 | # Precompile additional assets.
12 | # application.js, application.css, and all non-JS/CSS in the app/assets
13 | # folder are already added.
14 | # Rails.application.config.assets.precompile += %w( admin.js admin.css )
15 |
--------------------------------------------------------------------------------
/db/migrate/20180628023513_change_collation_for_tag_names.acts_as_taggable_on_engine.rb:
--------------------------------------------------------------------------------
1 | # This migration comes from acts_as_taggable_on_engine (originally 5)
2 | # This migration is added to circumvent issue #623 and have special characters
3 | # work properly
4 | if ActiveRecord.gem_version >= Gem::Version.new('5.0')
5 | class ChangeCollationForTagNames < ActiveRecord::Migration[4.2]; end
6 | else
7 | class ChangeCollationForTagNames < ActiveRecord::Migration; end
8 | end
9 | ChangeCollationForTagNames.class_eval do
10 | def up
11 | if ActsAsTaggableOn::Utils.using_mysql?
12 | execute("ALTER TABLE tags MODIFY name varchar(255) CHARACTER SET utf8 COLLATE utf8_bin;")
13 | end
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/db/seeds.rb:
--------------------------------------------------------------------------------
1 | # This file should contain all the record creation needed to seed the database with its default values.
2 | # The data can then be loaded with the rails db:seed command (or created alongside the database with db:setup).
3 | #
4 | # Examples:
5 | #
6 | # movies = Movie.create([{ name: 'Star Wars' }, { name: 'Lord of the Rings' }])
7 | # Character.create(name: 'Luke', movie: movies.first)
8 |
9 | if Rails.env == "development"
10 | 500.times do |fake|
11 | Gate.create!(:name => Faker::Lorem.word , :intro => Faker::Lorem.sentence(20, true),:intro_detail => Faker::Lorem.sentence(150, true), user_id:1 , server:"463954073876692992",:tag => Faker::Food.dish, is_public:"1" )
12 | end
13 | end
14 |
15 |
--------------------------------------------------------------------------------
/app/views/layouts/admin.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | MoonGate月門
5 | <%= csrf_meta_tags %>
6 | <%= csp_meta_tag %>
7 | <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
8 | <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
9 |
10 |
11 |
12 |
13 |
<%= render 'admin/header' %>
14 |
<%= render 'admin/sidebar' %>
15 |
<%= yield %>
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/config/initializers/inflections.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Add new inflection rules using the following format. Inflections
4 | # are locale specific, and you may define rules for as many different
5 | # locales as you wish. All of these examples are active by default:
6 | # ActiveSupport::Inflector.inflections(:en) do |inflect|
7 | # inflect.plural /^(ox)$/i, '\1en'
8 | # inflect.singular /^(ox)en/i, '\1'
9 | # inflect.irregular 'person', 'people'
10 | # inflect.uncountable %w( fish sheep )
11 | # end
12 |
13 | # These inflection rules are supported but not enabled by default:
14 | # ActiveSupport::Inflector.inflections(:en) do |inflect|
15 | # inflect.acronym 'RESTful'
16 | # end
17 |
--------------------------------------------------------------------------------
/app/views/layouts/application.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | MoonGate月門
5 | <%= csrf_meta_tags %>
6 | <%= csp_meta_tag %>
7 | <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
8 | <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
9 |
10 |
11 |
12 |
42 |
43 | <%= link_to "回上一頁", :back %>
44 |
--------------------------------------------------------------------------------
/config/puma.rb:
--------------------------------------------------------------------------------
1 | # Puma can serve each request in a thread from an internal thread pool.
2 | # The `threads` method setting takes two numbers: a minimum and maximum.
3 | # Any libraries that use thread pools should be configured to match
4 | # the maximum value specified for Puma. Default is set to 5 threads for minimum
5 | # and maximum; this matches the default thread size of Active Record.
6 | #
7 | threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }
8 | threads threads_count, threads_count
9 |
10 | # Specifies the `port` that Puma will listen on to receive requests; default is 3000.
11 | #
12 | port ENV.fetch("PORT") { 3000 }
13 |
14 | # Specifies the `environment` that Puma will run in.
15 | #
16 | environment ENV.fetch("RAILS_ENV") { "development" }
17 |
18 | # Specifies the number of `workers` to boot in clustered mode.
19 | # Workers are forked webserver processes. If using threads and workers together
20 | # the concurrency of the application would be max `threads` * `workers`.
21 | # Workers do not work on JRuby or Windows (both of which do not support
22 | # processes).
23 | #
24 | # workers ENV.fetch("WEB_CONCURRENCY") { 2 }
25 |
26 | # Use the `preload_app!` method when specifying a `workers` number.
27 | # This directive tells Puma to first boot the application and load code
28 | # before forking the application. This takes advantage of Copy On Write
29 | # process behavior so workers use less memory.
30 | #
31 | # preload_app!
32 |
33 | # Allow puma to be restarted by `rails restart` command.
34 | plugin :tmp_restart
35 |
--------------------------------------------------------------------------------
/app/views/admin/manage_gates.html.erb:
--------------------------------------------------------------------------------
1 | <%= form_tag admin_manage_gates_path, method:"get" do %>
2 | <%= text_field_tag :search, params[:search], placeholder:"搜尋..." %>
3 | <% end %>
4 |
5 |
41 |
--------------------------------------------------------------------------------
/app/uploaders/image_uploader.rb:
--------------------------------------------------------------------------------
1 | class ImageUploader < CarrierWave::Uploader::Base
2 | # using Cloudinary as storage database
3 | include Cloudinary::CarrierWave
4 | # Choose what kind of storage to use for this uploader:
5 |
6 | process :convert => 'png'
7 | process :tags => ["MoonGate_pics"]
8 |
9 | # Override the directory where uploaded files will be stored.
10 | # This is a sensible default for uploaders that are meant to be mounted:
11 | def store_dir
12 | "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
13 | end
14 |
15 | version :standard do
16 | process resize_to_fill: [200,200, :north]
17 | end
18 |
19 | version :thumb do
20 | process resize_to_fit: [50,50]
21 | end
22 |
23 | # Provide a default URL as a default if there hasn't been a file uploaded:
24 | # def default_url(*args)
25 | # # For Rails 3.1+ asset pipeline compatibility:
26 | # # ActionController::Base.helpers.asset_path("fallback/" + [version_name, "default.png"].compact.join('_'))
27 | #
28 | # "/images/fallback/" + [version_name, "default.png"].compact.join('_')
29 | # end
30 |
31 | # Process files as they are uploaded:
32 | # process scale: [200, 300]
33 | #
34 | # def scale(width, height)
35 | # # do something
36 | # end
37 |
38 | # Create different versions of your uploaded files:
39 | # version :thumb do
40 | # process resize_to_fit: [50, 50]
41 | # end
42 |
43 | # Add a white list of extensions which are allowed to be uploaded.
44 | # For images you might use something like this:
45 | def extension_whitelist
46 | %w(jpg jpeg png)
47 | end
48 |
49 | # Override the filename of the uploaded files:
50 | # Avoid using model.id or version_name here, see uploader/store.rb for details.
51 | # def filename
52 | # "something.jpg" if original_filename
53 | # end
54 | end
55 |
--------------------------------------------------------------------------------
/public/500.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | We're sorry, but something went wrong (500)
5 |
6 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
We're sorry, but something went wrong.
62 |
63 |
If you are the application owner check the logs for more information.
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/db/migrate/20180625014839_add_devise_to_users.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class AddDeviseToUsers < ActiveRecord::Migration[5.2]
4 | def self.up
5 | change_table :users do |t|
6 | ## Database authenticatable
7 | t.string :email, null: false, default: ""
8 | t.string :encrypted_password, null: false, default: ""
9 |
10 | ## Recoverable
11 | t.string :reset_password_token
12 | t.datetime :reset_password_sent_at
13 |
14 | ## Rememberable
15 | t.datetime :remember_created_at
16 |
17 | ## Trackable
18 | t.integer :sign_in_count, default: 0, null: false
19 | t.datetime :current_sign_in_at
20 | t.datetime :last_sign_in_at
21 | t.inet :current_sign_in_ip
22 | t.inet :last_sign_in_ip
23 |
24 | ## Confirmable
25 | # t.string :confirmation_token
26 | # t.datetime :confirmed_at
27 | # t.datetime :confirmation_sent_at
28 | # t.string :unconfirmed_email # Only if using reconfirmable
29 |
30 | ## Lockable
31 | # t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
32 | # t.string :unlock_token # Only if unlock strategy is :email or :both
33 | # t.datetime :locked_at
34 |
35 |
36 | # Uncomment below if timestamps were not included in your original model.
37 | # t.timestamps null: false
38 | end
39 |
40 | add_index :users, :email, unique: true
41 | add_index :users, :reset_password_token, unique: true
42 | # add_index :users, :confirmation_token, unique: true
43 | # add_index :users, :unlock_token, unique: true
44 | end
45 |
46 | def self.down
47 | # By default, we don't want to make any assumption about how to roll back a migration when your
48 | # model already existed. Please edit below which fields you would like to remove in this migration.
49 | raise ActiveRecord::IrreversibleMigration
50 | end
51 | end
52 |
--------------------------------------------------------------------------------
/public/422.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | The change you wanted was rejected (422)
5 |
6 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
The change you wanted was rejected.
62 |
Maybe you tried to change something you didn't have access to.
63 |
64 |
If you are the application owner check the logs for more information.
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/public/404.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | The page you were looking for doesn't exist (404)
5 |
6 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
The page you were looking for doesn't exist.
62 |
You may have mistyped the address or the page may have moved.
63 |
64 |
If you are the application owner check the logs for more information.
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/config/environments/test.rb:
--------------------------------------------------------------------------------
1 | Rails.application.configure do
2 | # Settings specified here will take precedence over those in config/application.rb.
3 |
4 | # The test environment is used exclusively to run your application's
5 | # test suite. You never need to work with it otherwise. Remember that
6 | # your test database is "scratch space" for the test suite and is wiped
7 | # and recreated between test runs. Don't rely on the data there!
8 | config.cache_classes = true
9 |
10 | # Do not eager load code on boot. This avoids loading your whole application
11 | # just for the purpose of running a single test. If you are using a tool that
12 | # preloads Rails for running tests, you may have to set it to true.
13 | config.eager_load = false
14 |
15 | # Configure public file server for tests with Cache-Control for performance.
16 | config.public_file_server.enabled = true
17 | config.public_file_server.headers = {
18 | 'Cache-Control' => "public, max-age=#{1.hour.to_i}"
19 | }
20 |
21 | # Show full error reports and disable caching.
22 | config.consider_all_requests_local = true
23 | config.action_controller.perform_caching = false
24 |
25 | # Raise exceptions instead of rendering exception templates.
26 | config.action_dispatch.show_exceptions = false
27 |
28 | # Disable request forgery protection in test environment.
29 | config.action_controller.allow_forgery_protection = false
30 |
31 | # Store uploaded files on the local file system in a temporary directory
32 | config.active_storage.service = :test
33 |
34 | config.action_mailer.perform_caching = false
35 |
36 | # Tell Action Mailer not to deliver emails to the real world.
37 | # The :test delivery method accumulates sent emails in the
38 | # ActionMailer::Base.deliveries array.
39 | config.action_mailer.delivery_method = :test
40 |
41 | # Print deprecation notices to the stderr.
42 | config.active_support.deprecation = :stderr
43 |
44 | # Raises error for missing translations
45 | # config.action_view.raise_on_missing_translations = true
46 | end
47 |
--------------------------------------------------------------------------------
/Guardfile:
--------------------------------------------------------------------------------
1 | # A sample Guardfile
2 | # More info at https://github.com/guard/guard#readme
3 |
4 | ## Uncomment and set this to only include directories you want to watch
5 | # directories %w(app lib config test spec features) \
6 | # .select{|d| Dir.exists?(d) ? d : UI.warning("Directory #{d} does not exist")}
7 |
8 | ## Note: if you are using the `directories` clause above and you are not
9 | ## watching the project directory ('.'), then you will want to move
10 | ## the Guardfile to a watched dir and symlink it back, e.g.
11 | #
12 | # $ mkdir config
13 | # $ mv Guardfile config/
14 | # $ ln -s config/Guardfile .
15 | #
16 | # and, you'll have to watch "config/Guardfile" instead of "Guardfile"
17 |
18 | guard 'livereload' do
19 | extensions = {
20 | css: :css,
21 | scss: :css,
22 | sass: :css,
23 | js: :js,
24 | coffee: :js,
25 | html: :html,
26 | png: :png,
27 | gif: :gif,
28 | jpg: :jpg,
29 | jpeg: :jpeg,
30 | # less: :less, # uncomment if you want LESS stylesheets done in browser
31 |
32 | notify: true, # default false
33 |
34 | host: '127.0.0.1', # default '0.0.0.0'
35 |
36 | port: '3000', # default '35729'
37 |
38 | apply_css_live: true, # default true
39 |
40 | override_url: true, # default false
41 |
42 | grace_period: 0.5 , # default 0 (seconds)
43 |
44 | js_template: './my_livereload.js.erb' # default is livereload.js.erb from gem
45 | }
46 |
47 | rails_view_exts = %w(erb haml slim)
48 |
49 | # file types LiveReload may optimize refresh for
50 | compiled_exts = extensions.values.uniq
51 | watch(%r{public/.+\.(#{compiled_exts * '|'})})
52 |
53 | extensions.each do |ext, type|
54 | watch(%r{
55 | (?:app|vendor)
56 | (?:/assets/\w+/(?[^.]+) # path+base without extension
57 | (?\.#{ext})) # matching extension (must be first encountered)
58 | (?:\.\w+|$) # other extensions
59 | }x) do |m|
60 | path = m[1]
61 | "/assets/#{path}.#{type}"
62 | end
63 | end
64 |
65 | # file needing a full reload of the page anyway
66 | watch(%r{app/views/.+\.(#{rails_view_exts * '|'})$})
67 | watch(%r{app/helpers/.+\.rb})
68 | watch(%r{config/locales/.+\.yml})
69 | end
70 |
--------------------------------------------------------------------------------
/app/helpers/gates_helper.rb:
--------------------------------------------------------------------------------
1 | module GatesHelper
2 | # 如果使用者為登入狀態,就顯示登出按鈕,否則顯示登入按鈕
3 | def sign_button
4 | if user_signed_in?
5 | @name = current_user[:email].split("@")
6 | link_to content_tag(:i, " 會員登出 ( #{@name[0]} )", class:"fa fa-user"), destroy_user_session_path, method: "delete"
7 | else
8 | link_to content_tag(:i," 會員登入",class:"fa fa-user"), user_session_path
9 | end
10 | end
11 |
12 | # 顯示喜愛月門按鈕
13 | def like_gate_button(gate)
14 | if user_signed_in?
15 | if gate.like_logs.by(current_user).exists?
16 | link_to content_tag(:i, gate.like_logs.size, class:"fa fa-heart").html_safe, gate_like_path(gate), method: :delete, class:"btn-tag-like"
17 | else
18 | link_to content_tag(:i, gate.like_logs.size, class:"fa fa-heart-o").html_safe, gate_like_path(gate), method: :post, class:"btn-tag-like"
19 | end
20 | else
21 | link_to content_tag(:i, gate.like_logs.size, class:"fa fa-heart-o").html_safe, user_session_path, class:"btn-tag-like"
22 | end
23 | end
24 |
25 |
26 | # 檢查是否為 gate 擁有者 id 與登入者 id 是否相同
27 | def gate_owner?(gate)
28 | if gate[:user_id] == current_user[:id]
29 | flash[:notice] = "你有權限編輯!"
30 | else
31 | flash[:notice] = "權限不足!"
32 | redirect_to gates_path
33 | false
34 | end
35 | end
36 |
37 | #顯示月門相關標籤
38 | def search_tag_button(tag_list)
39 | @a = 1
40 | tag_list.each do |tag|
41 | if @a < (tag_list.length)
42 | concat link_to(tag, search_tag_gates_path(search_word: tag.to_s), class:"btn-tag") + " "
43 | @a += 1
44 | else
45 | concat link_to(tag, search_tag_gates_path(search_word: tag.to_s), class:"btn-tag ")
46 | end
47 | end
48 | end
49 |
50 | #未登錄時顯示註冊按鈕
51 | def register_button
52 | link_to content_tag(:i," 會員註冊",class:"fa fa-address-card"), new_user_registration_path unless user_signed_in?
53 | end
54 |
55 | def show_gate_icon(gate)
56 | if gate.icon.to_s.empty?
57 | image_tag("default_gate_icon.jpg",class:"gate-icon")
58 | else
59 | link_to cl_image_tag(gate.icon, width:50, height:50, radius:"max" ),gate_path(gate),target:"_blank"
60 | end
61 | end
62 |
63 | def show_add_gate_tip
64 | "您目前尚未擁有月門,請點選新增月門按鈕" if current_user.gates.count == 0
65 | end
66 | end
67 |
--------------------------------------------------------------------------------
/config/environments/development.rb:
--------------------------------------------------------------------------------
1 | Rails.application.configure do
2 | # Settings specified here will take precedence over those in config/application.rb.
3 |
4 | # In the development environment your application's code is reloaded on
5 | # every request. This slows down response time but is perfect for development
6 | # since you don't have to restart the web server when you make code changes.
7 | config.cache_classes = false
8 |
9 | # Do not eager load code on boot.
10 | config.eager_load = false
11 |
12 | # Show full error reports.
13 | config.consider_all_requests_local = true
14 |
15 | # Enable/disable caching. By default caching is disabled.
16 | # Run rails dev:cache to toggle caching.
17 | if Rails.root.join('tmp', 'caching-dev.txt').exist?
18 | config.action_controller.perform_caching = true
19 |
20 | config.cache_store = :memory_store
21 | config.public_file_server.headers = {
22 | 'Cache-Control' => "public, max-age=#{2.days.to_i}"
23 | }
24 | else
25 | config.action_controller.perform_caching = false
26 |
27 | config.cache_store = :null_store
28 | end
29 |
30 | # Store uploaded files on the local file system (see config/storage.yml for options)
31 | config.active_storage.service = :local
32 |
33 | # Don't care if the mailer can't send.
34 | config.action_mailer.raise_delivery_errors = false
35 |
36 | config.action_mailer.perform_caching = false
37 |
38 | # Print deprecation notices to the Rails logger.
39 | config.active_support.deprecation = :log
40 |
41 | # Raise an error on page load if there are pending migrations.
42 | config.active_record.migration_error = :page_load
43 |
44 | # Highlight code that triggered database queries in logs.
45 | config.active_record.verbose_query_logs = true
46 |
47 | # Debug mode disables concatenation and preprocessing of assets.
48 | # This option may cause significant delays in view rendering with a large
49 | # number of complex assets.
50 | config.assets.debug = true
51 |
52 | # Suppress logger output for asset requests.
53 | config.assets.quiet = true
54 |
55 | # Raises error for missing translations
56 | # config.action_view.raise_on_missing_translations = true
57 |
58 | # Use an evented file watcher to asynchronously detect changes in source code,
59 | # routes, locales, etc. This feature depends on the listen gem.
60 | config.file_watcher = ActiveSupport::EventedFileUpdateChecker
61 |
62 | # for Devise registration testing
63 | config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
64 | end
65 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 | git_source(:github) { |repo| "https://github.com/#{repo}.git" }
3 |
4 | ruby '2.3.7'
5 |
6 | # Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
7 | gem 'rails', '~> 5.2.0'
8 |
9 | # Use Puma as the app server
10 | gem 'puma', '~> 3.11'
11 | # Use SCSS for stylesheets
12 | gem 'sass-rails', '~> 5.0'
13 | # Use Uglifier as compressor for JavaScript assets
14 | gem 'uglifier', '>= 1.3.0'
15 | # See https://github.com/rails/execjs#readme for more supported runtimes
16 | # gem 'mini_racer', platforms: :ruby
17 |
18 | # Use CoffeeScript for .coffee assets and views
19 | gem 'coffee-rails', '~> 4.2'
20 | # Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks
21 | gem 'turbolinks', '~> 5'
22 | # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
23 | gem 'jbuilder', '~> 2.5'
24 | # Use Redis adapter to run Action Cable in production
25 | # gem 'redis', '~> 4.0'
26 | # Use ActiveModel has_secure_password
27 | # gem 'bcrypt', '~> 3.1.7'
28 |
29 | # Use ActiveStorage variant
30 | # gem 'mini_magick', '~> 4.8'
31 |
32 | # Use Capistrano for deployment
33 | # gem 'capistrano-rails', group: :development
34 |
35 | # using Datebase postgresql
36 | gem 'pg', '~> 0.19.0'
37 |
38 | gem 'devise'
39 |
40 | # using simple form
41 | gem 'simple_form'
42 |
43 | # using bootstrap
44 | gem 'bootstrap-sass', '~> 3.3.7'
45 | gem 'jquery-rails'
46 | gem "font-awesome-rails"
47 |
48 | # using tagging plug-in
49 | gem 'acts-as-taggable-on', '~> 6.0'
50 |
51 | # for uploading and resize images
52 | gem 'carrierwave'
53 | gem 'cloudinary'
54 |
55 | # divide pages
56 | gem 'kaminari'
57 |
58 | # Reduces boot times through caching; required in config/boot.rb
59 | gem 'bootsnap', '>= 1.1.0', require: false
60 |
61 |
62 |
63 | group :development, :test do
64 | # Call 'byebug' anywhere in the code to stop execution and get a debugger console
65 | gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
66 | end
67 |
68 | group :development do
69 | # Access an interactive console on exception pages or by calling 'console' anywhere in the code.
70 | gem 'web-console', '>= 3.3.0'
71 | gem 'listen', '>= 3.0.5', '< 3.2'
72 | # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
73 | gem 'spring'
74 | gem 'spring-watcher-listen', '~> 2.0.0'
75 | gem 'guard-livereload', '~> 2.5', require: false
76 |
77 | # Generate testing data
78 | gem 'faker'
79 |
80 | gem 'pry-rails'
81 |
82 | end
83 |
84 | group :test do
85 | # Adds support for Capybara system testing and selenium driver
86 | gem 'capybara', '>= 2.15', '< 4.0'
87 | gem 'selenium-webdriver'
88 | # Easy installation and use of chromedriver to run system tests with Chrome
89 | gem 'chromedriver-helper'
90 | end
91 |
--------------------------------------------------------------------------------
/app/controllers/gates_controller.rb:
--------------------------------------------------------------------------------
1 | class GatesController < ApplicationController
2 | before_action :authenticate_user! ,only: [:edit, :destory , :new, :create, :manage]
3 | before_action :find_gate_id, except: [:index, :show, :new, :create, :search_tag, :manage, :join_server ]
4 |
5 | # 將 Gate Model 資料傳進實體變數 @gates
6 | def index
7 | @gates = Gate.public_server.includes(:user, :like_logs, :taggings, :tags)
8 | @gates = @gates.left_joins(:like_logs).group(:id).order('COUNT(like_logs.id)DESC').page(params[:page]).per(9)
9 | @tags = ActsAsTaggableOn::Tag.most_used(20)
10 | end
11 |
12 | def show
13 | @gate = Gate.public_server.find(params[:id])
14 | end
15 |
16 | # 在 Controller 設定實體變數 @gate 給 view 的 form_for 使用
17 | def new
18 | @gate = Gate.new
19 | end
20 |
21 | # 將已過濾的資料存進實體變數 @gate 當中
22 | def create
23 | @gate = Gate.new(gate_params)
24 | @gate.user_id = current_user[:id]
25 |
26 | if @gate.save
27 | redirect_to manage_gates_path, :flash =>{success:'新增成功!'}
28 | else
29 | # 儲存失敗時借用 new 方法的頁面,不使用 redirect_to 方法使用者在輸入時的資料不會消失
30 | render :new, :flash =>{success:'新增失敗!'}
31 | end
32 | end
33 |
34 | # 取出 Gate 資料中 id 是 params[:id] 的資料
35 | def edit
36 | end
37 |
38 | def update
39 | if @gate.update(gate_params)
40 | @gate.tag_list.add(params[:tag])
41 | @gate.save
42 | redirect_to manage_gates_path, :flash=>{success:'更新成功!'}
43 | else
44 | render :edit, :flash=>{danger:'更新失敗!'}
45 | end
46 | end
47 |
48 | def destroy
49 | @gate.destroy
50 | redirect_to manage_gates_path, :flash=>{success:'刪除成功!'}
51 | end
52 |
53 | def search_tag
54 | @tags = ActsAsTaggableOn::Tag.most_used(20)
55 | #如果使用者沒輸入搜尋字
56 | if params[:search_word].empty?
57 | # 列出所有月門
58 | @gates = Gate.public_server.left_joins(:like_logs).group(:id).order('COUNT(like_logs.id)DESC').page(params[:page]).per(9)
59 | else
60 | # 有輸入關鍵字對關鍵字查詢
61 | @gates = Gate.public_server.tagged_with(params[:search_word]).page(params[:page]).per(9)
62 | flash.now[:danger] ="目前並無搜尋到相關月門..." if @gates.empty?
63 | end
64 | end
65 |
66 | def manage
67 | @gates = User.find(current_user[:id]).gates.page(params[:page]).per(8)
68 | end
69 |
70 | def join_server
71 | url = URI("https://discordapp.com/api/guilds/#{params[:gate_server]}/widget.json")
72 | res = Net::HTTP.get_response(url)
73 | if res.is_a?(Net::HTTPSuccess)
74 | link = JSON.parse(open("https://discordapp.com/api/guilds/#{params[:gate_server]}/widget.json").read)
75 | else
76 | redirect_to root_path
77 | flash[:danger] = '目前找不到伺服器,請確認伺服器 ID 是否正常?'
78 | return
79 | end
80 |
81 | join_link = link['instant_invite']
82 | redirect_to join_link.to_s
83 | end
84 |
85 | private
86 | # 利用 Strong Parameters 設定過濾參數
87 | def gate_params
88 | params.require(:gate).permit(:name, :icon, :intro, :intro_detail, :is_public, :like, :server, :tag_list, :user_id, :search_word)
89 | end
90 | # 每個 Action 撈出 route 對應資料庫 id 的參數
91 | def find_gate_id
92 | @gate = scoped.find(params[:id])
93 | end
94 |
95 | def scoped
96 | return Gate if current_user.admin? && ['update', 'edit', 'destroy'].include?(params[:action])
97 | current_user.gates
98 | end
99 | end
100 |
--------------------------------------------------------------------------------
/db/schema.rb:
--------------------------------------------------------------------------------
1 | # This file is auto-generated from the current state of the database. Instead
2 | # of editing this file, please use the migrations feature of Active Record to
3 | # incrementally modify your database, and then regenerate this schema definition.
4 | #
5 | # Note that this schema.rb definition is the authoritative source for your
6 | # database schema. If you need to create the application database on another
7 | # system, you should be using db:schema:load, not running all the migrations
8 | # from scratch. The latter is a flawed and unsustainable approach (the more migrations
9 | # you'll amass, the slower it'll run and the greater likelihood for issues).
10 | #
11 | # It's strongly recommended that you check this file into your version control system.
12 |
13 | ActiveRecord::Schema.define(version: 2018_07_12_021730) do
14 |
15 | # These are extensions that must be enabled in order to support this database
16 | enable_extension "plpgsql"
17 |
18 | create_table "gates", force: :cascade do |t|
19 | t.string "name"
20 | t.string "icon"
21 | t.string "tag"
22 | t.text "intro"
23 | t.text "intro_detail"
24 | t.boolean "is_public"
25 | t.datetime "created_at", null: false
26 | t.datetime "updated_at", null: false
27 | t.string "server"
28 | t.integer "like", default: 0
29 | t.integer "user_id"
30 | end
31 |
32 | create_table "like_logs", force: :cascade do |t|
33 | t.bigint "gate_id"
34 | t.datetime "created_at", null: false
35 | t.datetime "updated_at", null: false
36 | t.string "ip_address"
37 | t.integer "who_liked"
38 | t.index ["gate_id"], name: "index_like_logs_on_gate_id"
39 | end
40 |
41 | create_table "taggings", id: :serial, force: :cascade do |t|
42 | t.integer "tag_id"
43 | t.string "taggable_type"
44 | t.integer "taggable_id"
45 | t.string "tagger_type"
46 | t.integer "tagger_id"
47 | t.string "context", limit: 128
48 | t.datetime "created_at"
49 | t.index ["context"], name: "index_taggings_on_context"
50 | t.index ["tag_id", "taggable_id", "taggable_type", "context", "tagger_id", "tagger_type"], name: "taggings_idx", unique: true
51 | t.index ["tag_id"], name: "index_taggings_on_tag_id"
52 | t.index ["taggable_id", "taggable_type", "context"], name: "index_taggings_on_taggable_id_and_taggable_type_and_context"
53 | t.index ["taggable_id", "taggable_type", "tagger_id", "context"], name: "taggings_idy"
54 | t.index ["taggable_id"], name: "index_taggings_on_taggable_id"
55 | t.index ["taggable_type"], name: "index_taggings_on_taggable_type"
56 | t.index ["tagger_id", "tagger_type"], name: "index_taggings_on_tagger_id_and_tagger_type"
57 | t.index ["tagger_id"], name: "index_taggings_on_tagger_id"
58 | end
59 |
60 | create_table "tags", id: :serial, force: :cascade do |t|
61 | t.string "name"
62 | t.integer "taggings_count", default: 0
63 | t.index ["name"], name: "index_tags_on_name", unique: true
64 | end
65 |
66 | create_table "users", force: :cascade do |t|
67 | t.string "email", default: "", null: false
68 | t.string "encrypted_password", default: "", null: false
69 | t.string "reset_password_token"
70 | t.datetime "reset_password_sent_at"
71 | t.datetime "remember_created_at"
72 | t.integer "sign_in_count", default: 0, null: false
73 | t.datetime "current_sign_in_at"
74 | t.datetime "last_sign_in_at"
75 | t.inet "current_sign_in_ip"
76 | t.inet "last_sign_in_ip"
77 | t.integer "role", default: 0
78 | t.index ["email"], name: "index_users_on_email", unique: true
79 | t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
80 | end
81 |
82 | end
83 |
--------------------------------------------------------------------------------
/config/locales/devise.en.yml:
--------------------------------------------------------------------------------
1 | # Additional translations at https://github.com/plataformatec/devise/wiki/I18n
2 |
3 | en:
4 | devise:
5 | confirmations:
6 | confirmed: "Your email address has been successfully confirmed."
7 | send_instructions: "You will receive an email with instructions for how to confirm your email address in a few minutes."
8 | send_paranoid_instructions: "If your email address exists in our database, you will receive an email with instructions for how to confirm your email address in a few minutes."
9 | failure:
10 | already_authenticated: "You are already signed in."
11 | inactive: "Your account is not activated yet."
12 | invalid: "Invalid %{authentication_keys} or password."
13 | locked: "Your account is locked."
14 | last_attempt: "You have one more attempt before your account is locked."
15 | not_found_in_database: "Invalid %{authentication_keys} or password."
16 | timeout: "Your session expired. Please sign in again to continue."
17 | unauthenticated: "您需要註冊或登入以管理月門!"
18 | unconfirmed: "You have to confirm your email address before continuing."
19 | mailer:
20 | confirmation_instructions:
21 | subject: "Confirmation instructions"
22 | reset_password_instructions:
23 | subject: "Reset password instructions"
24 | unlock_instructions:
25 | subject: "Unlock instructions"
26 | email_changed:
27 | subject: "Email Changed"
28 | password_change:
29 | subject: "Password Changed"
30 | omniauth_callbacks:
31 | failure: "Could not authenticate you from %{kind} because \"%{reason}\"."
32 | success: "Successfully authenticated from %{kind} account."
33 | passwords:
34 | no_token: "You can't access this page without coming from a password reset email. If you do come from a password reset email, please make sure you used the full URL provided."
35 | send_instructions: "You will receive an email with instructions on how to reset your password in a few minutes."
36 | send_paranoid_instructions: "If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes."
37 | updated: "Your password has been changed successfully. You are now signed in."
38 | updated_not_active: "Your password has been changed successfully."
39 | registrations:
40 | destroyed: "Bye! Your account has been successfully cancelled. We hope to see you again soon."
41 | signed_up: "Welcome! You have signed up successfully."
42 | signed_up_but_inactive: "You have signed up successfully. However, we could not sign you in because your account is not yet activated."
43 | signed_up_but_locked: "You have signed up successfully. However, we could not sign you in because your account is locked."
44 | signed_up_but_unconfirmed: "A message with a confirmation link has been sent to your email address. Please follow the link to activate your account."
45 | update_needs_confirmation: "You updated your account successfully, but we need to verify your new email address. Please check your email and follow the confirm link to confirm your new email address."
46 | updated: "Your account has been updated successfully."
47 | sessions:
48 | signed_in: ""
49 | signed_out: ""
50 | already_signed_out: ""
51 | unlocks:
52 | send_instructions: "You will receive an email with instructions for how to unlock your account in a few minutes."
53 | send_paranoid_instructions: "If your account exists, you will receive an email with instructions for how to unlock it in a few minutes."
54 | unlocked: "Your account has been unlocked successfully. Please sign in to continue."
55 | errors:
56 | messages:
57 | already_confirmed: "was already confirmed, please try signing in"
58 | confirmation_period_expired: "needs to be confirmed within %{period}, please request a new one"
59 | expired: "has expired, please request a new one"
60 | not_found: "not found"
61 | not_locked: "was not locked"
62 | not_saved:
63 | one: "1 error prohibited this %{resource} from being saved:"
64 | other: "%{count} errors prohibited this %{resource} from being saved:"
65 |
--------------------------------------------------------------------------------
/config/environments/production.rb:
--------------------------------------------------------------------------------
1 | Rails.application.configure do
2 | # Settings specified here will take precedence over those in config/application.rb.
3 |
4 | # Code is not reloaded between requests.
5 | config.cache_classes = true
6 |
7 | # Eager load code on boot. This eager loads most of Rails and
8 | # your application in memory, allowing both threaded web servers
9 | # and those relying on copy on write to perform better.
10 | # Rake tasks automatically ignore this option for performance.
11 | config.eager_load = true
12 |
13 | # Full error reports are disabled and caching is turned on.
14 | config.consider_all_requests_local = false
15 | config.action_controller.perform_caching = true
16 |
17 | # Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"]
18 | # or in config/master.key. This key is used to decrypt credentials (and other encrypted files).
19 | # config.require_master_key = true
20 |
21 | # Disable serving static files from the `/public` folder by default since
22 | # Apache or NGINX already handles this.
23 | config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?
24 |
25 | # Compress JavaScripts and CSS.
26 | config.assets.js_compressor = :uglifier
27 | # config.assets.css_compressor = :sass
28 |
29 | # Do not fallback to assets pipeline if a precompiled asset is missed.
30 | config.assets.compile = false
31 |
32 | # `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb
33 |
34 | # Enable serving of images, stylesheets, and JavaScripts from an asset server.
35 | # config.action_controller.asset_host = 'http://assets.example.com'
36 |
37 | # Specifies the header that your server uses for sending files.
38 | # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache
39 | # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX
40 |
41 | # Store uploaded files on the local file system (see config/storage.yml for options)
42 | config.active_storage.service = :local
43 |
44 | # Mount Action Cable outside main process or domain
45 | # config.action_cable.mount_path = nil
46 | # config.action_cable.url = 'wss://example.com/cable'
47 | # config.action_cable.allowed_request_origins = [ 'http://example.com', /http:\/\/example.*/ ]
48 |
49 | # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
50 | # config.force_ssl = true
51 |
52 | # Use the lowest log level to ensure availability of diagnostic information
53 | # when problems arise.
54 | config.log_level = :debug
55 |
56 | # Prepend all log lines with the following tags.
57 | config.log_tags = [ :request_id ]
58 |
59 | # Use a different cache store in production.
60 | # config.cache_store = :mem_cache_store
61 |
62 | # Use a real queuing backend for Active Job (and separate queues per environment)
63 | # config.active_job.queue_adapter = :resque
64 | # config.active_job.queue_name_prefix = "MoonGate_#{Rails.env}"
65 |
66 | config.action_mailer.perform_caching = false
67 |
68 | # Ignore bad email addresses and do not raise email delivery errors.
69 | # Set this to true and configure the email server for immediate delivery to raise delivery errors.
70 | # config.action_mailer.raise_delivery_errors = false
71 |
72 | # Enable locale fallbacks for I18n (makes lookups for any locale fall back to
73 | # the I18n.default_locale when a translation cannot be found).
74 | config.i18n.fallbacks = true
75 |
76 | # Send deprecation notices to registered listeners.
77 | config.active_support.deprecation = :notify
78 |
79 | # Use default logging formatter so that PID and timestamp are not suppressed.
80 | config.log_formatter = ::Logger::Formatter.new
81 |
82 | # Use a different logger for distributed setups.
83 | # require 'syslog/logger'
84 | # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name')
85 |
86 | if ENV["RAILS_LOG_TO_STDOUT"].present?
87 | logger = ActiveSupport::Logger.new(STDOUT)
88 | logger.formatter = config.log_formatter
89 | config.logger = ActiveSupport::TaggedLogging.new(logger)
90 | end
91 |
92 | # Do not dump schema after migrations.
93 | config.active_record.dump_schema_after_migration = false
94 | end
95 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/gates.scss:
--------------------------------------------------------------------------------
1 | // Place all the styles related to the Gates controller here.
2 | // They will automatically be included in application.css.
3 | // You can use Sass (SCSS) here: http://sass-lang.com/
4 | $primary-color: #2ecc71;
5 | $primary-color-dark: #16a085;
6 | $secondary-color: #4CBBE8;
7 | $secondary-color-light: rgb(139, 222, 255);
8 | $secondary-color-dark: #2980b9;
9 | $btn-color: rgb(32, 192, 255);
10 | $btn-color-dark:rgb(26, 158, 211);
11 | $bg-color: #2c3e50;
12 | $gate_box_height: 300px;
13 | $gate_box_width: 360px;
14 | $gate-box-color: rgb(255, 255, 255);
15 | $gate-header-height: 60px;
16 | $gate-body-height: 200px;
17 |
18 | .invalid-feedback{
19 | color: red;
20 | }
21 |
22 | .show-gate-icon {
23 | margin-top: 50%;
24 | margin-bottom: 50%;
25 | }
26 |
27 | .navbar-default .navbar-brand {
28 | color: $secondary-color;
29 | }
30 |
31 | .navbar-default .navbar-brand:hover,
32 | .navbar-default .navbar-brand:focus {
33 | color: $secondary-color-dark;
34 | background-color: transparent;
35 | }
36 |
37 | .push-right {
38 | float: right;
39 | }
40 |
41 | .center {
42 | text-align: center;
43 | padding: 0px auto;
44 | }
45 |
46 | .navbar-default {
47 | background-color: $bg-color;
48 | }
49 |
50 | .navbar-default .navbar-nav>li>a {
51 | color: $secondary-color;
52 | }
53 |
54 | .navbar-default .navbar-nav>li>a:hover {
55 | background-color: $secondary-color-light;
56 | }
57 |
58 | ul {
59 | padding: 0;
60 | }
61 |
62 | .gate-box-header a {
63 | color: $primary-color;
64 | }
65 |
66 | .gate-box-header a:hover {
67 | color: $primary-color-dark;
68 | }
69 |
70 | .search-form {
71 | padding-top: 0.8em;
72 | display: inline-block;
73 | }
74 |
75 | .sign-info {
76 | text-align: right;
77 | }
78 |
79 | .gate-box {
80 | box-sizing: border-box;
81 | max-width: 360px;
82 | margin: 10px;
83 | padding: 0px 0px 0px 0px;
84 | background-color: $gate-box-color;
85 | box-shadow: 1px 1px 1px 1px gray;
86 | transition: 0.3s;
87 | }
88 |
89 | .gate-box:hover {
90 | box-shadow: 2px 2px 2px 2px gray;
91 | }
92 |
93 | .gate-box-header {
94 | height: 60px;
95 | background-color: $bg-color;
96 | }
97 |
98 | .gate-box-icon {
99 | padding: 5px;
100 | width: 60;
101 | margin: 0px auto;
102 | }
103 |
104 | .gate-box-name {
105 | font-size: 1.2em;
106 | max-height: 60px;
107 | text-align: center;
108 | padding: 15px 5px 0px 5px;
109 | line-height: 1.1em;
110 | }
111 |
112 | .gate-box-body {
113 | height: 300px;
114 | padding: 5px
115 | }
116 |
117 | .gate-intro {
118 | padding-top: 10px;
119 | }
120 |
121 | .gate-box-tool {
122 | padding: 7.5px;
123 | text-align: left;
124 | border: 0px;
125 | border-top: 1px solid $bg-color;
126 | overflow: scroll;
127 | height: 40px;
128 | }
129 |
130 | .gate-tag {
131 | overflow: scroll;
132 | }
133 |
134 | .gate-like {
135 | float: right;
136 | }
137 |
138 | .show-name {
139 | margin: auto 0 auto 0;
140 | }
141 |
142 | .btn-tag {
143 | color: #fff;
144 | background-color: $btn-color;
145 | border-color: $btn-color;
146 | display: inline-block;
147 | margin-bottom: 0;
148 | text-align: center;
149 | vertical-align: middle;
150 | border: 1px solid transparent;
151 | white-space: nowrap;
152 | padding: 2px 8px;
153 | font-size: 0.8em;
154 | border-radius: 4px;
155 | }
156 |
157 | .btn-tag:hover {
158 | color: #fff;
159 | background-color: $btn-color-dark;
160 | border-color: $btn-color-dark;
161 | text-decoration: none;
162 | }
163 |
164 | .btn-tag-like {
165 | color: #fff;
166 | background-color: $btn-color;
167 | border-color: $btn-color;
168 | display: inline-block;
169 | margin-bottom: 0;
170 | text-align: center;
171 | vertical-align: middle;
172 | border: 1px solid transparent;
173 | white-space: nowrap;
174 | padding: 2px 8px;
175 | font-size: 0.8em;
176 | border-radius: 4px;
177 | }
178 |
179 | .btn-tag-like:hover {
180 | color: #fff;
181 | background-color: $btn-color-dark;
182 | border-color: $btn-color-dark;
183 | text-decoration: none;
184 | }
185 |
186 | .glyphicon-tags {
187 | color: $bg-color;
188 | font-size: 1em;
189 | }
190 |
191 | .btn-warning {
192 | color: #fff;
193 | background-color: $primary-color;
194 | border-color: $primary-color-dark;
195 | display: inline-block;
196 | margin-bottom: 0;
197 | text-align: center;
198 | vertical-align: middle;
199 | border: 1px solid transparent;
200 | white-space: nowrap;
201 | padding: 2px 8px;
202 | font-size: 0.8em;
203 | border-radius: 4px;
204 | }
205 |
206 | .btn-warning:hover {
207 | color: #fff;
208 | background-color: $primary-color-dark;
209 | border-color: $primary-color-dark;
210 | text-decoration: none;
211 | }
212 |
213 | .navbar-right {
214 | margin-right: 0;
215 | }
216 |
217 | .gate-icon {
218 | width: 50px;
219 | height: 50px;
220 | border-radius: 50%;
221 | }
222 |
--------------------------------------------------------------------------------
/config/initializers/simple_form.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | #
3 | # Uncomment this and change the path if necessary to include your own
4 | # components.
5 | # See https://github.com/plataformatec/simple_form#custom-components to know
6 | # more about custom components.
7 | # Dir[Rails.root.join('lib/components/**/*.rb')].each { |f| require f }
8 | #
9 | # Use this setup block to configure all options available in SimpleForm.
10 | SimpleForm.setup do |config|
11 | # Wrappers are used by the form builder to generate a
12 | # complete input. You can remove any component from the
13 | # wrapper, change the order or even add your own to the
14 | # stack. The options given below are used to wrap the
15 | # whole input.
16 | config.wrappers :default, class: :input,
17 | hint_class: :field_with_hint, error_class: :field_with_errors, valid_class: :field_without_errors do |b|
18 | ## Extensions enabled by default
19 | # Any of these extensions can be disabled for a
20 | # given input by passing: `f.input EXTENSION_NAME => false`.
21 | # You can make any of these extensions optional by
22 | # renaming `b.use` to `b.optional`.
23 |
24 | # Determines whether to use HTML5 (:email, :url, ...)
25 | # and required attributes
26 | b.use :html5
27 |
28 | # Calculates placeholders automatically from I18n
29 | # You can also pass a string as f.input placeholder: "Placeholder"
30 | b.use :placeholder
31 |
32 | ## Optional extensions
33 | # They are disabled unless you pass `f.input EXTENSION_NAME => true`
34 | # to the input. If so, they will retrieve the values from the model
35 | # if any exists. If you want to enable any of those
36 | # extensions by default, you can change `b.optional` to `b.use`.
37 |
38 | # Calculates maxlength from length validations for string inputs
39 | # and/or database column lengths
40 | b.optional :maxlength
41 |
42 | # Calculate minlength from length validations for string inputs
43 | b.optional :minlength
44 |
45 | # Calculates pattern from format validations for string inputs
46 | b.optional :pattern
47 |
48 | # Calculates min and max from length validations for numeric inputs
49 | b.optional :min_max
50 |
51 | # Calculates readonly automatically from readonly attributes
52 | b.optional :readonly
53 |
54 | ## Inputs
55 | # b.use :input, class: 'input', error_class: 'is-invalid', valid_class: 'is-valid'
56 | b.use :label_input
57 | b.use :hint, wrap_with: { tag: :span, class: :hint }
58 | b.use :error, wrap_with: { tag: :span, class: :error }
59 |
60 | ## full_messages_for
61 | # If you want to display the full error message for the attribute, you can
62 | # use the component :full_error, like:
63 | #
64 | # b.use :full_error, wrap_with: { tag: :span, class: :error }
65 | end
66 |
67 | # The default wrapper to be used by the FormBuilder.
68 | config.default_wrapper = :default
69 |
70 | # Define the way to render check boxes / radio buttons with labels.
71 | # Defaults to :nested for bootstrap config.
72 | # inline: input + label
73 | # nested: label > input
74 | config.boolean_style = :nested
75 |
76 | # Default class for buttons
77 | config.button_class = 'btn'
78 |
79 | # Method used to tidy up errors. Specify any Rails Array method.
80 | # :first lists the first message for each field.
81 | # Use :to_sentence to list all errors for each field.
82 | # config.error_method = :first
83 |
84 | # Default tag used for error notification helper.
85 | config.error_notification_tag = :div
86 |
87 | # CSS class to add for error notification helper.
88 | config.error_notification_class = 'error_notification'
89 |
90 | # ID to add for error notification helper.
91 | # config.error_notification_id = nil
92 |
93 | # Series of attempts to detect a default label method for collection.
94 | # config.collection_label_methods = [ :to_label, :name, :title, :to_s ]
95 |
96 | # Series of attempts to detect a default value method for collection.
97 | # config.collection_value_methods = [ :id, :to_s ]
98 |
99 | # You can wrap a collection of radio/check boxes in a pre-defined tag, defaulting to none.
100 | # config.collection_wrapper_tag = nil
101 |
102 | # You can define the class to use on all collection wrappers. Defaulting to none.
103 | # config.collection_wrapper_class = nil
104 |
105 | # You can wrap each item in a collection of radio/check boxes with a tag,
106 | # defaulting to :span.
107 | # config.item_wrapper_tag = :span
108 |
109 | # You can define a class to use in all item wrappers. Defaulting to none.
110 | # config.item_wrapper_class = nil
111 |
112 | # How the label text should be generated altogether with the required text.
113 | # config.label_text = lambda { |label, required, explicit_label| "#{required} #{label}" }
114 |
115 | # You can define the class to use on all labels. Default is nil.
116 | # config.label_class = nil
117 |
118 | # You can define the default class to be used on forms. Can be overriden
119 | # with `html: { :class }`. Defaulting to none.
120 | # config.default_form_class = nil
121 |
122 | # You can define which elements should obtain additional classes
123 | # config.generate_additional_classes_for = [:wrapper, :label, :input]
124 |
125 | # Whether attributes are required by default (or not). Default is true.
126 | # config.required_by_default = true
127 |
128 | # Tell browsers whether to use the native HTML5 validations (novalidate form option).
129 | # These validations are enabled in SimpleForm's internal config but disabled by default
130 | # in this configuration, which is recommended due to some quirks from different browsers.
131 | # To stop SimpleForm from generating the novalidate option, enabling the HTML5 validations,
132 | # change this configuration to true.
133 | config.browser_validations = false
134 |
135 | # Collection of methods to detect if a file type was given.
136 | # config.file_methods = [ :mounted_as, :file?, :public_filename, :attached? ]
137 |
138 | # Custom mappings for input types. This should be a hash containing a regexp
139 | # to match as key, and the input type that will be used when the field name
140 | # matches the regexp as value.
141 | # config.input_mappings = { /count/ => :integer }
142 |
143 | # Custom wrappers for input types. This should be a hash containing an input
144 | # type as key and the wrapper that will be used for all inputs with specified type.
145 | # config.wrapper_mappings = { string: :prepend }
146 |
147 | # Namespaces where SimpleForm should look for custom input classes that
148 | # override default inputs.
149 | # config.custom_inputs_namespaces << "CustomInputs"
150 |
151 | # Default priority for time_zone inputs.
152 | # config.time_zone_priority = nil
153 |
154 | # Default priority for country inputs.
155 | # config.country_priority = nil
156 |
157 | # When false, do not use translations for labels.
158 | # config.translate_labels = true
159 |
160 | # Automatically discover new inputs in Rails' autoload path.
161 | # config.inputs_discovery = true
162 |
163 | # Cache SimpleForm inputs discovery
164 | # config.cache_discovery = !Rails.env.development?
165 |
166 | # Default class for inputs
167 | # config.input_class = nil
168 |
169 | # Define the default class of the input wrapper of the boolean input.
170 | config.boolean_label_class = 'checkbox'
171 |
172 | # Defines if the default input wrapper class should be included in radio
173 | # collection wrappers.
174 | # config.include_default_input_wrapper_class = true
175 |
176 | # Defines which i18n scope will be used in Simple Form.
177 | # config.i18n_scope = 'simple_form'
178 |
179 | # Defines validation classes to the input_field. By default it's nil.
180 | # config.input_field_valid_class = 'is-valid'
181 | # config.input_field_error_class = 'is-invalid'
182 | end
183 |
--------------------------------------------------------------------------------
/Gemfile.lock:
--------------------------------------------------------------------------------
1 | GEM
2 | remote: https://rubygems.org/
3 | specs:
4 | actioncable (5.2.0)
5 | actionpack (= 5.2.0)
6 | nio4r (~> 2.0)
7 | websocket-driver (>= 0.6.1)
8 | actionmailer (5.2.0)
9 | actionpack (= 5.2.0)
10 | actionview (= 5.2.0)
11 | activejob (= 5.2.0)
12 | mail (~> 2.5, >= 2.5.4)
13 | rails-dom-testing (~> 2.0)
14 | actionpack (5.2.0)
15 | actionview (= 5.2.0)
16 | activesupport (= 5.2.0)
17 | rack (~> 2.0)
18 | rack-test (>= 0.6.3)
19 | rails-dom-testing (~> 2.0)
20 | rails-html-sanitizer (~> 1.0, >= 1.0.2)
21 | actionview (5.2.0)
22 | activesupport (= 5.2.0)
23 | builder (~> 3.1)
24 | erubi (~> 1.4)
25 | rails-dom-testing (~> 2.0)
26 | rails-html-sanitizer (~> 1.0, >= 1.0.3)
27 | activejob (5.2.0)
28 | activesupport (= 5.2.0)
29 | globalid (>= 0.3.6)
30 | activemodel (5.2.0)
31 | activesupport (= 5.2.0)
32 | activerecord (5.2.0)
33 | activemodel (= 5.2.0)
34 | activesupport (= 5.2.0)
35 | arel (>= 9.0)
36 | activestorage (5.2.0)
37 | actionpack (= 5.2.0)
38 | activerecord (= 5.2.0)
39 | marcel (~> 0.3.1)
40 | activesupport (5.2.0)
41 | concurrent-ruby (~> 1.0, >= 1.0.2)
42 | i18n (>= 0.7, < 2)
43 | minitest (~> 5.1)
44 | tzinfo (~> 1.1)
45 | acts-as-taggable-on (6.0.0)
46 | activerecord (~> 5.0)
47 | addressable (2.5.2)
48 | public_suffix (>= 2.0.2, < 4.0)
49 | archive-zip (0.11.0)
50 | io-like (~> 0.3.0)
51 | arel (9.0.0)
52 | autoprefixer-rails (9.0.0)
53 | execjs
54 | aws_cf_signer (0.1.3)
55 | bcrypt (3.1.12)
56 | bindex (0.5.0)
57 | bootsnap (1.3.0)
58 | msgpack (~> 1.0)
59 | bootstrap-sass (3.3.7)
60 | autoprefixer-rails (>= 5.2.1)
61 | sass (>= 3.3.4)
62 | builder (3.2.3)
63 | byebug (10.0.2)
64 | capybara (3.2.1)
65 | addressable
66 | mini_mime (>= 0.1.3)
67 | nokogiri (~> 1.8)
68 | rack (>= 1.6.0)
69 | rack-test (>= 0.6.3)
70 | xpath (~> 3.1)
71 | carrierwave (1.2.3)
72 | activemodel (>= 4.0.0)
73 | activesupport (>= 4.0.0)
74 | mime-types (>= 1.16)
75 | childprocess (0.9.0)
76 | ffi (~> 1.0, >= 1.0.11)
77 | chromedriver-helper (1.2.0)
78 | archive-zip (~> 0.10)
79 | nokogiri (~> 1.8)
80 | cloudinary (1.9.1)
81 | aws_cf_signer
82 | rest-client
83 | coderay (1.1.2)
84 | coffee-rails (4.2.2)
85 | coffee-script (>= 2.2.0)
86 | railties (>= 4.0.0)
87 | coffee-script (2.4.1)
88 | coffee-script-source
89 | execjs
90 | coffee-script-source (1.12.2)
91 | concurrent-ruby (1.0.5)
92 | crass (1.0.4)
93 | devise (4.4.3)
94 | bcrypt (~> 3.0)
95 | orm_adapter (~> 0.1)
96 | railties (>= 4.1.0, < 6.0)
97 | responders
98 | warden (~> 1.2.3)
99 | domain_name (0.5.20180417)
100 | unf (>= 0.0.5, < 1.0.0)
101 | em-websocket (0.5.1)
102 | eventmachine (>= 0.12.9)
103 | http_parser.rb (~> 0.6.0)
104 | erubi (1.7.1)
105 | eventmachine (1.2.7)
106 | execjs (2.7.0)
107 | faker (1.8.7)
108 | i18n (>= 0.7)
109 | ffi (1.9.25)
110 | font-awesome-rails (4.7.0.4)
111 | railties (>= 3.2, < 6.0)
112 | formatador (0.2.5)
113 | globalid (0.4.1)
114 | activesupport (>= 4.2.0)
115 | guard (2.14.2)
116 | formatador (>= 0.2.4)
117 | listen (>= 2.7, < 4.0)
118 | lumberjack (>= 1.0.12, < 2.0)
119 | nenv (~> 0.1)
120 | notiffany (~> 0.0)
121 | pry (>= 0.9.12)
122 | shellany (~> 0.0)
123 | thor (>= 0.18.1)
124 | guard-compat (1.2.1)
125 | guard-livereload (2.5.2)
126 | em-websocket (~> 0.5)
127 | guard (~> 2.8)
128 | guard-compat (~> 1.0)
129 | multi_json (~> 1.8)
130 | http-cookie (1.0.3)
131 | domain_name (~> 0.5)
132 | http_parser.rb (0.6.0)
133 | i18n (1.0.1)
134 | concurrent-ruby (~> 1.0)
135 | io-like (0.3.0)
136 | jbuilder (2.7.0)
137 | activesupport (>= 4.2.0)
138 | multi_json (>= 1.2)
139 | jquery-rails (4.3.3)
140 | rails-dom-testing (>= 1, < 3)
141 | railties (>= 4.2.0)
142 | thor (>= 0.14, < 2.0)
143 | kaminari (1.1.1)
144 | activesupport (>= 4.1.0)
145 | kaminari-actionview (= 1.1.1)
146 | kaminari-activerecord (= 1.1.1)
147 | kaminari-core (= 1.1.1)
148 | kaminari-actionview (1.1.1)
149 | actionview
150 | kaminari-core (= 1.1.1)
151 | kaminari-activerecord (1.1.1)
152 | activerecord
153 | kaminari-core (= 1.1.1)
154 | kaminari-core (1.1.1)
155 | listen (3.1.5)
156 | rb-fsevent (~> 0.9, >= 0.9.4)
157 | rb-inotify (~> 0.9, >= 0.9.7)
158 | ruby_dep (~> 1.2)
159 | loofah (2.2.2)
160 | crass (~> 1.0.2)
161 | nokogiri (>= 1.5.9)
162 | lumberjack (1.0.13)
163 | mail (2.7.0)
164 | mini_mime (>= 0.1.1)
165 | marcel (0.3.2)
166 | mimemagic (~> 0.3.2)
167 | method_source (0.9.0)
168 | mime-types (3.1)
169 | mime-types-data (~> 3.2015)
170 | mime-types-data (3.2016.0521)
171 | mimemagic (0.3.2)
172 | mini_mime (1.0.0)
173 | mini_portile2 (2.3.0)
174 | minitest (5.11.3)
175 | msgpack (1.2.4)
176 | multi_json (1.13.1)
177 | nenv (0.3.0)
178 | netrc (0.11.0)
179 | nio4r (2.3.1)
180 | nokogiri (1.8.4)
181 | mini_portile2 (~> 2.3.0)
182 | notiffany (0.1.1)
183 | nenv (~> 0.1)
184 | shellany (~> 0.0)
185 | orm_adapter (0.5.0)
186 | pg (0.19.0)
187 | pry (0.11.3)
188 | coderay (~> 1.1.0)
189 | method_source (~> 0.9.0)
190 | pry-rails (0.3.6)
191 | pry (>= 0.10.4)
192 | public_suffix (3.0.2)
193 | puma (3.12.0)
194 | rack (2.0.5)
195 | rack-test (1.0.0)
196 | rack (>= 1.0, < 3)
197 | rails (5.2.0)
198 | actioncable (= 5.2.0)
199 | actionmailer (= 5.2.0)
200 | actionpack (= 5.2.0)
201 | actionview (= 5.2.0)
202 | activejob (= 5.2.0)
203 | activemodel (= 5.2.0)
204 | activerecord (= 5.2.0)
205 | activestorage (= 5.2.0)
206 | activesupport (= 5.2.0)
207 | bundler (>= 1.3.0)
208 | railties (= 5.2.0)
209 | sprockets-rails (>= 2.0.0)
210 | rails-dom-testing (2.0.3)
211 | activesupport (>= 4.2.0)
212 | nokogiri (>= 1.6)
213 | rails-html-sanitizer (1.0.4)
214 | loofah (~> 2.2, >= 2.2.2)
215 | railties (5.2.0)
216 | actionpack (= 5.2.0)
217 | activesupport (= 5.2.0)
218 | method_source
219 | rake (>= 0.8.7)
220 | thor (>= 0.18.1, < 2.0)
221 | rake (12.3.1)
222 | rb-fsevent (0.10.3)
223 | rb-inotify (0.9.10)
224 | ffi (>= 0.5.0, < 2)
225 | responders (2.4.0)
226 | actionpack (>= 4.2.0, < 5.3)
227 | railties (>= 4.2.0, < 5.3)
228 | rest-client (2.0.2)
229 | http-cookie (>= 1.0.2, < 2.0)
230 | mime-types (>= 1.16, < 4.0)
231 | netrc (~> 0.8)
232 | ruby_dep (1.5.0)
233 | rubyzip (1.2.1)
234 | sass (3.5.7)
235 | sass-listen (~> 4.0.0)
236 | sass-listen (4.0.0)
237 | rb-fsevent (~> 0.9, >= 0.9.4)
238 | rb-inotify (~> 0.9, >= 0.9.7)
239 | sass-rails (5.0.7)
240 | railties (>= 4.0.0, < 6)
241 | sass (~> 3.1)
242 | sprockets (>= 2.8, < 4.0)
243 | sprockets-rails (>= 2.0, < 4.0)
244 | tilt (>= 1.1, < 3)
245 | selenium-webdriver (3.12.0)
246 | childprocess (~> 0.5)
247 | rubyzip (~> 1.2)
248 | shellany (0.0.1)
249 | simple_form (4.0.1)
250 | actionpack (>= 5.0)
251 | activemodel (>= 5.0)
252 | spring (2.0.2)
253 | activesupport (>= 4.2)
254 | spring-watcher-listen (2.0.1)
255 | listen (>= 2.7, < 4.0)
256 | spring (>= 1.2, < 3.0)
257 | sprockets (3.7.2)
258 | concurrent-ruby (~> 1.0)
259 | rack (> 1, < 3)
260 | sprockets-rails (3.2.1)
261 | actionpack (>= 4.0)
262 | activesupport (>= 4.0)
263 | sprockets (>= 3.0.0)
264 | thor (0.20.0)
265 | thread_safe (0.3.6)
266 | tilt (2.0.8)
267 | turbolinks (5.1.1)
268 | turbolinks-source (~> 5.1)
269 | turbolinks-source (5.1.0)
270 | tzinfo (1.2.5)
271 | thread_safe (~> 0.1)
272 | uglifier (4.1.16)
273 | execjs (>= 0.3.0, < 3)
274 | unf (0.1.4)
275 | unf_ext
276 | unf_ext (0.0.7.5)
277 | warden (1.2.7)
278 | rack (>= 1.0)
279 | web-console (3.6.2)
280 | actionview (>= 5.0)
281 | activemodel (>= 5.0)
282 | bindex (>= 0.4.0)
283 | railties (>= 5.0)
284 | websocket-driver (0.7.0)
285 | websocket-extensions (>= 0.1.0)
286 | websocket-extensions (0.1.3)
287 | xpath (3.1.0)
288 | nokogiri (~> 1.8)
289 |
290 | PLATFORMS
291 | ruby
292 |
293 | DEPENDENCIES
294 | acts-as-taggable-on (~> 6.0)
295 | bootsnap (>= 1.1.0)
296 | bootstrap-sass (~> 3.3.7)
297 | byebug
298 | capybara (>= 2.15, < 4.0)
299 | carrierwave
300 | chromedriver-helper
301 | cloudinary
302 | coffee-rails (~> 4.2)
303 | devise
304 | faker
305 | font-awesome-rails
306 | guard-livereload (~> 2.5)
307 | jbuilder (~> 2.5)
308 | jquery-rails
309 | kaminari
310 | listen (>= 3.0.5, < 3.2)
311 | pg (~> 0.19.0)
312 | pry-rails
313 | puma (~> 3.11)
314 | rails (~> 5.2.0)
315 | sass-rails (~> 5.0)
316 | selenium-webdriver
317 | simple_form
318 | spring
319 | spring-watcher-listen (~> 2.0.0)
320 | turbolinks (~> 5)
321 | uglifier (>= 1.3.0)
322 | web-console (>= 3.3.0)
323 |
324 | RUBY VERSION
325 | ruby 2.3.7p456
326 |
327 | BUNDLED WITH
328 | 1.16.2
329 |
--------------------------------------------------------------------------------
/config/initializers/devise.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | # Use this hook to configure devise mailer, warden hooks and so forth.
4 | # Many of these configuration options can be set straight in your model.
5 | Devise.setup do |config|
6 | # The secret key used by Devise. Devise uses this key to generate
7 | # random tokens. Changing this key will render invalid all existing
8 | # confirmation, reset password and unlock tokens in the database.
9 | # Devise will use the `secret_key_base` as its `secret_key`
10 | # by default. You can change it below and use your own secret key.
11 | # config.secret_key = '5b86f3969dc054090c927027689166b07da82c08871199204cbccd9af144d5d7300e0e904015cc014358f69e4c604d480576ddc47a0b7443bcc3ebe1fa46969a'
12 | config.secret_key = 'ed39a3333465ca984976e61ab13a0bb2d2ec64a4a47cda9c9597a791065b7f0811a2deb34990ca66dbe94f5d21aa601878d2dd0752d97b7cee63156bf66b509a'
13 |
14 | # ==> Controller configuration
15 | # Configure the parent class to the devise controllers.
16 | # config.parent_controller = 'DeviseController'
17 |
18 | # ==> Mailer Configuration
19 | # Configure the e-mail address which will be shown in Devise::Mailer,
20 | # note that it will be overwritten if you use your own mailer class
21 | # with default "from" parameter.
22 | config.mailer_sender = 'please-change-me-at-config-initializers-devise@example.com'
23 |
24 | # Configure the class responsible to send e-mails.
25 | # config.mailer = 'Devise::Mailer'
26 |
27 | # Configure the parent class responsible to send e-mails.
28 | # config.parent_mailer = 'ActionMailer::Base'
29 |
30 | # ==> ORM configuration
31 | # Load and configure the ORM. Supports :active_record (default) and
32 | # :mongoid (bson_ext recommended) by default. Other ORMs may be
33 | # available as additional gems.
34 | require 'devise/orm/active_record'
35 |
36 | # ==> Configuration for any authentication mechanism
37 | # Configure which keys are used when authenticating a user. The default is
38 | # just :email. You can configure it to use [:username, :subdomain], so for
39 | # authenticating a user, both parameters are required. Remember that those
40 | # parameters are used only when authenticating and not when retrieving from
41 | # session. If you need permissions, you should implement that in a before filter.
42 | # You can also supply a hash where the value is a boolean determining whether
43 | # or not authentication should be aborted when the value is not present.
44 | # config.authentication_keys = [:email]
45 |
46 | # Configure parameters from the request object used for authentication. Each entry
47 | # given should be a request method and it will automatically be passed to the
48 | # find_for_authentication method and considered in your model lookup. For instance,
49 | # if you set :request_keys to [:subdomain], :subdomain will be used on authentication.
50 | # The same considerations mentioned for authentication_keys also apply to request_keys.
51 | # config.request_keys = []
52 |
53 | # Configure which authentication keys should be case-insensitive.
54 | # These keys will be downcased upon creating or modifying a user and when used
55 | # to authenticate or find a user. Default is :email.
56 | config.case_insensitive_keys = [:email]
57 |
58 | # Configure which authentication keys should have whitespace stripped.
59 | # These keys will have whitespace before and after removed upon creating or
60 | # modifying a user and when used to authenticate or find a user. Default is :email.
61 | config.strip_whitespace_keys = [:email]
62 |
63 | # Tell if authentication through request.params is enabled. True by default.
64 | # It can be set to an array that will enable params authentication only for the
65 | # given strategies, for example, `config.params_authenticatable = [:database]` will
66 | # enable it only for database (email + password) authentication.
67 | # config.params_authenticatable = true
68 |
69 | # Tell if authentication through HTTP Auth is enabled. False by default.
70 | # It can be set to an array that will enable http authentication only for the
71 | # given strategies, for example, `config.http_authenticatable = [:database]` will
72 | # enable it only for database authentication. The supported strategies are:
73 | # :database = Support basic authentication with authentication key + password
74 | # config.http_authenticatable = false
75 |
76 | # If 401 status code should be returned for AJAX requests. True by default.
77 | # config.http_authenticatable_on_xhr = true
78 |
79 | # The realm used in Http Basic Authentication. 'Application' by default.
80 | # config.http_authentication_realm = 'Application'
81 |
82 | # It will change confirmation, password recovery and other workflows
83 | # to behave the same regardless if the e-mail provided was right or wrong.
84 | # Does not affect registerable.
85 | # config.paranoid = true
86 |
87 | # By default Devise will store the user in session. You can skip storage for
88 | # particular strategies by setting this option.
89 | # Notice that if you are skipping storage for all authentication paths, you
90 | # may want to disable generating routes to Devise's sessions controller by
91 | # passing skip: :sessions to `devise_for` in your config/routes.rb
92 | config.skip_session_storage = [:http_auth]
93 |
94 | # By default, Devise cleans up the CSRF token on authentication to
95 | # avoid CSRF token fixation attacks. This means that, when using AJAX
96 | # requests for sign in and sign up, you need to get a new CSRF token
97 | # from the server. You can disable this option at your own risk.
98 | # config.clean_up_csrf_token_on_authentication = true
99 |
100 | # When false, Devise will not attempt to reload routes on eager load.
101 | # This can reduce the time taken to boot the app but if your application
102 | # requires the Devise mappings to be loaded during boot time the application
103 | # won't boot properly.
104 | # config.reload_routes = true
105 |
106 | # ==> Configuration for :database_authenticatable
107 | # For bcrypt, this is the cost for hashing the password and defaults to 11. If
108 | # using other algorithms, it sets how many times you want the password to be hashed.
109 | #
110 | # Limiting the stretches to just one in testing will increase the performance of
111 | # your test suite dramatically. However, it is STRONGLY RECOMMENDED to not use
112 | # a value less than 10 in other environments. Note that, for bcrypt (the default
113 | # algorithm), the cost increases exponentially with the number of stretches (e.g.
114 | # a value of 20 is already extremely slow: approx. 60 seconds for 1 calculation).
115 | config.stretches = Rails.env.test? ? 1 : 11
116 |
117 | # Set up a pepper to generate the hashed password.
118 | # config.pepper = 'eb613cf35bd87beffd3d35a59a90f1105752c90eb5b8541774701cbb43417fd828375c132e0e057bc525b05bdb4eef5637a2038773600467f3fae0b1613ec6e4'
119 |
120 | # Send a notification to the original email when the user's email is changed.
121 | # config.send_email_changed_notification = false
122 |
123 | # Send a notification email when the user's password is changed.
124 | # config.send_password_change_notification = false
125 |
126 | # ==> Configuration for :confirmable
127 | # A period that the user is allowed to access the website even without
128 | # confirming their account. For instance, if set to 2.days, the user will be
129 | # able to access the website for two days without confirming their account,
130 | # access will be blocked just in the third day. Default is 0.days, meaning
131 | # the user cannot access the website without confirming their account.
132 | # config.allow_unconfirmed_access_for = 2.days
133 |
134 | # A period that the user is allowed to confirm their account before their
135 | # token becomes invalid. For example, if set to 3.days, the user can confirm
136 | # their account within 3 days after the mail was sent, but on the fourth day
137 | # their account can't be confirmed with the token any more.
138 | # Default is nil, meaning there is no restriction on how long a user can take
139 | # before confirming their account.
140 | # config.confirm_within = 3.days
141 |
142 | # If true, requires any email changes to be confirmed (exactly the same way as
143 | # initial account confirmation) to be applied. Requires additional unconfirmed_email
144 | # db field (see migrations). Until confirmed, new email is stored in
145 | # unconfirmed_email column, and copied to email column on successful confirmation.
146 | config.reconfirmable = true
147 |
148 | # Defines which key will be used when confirming an account
149 | # config.confirmation_keys = [:email]
150 |
151 | # ==> Configuration for :rememberable
152 | # The time the user will be remembered without asking for credentials again.
153 | # config.remember_for = 2.weeks
154 |
155 | # Invalidates all the remember me tokens when the user signs out.
156 | config.expire_all_remember_me_on_sign_out = true
157 |
158 | # If true, extends the user's remember period when remembered via cookie.
159 | # config.extend_remember_period = false
160 |
161 | # Options to be passed to the created cookie. For instance, you can set
162 | # secure: true in order to force SSL only cookies.
163 | # config.rememberable_options = {}
164 |
165 | # ==> Configuration for :validatable
166 | # Range for password length.
167 | config.password_length = 6..128
168 |
169 | # Email regex used to validate email formats. It simply asserts that
170 | # one (and only one) @ exists in the given string. This is mainly
171 | # to give user feedback and not to assert the e-mail validity.
172 | config.email_regexp = /\A[^@\s]+@[^@\s]+\z/
173 |
174 | # ==> Configuration for :timeoutable
175 | # The time you want to timeout the user session without activity. After this
176 | # time the user will be asked for credentials again. Default is 30 minutes.
177 | # config.timeout_in = 30.minutes
178 |
179 | # ==> Configuration for :lockable
180 | # Defines which strategy will be used to lock an account.
181 | # :failed_attempts = Locks an account after a number of failed attempts to sign in.
182 | # :none = No lock strategy. You should handle locking by yourself.
183 | # config.lock_strategy = :failed_attempts
184 |
185 | # Defines which key will be used when locking and unlocking an account
186 | # config.unlock_keys = [:email]
187 |
188 | # Defines which strategy will be used to unlock an account.
189 | # :email = Sends an unlock link to the user email
190 | # :time = Re-enables login after a certain amount of time (see :unlock_in below)
191 | # :both = Enables both strategies
192 | # :none = No unlock strategy. You should handle unlocking by yourself.
193 | # config.unlock_strategy = :both
194 |
195 | # Number of authentication tries before locking an account if lock_strategy
196 | # is failed attempts.
197 | # config.maximum_attempts = 20
198 |
199 | # Time interval to unlock the account if :time is enabled as unlock_strategy.
200 | # config.unlock_in = 1.hour
201 |
202 | # Warn on the last attempt before the account is locked.
203 | # config.last_attempt_warning = true
204 |
205 | # ==> Configuration for :recoverable
206 | #
207 | # Defines which key will be used when recovering the password for an account
208 | # config.reset_password_keys = [:email]
209 |
210 | # Time interval you can reset your password with a reset password key.
211 | # Don't put a too small interval or your users won't have the time to
212 | # change their passwords.
213 | config.reset_password_within = 6.hours
214 |
215 | # When set to false, does not sign a user in automatically after their password is
216 | # reset. Defaults to true, so a user is signed in automatically after a reset.
217 | # config.sign_in_after_reset_password = true
218 |
219 | # ==> Configuration for :encryptable
220 | # Allow you to use another hashing or encryption algorithm besides bcrypt (default).
221 | # You can use :sha1, :sha512 or algorithms from others authentication tools as
222 | # :clearance_sha1, :authlogic_sha512 (then you should set stretches above to 20
223 | # for default behavior) and :restful_authentication_sha1 (then you should set
224 | # stretches to 10, and copy REST_AUTH_SITE_KEY to pepper).
225 | #
226 | # Require the `devise-encryptable` gem when using anything other than bcrypt
227 | # config.encryptor = :sha512
228 |
229 | # ==> Scopes configuration
230 | # Turn scoped views on. Before rendering "sessions/new", it will first check for
231 | # "users/sessions/new". It's turned off by default because it's slower if you
232 | # are using only default views.
233 | # config.scoped_views = false
234 |
235 | # Configure the default scope given to Warden. By default it's the first
236 | # devise role declared in your routes (usually :user).
237 | # config.default_scope = :user
238 |
239 | # Set this configuration to false if you want /users/sign_out to sign out
240 | # only the current scope. By default, Devise signs out all scopes.
241 | # config.sign_out_all_scopes = true
242 |
243 | # ==> Navigation configuration
244 | # Lists the formats that should be treated as navigational. Formats like
245 | # :html, should redirect to the sign in page when the user does not have
246 | # access, but formats like :xml or :json, should return 401.
247 | #
248 | # If you have any extra navigational formats, like :iphone or :mobile, you
249 | # should add them to the navigational formats lists.
250 | #
251 | # The "*/*" below is required to match Internet Explorer requests.
252 | # config.navigational_formats = ['*/*', :html]
253 |
254 | # The default HTTP method used to sign out a resource. Default is :delete.
255 | config.sign_out_via = :delete
256 |
257 | # ==> OmniAuth
258 | # Add a new OmniAuth provider. Check the wiki for more information on setting
259 | # up on your models and hooks.
260 | # config.omniauth :github, 'APP_ID', 'APP_SECRET', scope: 'user,public_repo'
261 |
262 | # ==> Warden configuration
263 | # If you want to use other strategies, that are not supported by Devise, or
264 | # change the failure app, you can configure them inside the config.warden block.
265 | #
266 | # config.warden do |manager|
267 | # manager.intercept_401 = false
268 | # manager.default_strategies(scope: :user).unshift :some_external_strategy
269 | # end
270 |
271 | # ==> Mountable engine configurations
272 | # When using Devise inside an engine, let's call it `MyEngine`, and this engine
273 | # is mountable, there are some extra configurations to be taken into account.
274 | # The following options are available, assuming the engine is mounted as:
275 | #
276 | # mount MyEngine, at: '/my_engine'
277 | #
278 | # The router that invoked `devise_for`, in the example above, would be:
279 | # config.router_name = :my_engine
280 | #
281 | # When using OmniAuth, Devise cannot automatically set OmniAuth path,
282 | # so you need to do it manually. For the users scope, it would be:
283 | # config.omniauth_path_prefix = '/my_engine/users/auth'
284 | end
285 |
--------------------------------------------------------------------------------
/config/initializers/simple_form_bootstrap.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | # Please do not make direct changes to this file!
4 | # This generator is maintained by the community around simple_form-bootstrap:
5 | # https://github.com/rafaelfranca/simple_form-bootstrap
6 | # All future development, tests, and organization should happen there.
7 | # Background history: https://github.com/plataformatec/simple_form/issues/1561
8 |
9 | # Uncomment this and change the path if necessary to include your own
10 | # components.
11 | # See https://github.com/plataformatec/simple_form#custom-components
12 | # to know more about custom components.
13 | # Dir[Rails.root.join('lib/components/**/*.rb')].each { |f| require f }
14 |
15 | # Use this setup block to configure all options available in SimpleForm.
16 | SimpleForm.setup do |config|
17 | # Default class for buttons
18 | config.button_class = 'btn'
19 |
20 | # Define the default class of the input wrapper of the boolean input.
21 | config.boolean_label_class = 'form-check-label'
22 |
23 | # How the label text should be generated altogether with the required text.
24 | config.label_text = lambda { |label, required, explicit_label| "#{label} #{required}" }
25 |
26 | # Define the way to render check boxes / radio buttons with labels.
27 | config.boolean_style = :inline
28 |
29 | # You can wrap each item in a collection of radio/check boxes with a tag
30 | config.item_wrapper_tag = :div
31 |
32 | # Defines if the default input wrapper class should be included in radio
33 | # collection wrappers.
34 | config.include_default_input_wrapper_class = false
35 |
36 | # CSS class to add for error notification helper.
37 | config.error_notification_class = 'alert alert-danger'
38 |
39 | # Method used to tidy up errors. Specify any Rails Array method.
40 | # :first lists the first message for each field.
41 | # :to_sentence to list all errors for each field.
42 | config.error_method = :to_sentence
43 |
44 | # add validation classes to `input_field`
45 | config.input_field_error_class = 'is-invalid'
46 | config.input_field_valid_class = 'is-valid'
47 |
48 |
49 | # vertical forms
50 | #
51 | # vertical default_wrapper
52 | config.wrappers :vertical_form, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
53 | b.use :html5
54 | b.use :placeholder
55 | b.optional :maxlength
56 | b.optional :minlength
57 | b.optional :pattern
58 | b.optional :min_max
59 | b.optional :readonly
60 | b.use :label, class: 'form-control-label'
61 | b.use :input, class: 'form-control', error_class: 'is-invalid', valid_class: 'is-valid'
62 | b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
63 | b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
64 | end
65 |
66 | # vertical input for boolean
67 | config.wrappers :vertical_boolean, tag: 'fieldset', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
68 | b.use :html5
69 | b.optional :readonly
70 | b.wrapper :form_check_wrapper, tag: 'div', class: 'form-check' do |bb|
71 | bb.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid'
72 | bb.use :label, class: 'form-check-label'
73 | bb.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
74 | bb.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
75 | end
76 | end
77 |
78 | # vertical input for radio buttons and check boxes
79 | config.wrappers :vertical_collection, item_wrapper_class: 'form-check', tag: 'fieldset', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
80 | b.use :html5
81 | b.optional :readonly
82 | b.wrapper :legend_tag, tag: 'legend', class: 'col-form-label pt-0' do |ba|
83 | ba.use :label_text
84 | end
85 | b.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid'
86 | b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
87 | b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
88 | end
89 |
90 | # vertical input for inline radio buttons and check boxes
91 | config.wrappers :vertical_collection_inline, item_wrapper_class: 'form-check form-check-inline', tag: 'fieldset', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
92 | b.use :html5
93 | b.optional :readonly
94 | b.wrapper :legend_tag, tag: 'legend', class: 'col-form-label pt-0' do |ba|
95 | ba.use :label_text
96 | end
97 | b.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid'
98 | b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
99 | b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
100 | end
101 |
102 | # vertical file input
103 | config.wrappers :vertical_file, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
104 | b.use :html5
105 | b.use :placeholder
106 | b.optional :maxlength
107 | b.optional :minlength
108 | b.optional :readonly
109 | b.use :label
110 | b.use :input, class: 'form-control-file', error_class: 'is-invalid', valid_class: 'is-valid'
111 | b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
112 | b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
113 | end
114 |
115 | # vertical multi select
116 | config.wrappers :vertical_multi_select, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
117 | b.use :html5
118 | b.optional :readonly
119 | b.use :label, class: 'form-control-label'
120 | b.wrapper tag: 'div', class: 'd-flex flex-row justify-content-between align-items-center' do |ba|
121 | ba.use :input, class: 'form-control mx-1', error_class: 'is-invalid', valid_class: 'is-valid'
122 | end
123 | b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
124 | b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
125 | end
126 |
127 | # vertical range input
128 | config.wrappers :vertical_range, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
129 | b.use :html5
130 | b.use :placeholder
131 | b.optional :readonly
132 | b.optional :step
133 | b.use :label
134 | b.use :input, class: 'form-control-range', error_class: 'is-invalid', valid_class: 'is-valid'
135 | b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
136 | b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
137 | end
138 |
139 |
140 | # horizontal forms
141 | #
142 | # horizontal default_wrapper
143 | config.wrappers :horizontal_form, tag: 'div', class: 'form-group row', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
144 | b.use :html5
145 | b.use :placeholder
146 | b.optional :maxlength
147 | b.optional :minlength
148 | b.optional :pattern
149 | b.optional :min_max
150 | b.optional :readonly
151 | b.use :label, class: 'col-sm-3 col-form-label'
152 | b.wrapper :grid_wrapper, tag: 'div', class: 'col-sm-9' do |ba|
153 | ba.use :input, class: 'form-control', error_class: 'is-invalid', valid_class: 'is-valid'
154 | ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
155 | ba.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
156 | end
157 | end
158 |
159 | # horizontal input for boolean
160 | config.wrappers :horizontal_boolean, tag: 'div', class: 'form-group row', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
161 | b.use :html5
162 | b.optional :readonly
163 | b.wrapper tag: 'label', class: 'col-sm-3' do |ba|
164 | ba.use :label_text
165 | end
166 | b.wrapper :grid_wrapper, tag: 'div', class: 'col-sm-9' do |wr|
167 | wr.wrapper :form_check_wrapper, tag: 'div', class: 'form-check' do |bb|
168 | bb.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid'
169 | bb.use :label, class: 'form-check-label'
170 | bb.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
171 | bb.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
172 | end
173 | end
174 | end
175 |
176 | # horizontal input for radio buttons and check boxes
177 | config.wrappers :horizontal_collection, item_wrapper_class: 'form-check', tag: 'div', class: 'form-group row', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
178 | b.use :html5
179 | b.optional :readonly
180 | b.use :label, class: 'col-sm-3 form-control-label'
181 | b.wrapper :grid_wrapper, tag: 'div', class: 'col-sm-9' do |ba|
182 | ba.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid'
183 | ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
184 | ba.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
185 | end
186 | end
187 |
188 | # horizontal input for inline radio buttons and check boxes
189 | config.wrappers :horizontal_collection_inline, item_wrapper_class: 'form-check form-check-inline', tag: 'div', class: 'form-group row', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
190 | b.use :html5
191 | b.optional :readonly
192 | b.use :label, class: 'col-sm-3 form-control-label'
193 | b.wrapper :grid_wrapper, tag: 'div', class: 'col-sm-9' do |ba|
194 | ba.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid'
195 | ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
196 | ba.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
197 | end
198 | end
199 |
200 | # horizontal file input
201 | config.wrappers :horizontal_file, tag: 'div', class: 'form-group row', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
202 | b.use :html5
203 | b.use :placeholder
204 | b.optional :maxlength
205 | b.optional :minlength
206 | b.optional :readonly
207 | b.use :label, class: 'col-sm-3 form-control-label'
208 | b.wrapper :grid_wrapper, tag: 'div', class: 'col-sm-9' do |ba|
209 | ba.use :input, error_class: 'is-invalid', valid_class: 'is-valid'
210 | ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
211 | ba.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
212 | end
213 | end
214 |
215 | # horizontal multi select
216 | config.wrappers :horizontal_multi_select, tag: 'div', class: 'form-group row', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
217 | b.use :html5
218 | b.optional :readonly
219 | b.use :label, class: 'col-sm-3 control-label'
220 | b.wrapper :grid_wrapper, tag: 'div', class: 'col-sm-9' do |ba|
221 | ba.wrapper tag: 'div', class: 'd-flex flex-row justify-content-between align-items-center' do |bb|
222 | bb.use :input, class: 'form-control mx-1', error_class: 'is-invalid', valid_class: 'is-valid'
223 | end
224 | ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
225 | ba.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
226 | end
227 | end
228 |
229 | # horizontal range input
230 | config.wrappers :horizontal_range, tag: 'div', class: 'form-group row', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
231 | b.use :html5
232 | b.use :placeholder
233 | b.optional :readonly
234 | b.optional :step
235 | b.use :label, class: 'col-sm-3 form-control-label'
236 | b.wrapper :grid_wrapper, tag: 'div', class: 'col-sm-9' do |ba|
237 | ba.use :input, class: 'form-control-range', error_class: 'is-invalid', valid_class: 'is-valid'
238 | ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
239 | ba.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
240 | end
241 | end
242 |
243 |
244 | # inline forms
245 | #
246 | # inline default_wrapper
247 | config.wrappers :inline_form, tag: 'span', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
248 | b.use :html5
249 | b.use :placeholder
250 | b.optional :maxlength
251 | b.optional :minlength
252 | b.optional :pattern
253 | b.optional :min_max
254 | b.optional :readonly
255 | b.use :label, class: 'sr-only'
256 |
257 | b.use :input, class: 'form-control', error_class: 'is-invalid', valid_class: 'is-valid'
258 | b.use :error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
259 | b.optional :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
260 | end
261 |
262 | # inline input for boolean
263 | config.wrappers :inline_boolean, tag: 'span', class: 'form-check flex-wrap justify-content-start mr-sm-2', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
264 | b.use :html5
265 | b.optional :readonly
266 | b.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid'
267 | b.use :label, class: 'form-check-label'
268 | b.use :error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
269 | b.optional :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
270 | end
271 |
272 |
273 | # bootstrap custom forms
274 | #
275 | # custom input for boolean
276 | config.wrappers :custom_boolean, tag: 'fieldset', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
277 | b.use :html5
278 | b.optional :readonly
279 | b.wrapper :form_check_wrapper, tag: 'div', class: 'custom-control custom-checkbox' do |bb|
280 | bb.use :input, class: 'custom-control-input', error_class: 'is-invalid', valid_class: 'is-valid'
281 | bb.use :label, class: 'custom-control-label'
282 | bb.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
283 | bb.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
284 | end
285 | end
286 |
287 | config.wrappers :custom_boolean_switch, tag: 'fieldset', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
288 | b.use :html5
289 | b.optional :readonly
290 | b.wrapper :form_check_wrapper, tag: 'div', class: 'custom-control custom-checkbox-switch' do |bb|
291 | bb.use :input, class: 'custom-control-input', error_class: 'is-invalid', valid_class: 'is-valid'
292 | bb.use :label, class: 'custom-control-label'
293 | bb.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
294 | bb.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
295 | end
296 | end
297 |
298 | # custom input for radio buttons and check boxes
299 | config.wrappers :custom_collection, item_wrapper_class: 'custom-control', tag: 'fieldset', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
300 | b.use :html5
301 | b.optional :readonly
302 | b.wrapper :legend_tag, tag: 'legend', class: 'col-form-label pt-0' do |ba|
303 | ba.use :label_text
304 | end
305 | b.use :input, class: 'custom-control-input', error_class: 'is-invalid', valid_class: 'is-valid'
306 | b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
307 | b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
308 | end
309 |
310 | # custom input for inline radio buttons and check boxes
311 | config.wrappers :custom_collection_inline, item_wrapper_class: 'custom-control custom-control-inline', tag: 'fieldset', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
312 | b.use :html5
313 | b.optional :readonly
314 | b.wrapper :legend_tag, tag: 'legend', class: 'col-form-label pt-0' do |ba|
315 | ba.use :label_text
316 | end
317 | b.use :input, class: 'custom-control-input', error_class: 'is-invalid', valid_class: 'is-valid'
318 | b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
319 | b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
320 | end
321 |
322 | # custom file input
323 | config.wrappers :custom_file, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
324 | b.use :html5
325 | b.use :placeholder
326 | b.optional :maxlength
327 | b.optional :minlength
328 | b.optional :readonly
329 | b.use :label, class: 'form-control-label'
330 | b.wrapper :custom_file_wrapper, tag: 'div', class: 'custom-file' do |ba|
331 | ba.use :input, class: 'custom-file-input', error_class: 'is-invalid', valid_class: 'is-valid'
332 | ba.use :label, class: 'custom-file-label'
333 | ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
334 | end
335 | b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
336 | end
337 |
338 | # custom multi select
339 | config.wrappers :custom_multi_select, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
340 | b.use :html5
341 | b.optional :readonly
342 | b.use :label, class: 'form-control-label'
343 | b.wrapper tag: 'div', class: 'd-flex flex-row justify-content-between align-items-center' do |ba|
344 | ba.use :input, class: 'custom-select mx-1', error_class: 'is-invalid', valid_class: 'is-valid'
345 | end
346 | b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
347 | b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
348 | end
349 |
350 | # custom range input
351 | config.wrappers :custom_range, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
352 | b.use :html5
353 | b.use :placeholder
354 | b.optional :readonly
355 | b.optional :step
356 | b.use :label, class: 'form-control-label'
357 | b.use :input, class: 'custom-range', error_class: 'is-invalid', valid_class: 'is-valid'
358 | b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
359 | b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
360 | end
361 |
362 |
363 | # Input Group - custom component
364 | # see example app and config at https://github.com/rafaelfranca/simple_form-bootstrap
365 | # config.wrappers :input_group, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
366 | # b.use :html5
367 | # b.use :placeholder
368 | # b.optional :maxlength
369 | # b.optional :minlength
370 | # b.optional :pattern
371 | # b.optional :min_max
372 | # b.optional :readonly
373 | # b.use :label, class: 'form-control-label'
374 | # b.wrapper :input_group_tag, tag: 'div', class: 'input-group' do |ba|
375 | # ba.optional :prepend
376 | # ba.use :input, class: 'form-control', error_class: 'is-invalid', valid_class: 'is-valid'
377 | # ba.optional :append
378 | # end
379 | # b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
380 | # b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
381 | # end
382 |
383 |
384 | # Floating Labels form
385 | #
386 | # floating labels default_wrapper
387 | config.wrappers :floating_labels_form, tag: 'div', class: 'form-label-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
388 | b.use :html5
389 | b.use :placeholder
390 | b.optional :maxlength
391 | b.optional :minlength
392 | b.optional :pattern
393 | b.optional :min_max
394 | b.optional :readonly
395 | b.use :input, class: 'form-control', error_class: 'is-invalid', valid_class: 'is-valid'
396 | b.use :label, class: 'form-control-label'
397 | b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
398 | b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
399 | end
400 |
401 | # custom multi select
402 | config.wrappers :floating_labels_select, tag: 'div', class: 'form-label-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
403 | b.use :html5
404 | b.optional :readonly
405 | b.use :input, class: 'custom-select custom-select-lg', error_class: 'is-invalid', valid_class: 'is-valid'
406 | b.use :label, class: 'form-control-label'
407 | b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
408 | b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
409 | end
410 |
411 |
412 | # The default wrapper to be used by the FormBuilder.
413 | config.default_wrapper = :vertical_form
414 |
415 | # Custom wrappers for input types. This should be a hash containing an input
416 | # type as key and the wrapper that will be used for all inputs with specified type.
417 | config.wrapper_mappings = {
418 | boolean: :vertical_boolean,
419 | check_boxes: :vertical_collection,
420 | date: :vertical_multi_select,
421 | datetime: :vertical_multi_select,
422 | file: :vertical_file,
423 | radio_buttons: :vertical_collection,
424 | range: :vertical_range,
425 | time: :vertical_multi_select
426 | }
427 |
428 | # enable custom form wrappers
429 | # config.wrapper_mappings = {
430 | # boolean: :custom_boolean,
431 | # check_boxes: :custom_collection,
432 | # date: :custom_multi_select,
433 | # datetime: :custom_multi_select,
434 | # file: :custom_file,
435 | # radio_buttons: :custom_collection,
436 | # range: :custom_range,
437 | # time: :custom_multi_select
438 | # }
439 | end
440 |
--------------------------------------------------------------------------------