├── log └── .keep ├── storage └── .keep ├── tmp ├── .keep ├── pids │ └── .keep └── storage │ └── .keep ├── vendor └── .keep ├── lib ├── assets │ └── .keep └── tasks │ └── .keep ├── public ├── favicon.ico ├── apple-touch-icon.png ├── apple-touch-icon-precomposed.png ├── robots.txt ├── 500.html ├── 422.html └── 404.html ├── test ├── helpers │ └── .keep ├── mailers │ └── .keep ├── models │ └── .keep ├── system │ └── .keep ├── controllers │ └── .keep ├── integration │ └── .keep ├── fixtures │ └── files │ │ └── .keep ├── application_system_test_case.rb ├── channels │ └── application_cable │ │ └── connection_test.rb └── test_helper.rb ├── app ├── assets │ ├── images │ │ └── .keep │ ├── javascripts │ │ └── active_admin.js │ ├── config │ │ └── manifest.js │ └── stylesheets │ │ ├── active_admin.scss │ │ └── application.css ├── models │ ├── concerns │ │ └── .keep │ └── application_record.rb ├── controllers │ ├── concerns │ │ └── .keep │ └── application_controller.rb ├── views │ └── layouts │ │ ├── mailer.text.erb │ │ ├── mailer.html.erb │ │ └── application.html.erb ├── helpers │ └── application_helper.rb ├── channels │ └── application_cable │ │ ├── channel.rb │ │ └── connection.rb ├── mailers │ └── application_mailer.rb ├── jobs │ └── application_job.rb └── avo │ ├── resources │ ├── order_detail_resource.rb │ ├── category_resource.rb │ ├── employee_resource.rb │ ├── order_resource.rb │ ├── product_resource.rb │ └── customer_resource.rb │ └── actions │ └── export_csv.rb ├── .ruby-version ├── bin ├── rake ├── rails └── setup ├── config ├── initializers │ ├── motor-admin.txt │ ├── forest_liana.rb │ ├── filter_parameter_logging.rb │ ├── permissions_policy.rb │ ├── assets.rb │ ├── inflections.rb │ ├── content_security_policy.rb │ ├── rails_admin.rb │ ├── trestle.rb │ ├── avo.rb │ ├── active_admin.rb │ └── brick.rb ├── environment.rb ├── boot.rb ├── cable.yml ├── locales │ ├── pagy │ │ ├── nn.yml │ │ └── ro.yml │ ├── en.yml │ ├── avo.nn.yml │ ├── avo.nb.yml │ ├── avo.en.yml │ ├── avo.tr.yml │ ├── avo.pt.yml │ ├── avo.pt-BR.yml │ ├── avo.ro.yml │ └── avo.fr.yml ├── application.rb ├── storage.yml ├── routes.rb ├── puma.rb ├── environments │ ├── test.rb │ ├── development.rb │ └── production.rb └── database.yml ├── config.ru ├── Rakefile ├── .gitattributes ├── db ├── migrate │ ├── 20230226200200_create_categories.rb │ ├── 20230218103708_create_active_admin_comments.rb │ ├── 20230226200700_create_order_details.rb │ ├── 20230226200300_create_customers.rb │ ├── 20230226200600_create_products.rb │ ├── 20230226200400_create_employees.rb │ ├── 20230226200500_create_orders.rb │ └── 20230221083939_install_motor_admin.rb └── schema.rb ├── .gitignore ├── README.md ├── Gemfile └── Gemfile.lock /log/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /storage/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tmp/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vendor/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /lib/assets/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /lib/tasks/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/helpers/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/mailers/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/models/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/system/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tmp/pids/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tmp/storage/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/assets/images/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/controllers/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/integration/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.ruby-version: -------------------------------------------------------------------------------- 1 | ruby-3.2.0 2 | -------------------------------------------------------------------------------- /app/models/concerns/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/apple-touch-icon.png: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/fixtures/files/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/controllers/concerns/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/apple-touch-icon-precomposed.png: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/views/layouts/mailer.text.erb: -------------------------------------------------------------------------------- 1 | <%= yield %> 2 | -------------------------------------------------------------------------------- /app/assets/javascripts/active_admin.js: -------------------------------------------------------------------------------- 1 | //= require active_admin/base 2 | -------------------------------------------------------------------------------- /app/helpers/application_helper.rb: -------------------------------------------------------------------------------- 1 | module ApplicationHelper 2 | end 3 | -------------------------------------------------------------------------------- /app/assets/config/manifest.js: -------------------------------------------------------------------------------- 1 | //= link_tree ../images 2 | //= link_directory ../stylesheets .css 3 | -------------------------------------------------------------------------------- /app/controllers/application_controller.rb: -------------------------------------------------------------------------------- 1 | class ApplicationController < ActionController::Base 2 | end 3 | -------------------------------------------------------------------------------- /app/models/application_record.rb: -------------------------------------------------------------------------------- 1 | class ApplicationRecord < ActiveRecord::Base 2 | primary_abstract_class 3 | end 4 | -------------------------------------------------------------------------------- /bin/rake: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require_relative "../config/boot" 3 | require "rake" 4 | Rake.application.run 5 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # See https://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file 2 | -------------------------------------------------------------------------------- /config/initializers/motor-admin.txt: -------------------------------------------------------------------------------- 1 | Motor Admin doesn't use an initializer for its settings -- all settings are located in tables! -------------------------------------------------------------------------------- /app/channels/application_cable/channel.rb: -------------------------------------------------------------------------------- 1 | module ApplicationCable 2 | class Channel < ActionCable::Channel::Base 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /app/channels/application_cable/connection.rb: -------------------------------------------------------------------------------- 1 | module ApplicationCable 2 | class Connection < ActionCable::Connection::Base 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /app/mailers/application_mailer.rb: -------------------------------------------------------------------------------- 1 | class ApplicationMailer < ActionMailer::Base 2 | default from: "from@example.com" 3 | layout "mailer" 4 | end 5 | -------------------------------------------------------------------------------- /bin/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | APP_PATH = File.expand_path("../config/application", __dir__) 3 | require_relative "../config/boot" 4 | require "rails/commands" 5 | -------------------------------------------------------------------------------- /config/environment.rb: -------------------------------------------------------------------------------- 1 | # Load the Rails application. 2 | require_relative "application" 3 | 4 | # Initialize the Rails application. 5 | Rails.application.initialize! 6 | -------------------------------------------------------------------------------- /config.ru: -------------------------------------------------------------------------------- 1 | # This file is used by Rack-based servers to start the application. 2 | 3 | require_relative "config/environment" 4 | 5 | run Rails.application 6 | Rails.application.load_server 7 | -------------------------------------------------------------------------------- /test/application_system_test_case.rb: -------------------------------------------------------------------------------- 1 | require "test_helper" 2 | 3 | class ApplicationSystemTestCase < ActionDispatch::SystemTestCase 4 | driven_by :selenium, using: :chrome, screen_size: [1400, 1400] 5 | end 6 | -------------------------------------------------------------------------------- /config/boot.rb: -------------------------------------------------------------------------------- 1 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) 2 | 3 | require "bundler/setup" # Set up gems listed in the Gemfile. 4 | require "bootsnap/setup" # Speed up boot time by caching expensive operations. 5 | -------------------------------------------------------------------------------- /config/initializers/forest_liana.rb: -------------------------------------------------------------------------------- 1 | if Object.const_defined?('ForestLiana') 2 | ForestLiana.env_secret = Rails.application.secrets.forest_env_secret 3 | ForestLiana.auth_secret = Rails.application.secrets.forest_auth_secret 4 | end 5 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # Add your own tasks in files placed in lib/tasks ending in .rake, 2 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. 3 | 4 | require_relative "config/application" 5 | 6 | Rails.application.load_tasks 7 | -------------------------------------------------------------------------------- /config/cable.yml: -------------------------------------------------------------------------------- 1 | development: 2 | adapter: async 3 | 4 | test: 5 | adapter: test 6 | 7 | production: 8 | adapter: redis 9 | url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %> 10 | channel_prefix: admin_panel_comparison_production 11 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # See https://git-scm.com/docs/gitattributes for more about git attribute files. 2 | 3 | # Mark the database schema as having been generated. 4 | db/schema.rb linguist-generated 5 | 6 | # Mark any vendored files as having been vendored. 7 | vendor/* linguist-vendored 8 | -------------------------------------------------------------------------------- /app/jobs/application_job.rb: -------------------------------------------------------------------------------- 1 | class ApplicationJob < ActiveJob::Base 2 | # Automatically retry jobs that encountered a deadlock 3 | # retry_on ActiveRecord::Deadlocked 4 | 5 | # Most jobs are safe to ignore if the underlying records are no longer available 6 | # discard_on ActiveJob::DeserializationError 7 | end 8 | -------------------------------------------------------------------------------- /app/views/layouts/mailer.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 10 | 11 | <%= yield %> 12 | 13 | 14 | -------------------------------------------------------------------------------- /test/channels/application_cable/connection_test.rb: -------------------------------------------------------------------------------- 1 | require "test_helper" 2 | 3 | class ApplicationCable::ConnectionTest < ActionCable::Connection::TestCase 4 | # test "connects with cookies" do 5 | # cookies.signed[:user_id] = 42 6 | # 7 | # connect 8 | # 9 | # assert_equal connection.user_id, "42" 10 | # end 11 | end 12 | -------------------------------------------------------------------------------- /app/views/layouts/application.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | AdminPanelComparison 5 | 6 | <%= csrf_meta_tags %> 7 | <%= csp_meta_tag %> 8 | 9 | <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %> 10 | 11 | 12 | 13 | <%= yield %> 14 | 15 | 16 | -------------------------------------------------------------------------------- /test/test_helper.rb: -------------------------------------------------------------------------------- 1 | ENV["RAILS_ENV"] ||= "test" 2 | require_relative "../config/environment" 3 | require "rails/test_help" 4 | 5 | class ActiveSupport::TestCase 6 | # Run tests in parallel with specified workers 7 | parallelize(workers: :number_of_processors) 8 | 9 | # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order. 10 | fixtures :all 11 | 12 | # Add more helper methods to be used by all tests here... 13 | end 14 | -------------------------------------------------------------------------------- /config/initializers/filter_parameter_logging.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Configure parameters to be filtered from the log file. Use this to limit dissemination of 4 | # sensitive information. See the ActiveSupport::ParameterFilter documentation for supported 5 | # notations and behaviors. 6 | Rails.application.config.filter_parameters += [ 7 | :passw, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn 8 | ] 9 | -------------------------------------------------------------------------------- /config/initializers/permissions_policy.rb: -------------------------------------------------------------------------------- 1 | # Define an application-wide HTTP permissions policy. For further 2 | # information see https://developers.google.com/web/updates/2018/06/feature-policy 3 | # 4 | # Rails.application.config.permissions_policy do |f| 5 | # f.camera :none 6 | # f.gyroscope :none 7 | # f.microphone :none 8 | # f.usb :none 9 | # f.fullscreen :self 10 | # f.payment :self, "https://secure.example.com" 11 | # end 12 | -------------------------------------------------------------------------------- /db/migrate/20230226200200_create_categories.rb: -------------------------------------------------------------------------------- 1 | class CreateCategories < ActiveRecord::Migration[7.0] 2 | def change 3 | return unless reverting? || !table_exists?(:categories) || 4 | ActiveRecord::Base.connection.current_database == 'northwind' 5 | 6 | create_table :categories, id: :serial, primary_key: :id do |t| 7 | t.string :category_name 8 | t.string :description 9 | t.binary :picture 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /db/migrate/20230218103708_create_active_admin_comments.rb: -------------------------------------------------------------------------------- 1 | class CreateActiveAdminComments < ActiveRecord::Migration[7.0] 2 | def self.up 3 | create_table :active_admin_comments do |t| 4 | t.string :namespace 5 | t.text :body 6 | t.references :resource, polymorphic: true 7 | t.references :author, polymorphic: true 8 | t.timestamps 9 | end 10 | add_index :active_admin_comments, [:namespace] 11 | end 12 | 13 | def self.down 14 | drop_table :active_admin_comments 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /app/avo/resources/order_detail_resource.rb: -------------------------------------------------------------------------------- 1 | class OrderDetailResource < Avo::BaseResource 2 | self.title = :id 3 | self.includes = [] 4 | # self.search_query = -> do 5 | # scope.ransack(id_eq: params[:q], m: "or").result(distinct: false) 6 | # end 7 | 8 | field :id, as: :id 9 | # Fields generated from the model 10 | field :order, as: :belongs_to 11 | field :product, as: :belongs_to 12 | field :unit_price, as: :number 13 | field :quantity, as: :number 14 | field :discount, as: :number 15 | # add fields here 16 | end 17 | -------------------------------------------------------------------------------- /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 | 9 | # Precompile additional assets. 10 | # application.js, application.css, and all non-JS/CSS in the app/assets 11 | # folder are already added. 12 | # Rails.application.config.assets.precompile += %w( admin.js admin.css ) 13 | -------------------------------------------------------------------------------- /config/locales/pagy/nn.yml: -------------------------------------------------------------------------------- 1 | nn: 2 | pagy: 3 | item_name: 4 | one: "resultat" 5 | other: "resultat" 6 | nav: 7 | prev: "‹ Førre" 8 | next: "Neste ›" 9 | gap: "…" 10 | info: 11 | no_items: "Ingen %{item_name} funne" 12 | single_page: "Viser %{count} %{item_name}" 13 | multiple_pages: "Viser %{item_name} %{from}-%{to} av totalt %{count}" 14 | combo_nav_js: "" 15 | items_selector_js: "" 16 | -------------------------------------------------------------------------------- /db/migrate/20230226200700_create_order_details.rb: -------------------------------------------------------------------------------- 1 | class CreateOrderDetails < ActiveRecord::Migration[7.0] 2 | def change 3 | return unless reverting? || !table_exists?(:order_details) || 4 | ActiveRecord::Base.connection.current_database == 'northwind' 5 | 6 | create_table :order_details, id: :serial, primary_key: :id do |t| 7 | t.decimal :unit_price 8 | t.integer :quantity 9 | t.decimal :discount 10 | t.references :order, type: :integer, foreign_key: { to_table: :orders } 11 | t.references :product, type: :integer, foreign_key: { to_table: :products } 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /app/assets/stylesheets/active_admin.scss: -------------------------------------------------------------------------------- 1 | // Sass variable overrides must be declared before loading up Active Admin's styles. 2 | // 3 | // To view the variables that Active Admin provides, take a look at 4 | // `app/assets/stylesheets/active_admin/mixins/_variables.scss` in the 5 | // Active Admin source. 6 | // 7 | // For example, to change the sidebar width: 8 | // $sidebar-width: 242px; 9 | 10 | // Active Admin's got SASS! 11 | @import "active_admin/mixins"; 12 | @import "active_admin/base"; 13 | 14 | // Overriding any non-variable Sass must be done after the fact. 15 | // For example, to change the default status-tag color: 16 | // 17 | // .status_tag { background: #6090DB; } 18 | -------------------------------------------------------------------------------- /db/migrate/20230226200300_create_customers.rb: -------------------------------------------------------------------------------- 1 | class CreateCustomers < ActiveRecord::Migration[7.0] 2 | def change 3 | return unless reverting? || !table_exists?(:customers) || 4 | ActiveRecord::Base.connection.current_database == 'northwind' 5 | 6 | create_table :customers, id: :serial, primary_key: :id do |t| 7 | t.string :company_code 8 | t.string :company_name 9 | t.string :contact_name 10 | t.string :contact_title 11 | t.string :address 12 | t.string :city 13 | t.string :region 14 | t.string :postal_code 15 | t.string :country 16 | t.string :phone 17 | t.string :fax 18 | end 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /config/locales/pagy/ro.yml: -------------------------------------------------------------------------------- 1 | # :one_other pluralization (see https://github.com/ddnexus/pagy/blob/master/lib/locales/utils/p11n.rb) 2 | 3 | ro: 4 | pagy: 5 | item_name: 6 | one: "un record" 7 | other: "recorduri" 8 | nav: 9 | prev: "‹ Înapoi" 10 | next: "Înainte ›" 11 | gap: "…" 12 | info: 13 | no_items: "Nici %{item_name} găsit" 14 | single_page: "%{count} %{item_name}" 15 | multiple_pages: "%{from}-%{to} din totalul de %{count}" 16 | combo_nav_js: "" 17 | items_selector_js: "" 18 | -------------------------------------------------------------------------------- /db/migrate/20230226200600_create_products.rb: -------------------------------------------------------------------------------- 1 | class CreateProducts < ActiveRecord::Migration[7.0] 2 | def change 3 | return unless reverting? || !table_exists?(:products) || 4 | ActiveRecord::Base.connection.current_database == 'northwind' 5 | 6 | create_table :products, id: :serial, primary_key: :id do |t| 7 | t.string :product_name 8 | t.references :category, type: :integer, foreign_key: { to_table: :categories } 9 | t.decimal :unit_price 10 | t.boolean :discontinued 11 | t.integer :units_in_stock 12 | t.integer :units_on_order 13 | t.integer :reorder_level 14 | t.string :quantity_per_unit 15 | t.integer :supplier_id 16 | end 17 | end 18 | end 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/assets/stylesheets/application.css: -------------------------------------------------------------------------------- 1 | /* 2 | * This is a manifest file that'll be compiled into application.css, which will include all the files 3 | * listed below. 4 | * 5 | * Any CSS (and SCSS, if configured) file within this directory, lib/assets/stylesheets, or any plugin's 6 | * vendor/assets/stylesheets directory can be referenced here using a relative path. 7 | * 8 | * You're free to add application-wide styles to this file and they'll appear at the bottom of the 9 | * compiled file so the styles you add here take precedence over styles defined in any other CSS 10 | * files in this directory. Styles in this file should be added after the last require_* statement. 11 | * It is generally better to create a new file per style scope. 12 | * 13 | *= require_tree . 14 | *= require_self 15 | */ 16 | -------------------------------------------------------------------------------- /config/application.rb: -------------------------------------------------------------------------------- 1 | require_relative "boot" 2 | 3 | require "rails/all" 4 | 5 | # Require the gems listed in Gemfile, including any gems 6 | # you've limited to :test, :development, or :production. 7 | Bundler.require(*Rails.groups) 8 | 9 | module AdminPanelComparison 10 | class Application < Rails::Application 11 | # Initialize configuration defaults for originally generated Rails version. 12 | config.load_defaults 7.0 13 | 14 | # Configuration for the application, engines, and railties goes here. 15 | # 16 | # These settings can be overridden in specific environments using the files 17 | # in config/environments, which are processed later. 18 | # 19 | # config.time_zone = "Central Time (US & Canada)" 20 | # config.eager_load_paths << Rails.root.join("extras") 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /db/migrate/20230226200400_create_employees.rb: -------------------------------------------------------------------------------- 1 | class CreateEmployees < ActiveRecord::Migration[7.0] 2 | def change 3 | return unless reverting? || !table_exists?(:employees) || 4 | ActiveRecord::Base.connection.current_database == 'northwind' 5 | 6 | create_table :employees, id: :serial, primary_key: :id do |t| 7 | t.string :first_name 8 | t.string :last_name 9 | t.string :title 10 | t.string :title_of_courtesy 11 | t.references :reports_to, type: :integer 12 | t.date :birth_date 13 | t.date :hire_date 14 | t.binary :photo 15 | t.string :address 16 | t.string :city 17 | t.string :region 18 | t.string :postal_code 19 | t.string :country 20 | t.string :home_phone 21 | t.string :extension 22 | t.text :notes 23 | end 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files for more about ignoring files. 2 | # 3 | # If you find yourself ignoring temporary files generated by your text editor 4 | # or operating system, you probably want to add a global ignore instead: 5 | # git config --global core.excludesfile '~/.gitignore_global' 6 | 7 | # Ignore bundler config. 8 | /.bundle 9 | 10 | # Ignore all logfiles and tempfiles. 11 | /log/* 12 | /tmp/* 13 | !/log/.keep 14 | !/tmp/.keep 15 | 16 | # Ignore pidfiles, but keep the directory. 17 | /tmp/pids/* 18 | !/tmp/pids/ 19 | !/tmp/pids/.keep 20 | 21 | # Ignore uploaded files in development. 22 | /storage/* 23 | !/storage/.keep 24 | /tmp/storage/* 25 | !/tmp/storage/ 26 | !/tmp/storage/.keep 27 | 28 | /public/assets 29 | 30 | # Ignore master key for decrypting credentials and more. 31 | /config/master.key 32 | /config/secrets.yml 33 | /config/credentials.yml.enc 34 | -------------------------------------------------------------------------------- /db/migrate/20230226200500_create_orders.rb: -------------------------------------------------------------------------------- 1 | class CreateOrders < ActiveRecord::Migration[7.0] 2 | def change 3 | return unless reverting? || !table_exists?(:orders) || 4 | ActiveRecord::Base.connection.current_database == 'northwind' 5 | 6 | create_table :orders, id: :serial, primary_key: :id do |t| 7 | t.date :order_date 8 | t.references :customer, type: :integer, foreign_key: { to_table: :customers } 9 | t.references :employee, type: :integer, foreign_key: { to_table: :employees } 10 | t.date :required_date 11 | t.date :shipped_date 12 | t.integer :ship_via_id 13 | t.decimal :freight 14 | t.string :ship_name 15 | t.string :ship_address 16 | t.string :ship_city 17 | t.string :ship_region 18 | t.string :ship_postal_code 19 | t.string :ship_country 20 | t.string :customer_code 21 | end 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /app/avo/resources/category_resource.rb: -------------------------------------------------------------------------------- 1 | class CategoryResource < Avo::BaseResource 2 | self.title = :category_name 3 | self.includes = [:products] 4 | self.record_selector = false 5 | self.description = "Category picture is rendered from binary data stored in the database." 6 | 7 | field :category_name, as: :text 8 | field :description, as: :trix, always_show: true 9 | field :description_excerpt, as: :text, only_on: :index do |category| 10 | ActionView::Base.full_sanitizer.sanitize(category.description).truncate 120 11 | end 12 | field :picture, as: :text do |category| 13 | # Have Brick create an element using inline Base64 when there is a picture available 14 | ::Brick::Rails.display_binary(category.picture).html_safe 15 | rescue 16 | nil 17 | end 18 | field :products, as: :has_many, discreet_pagination: true, searchable: true 19 | field :product_count, as: :number, only_on: :index do |category| 20 | category.products.count 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /config/locales/en.yml: -------------------------------------------------------------------------------- 1 | # Files in the config/locales directory are used for internationalization 2 | # and are automatically loaded by Rails. If you want to use locales other 3 | # than English, add the necessary files in this directory. 4 | # 5 | # To use the locales, use `I18n.t`: 6 | # 7 | # I18n.t "hello" 8 | # 9 | # In views, this is aliased to just `t`: 10 | # 11 | # <%= t("hello") %> 12 | # 13 | # To use a different locale, set it with `I18n.locale`: 14 | # 15 | # I18n.locale = :es 16 | # 17 | # This would use the information in config/locales/es.yml. 18 | # 19 | # The following keys must be escaped otherwise they will not be retrieved by 20 | # the default I18n backend: 21 | # 22 | # true, false, on, off, yes, no 23 | # 24 | # Instead, surround them with single quotes. 25 | # 26 | # en: 27 | # "true": "foo" 28 | # 29 | # To learn more, please read the Rails Internationalization guide 30 | # available at https://guides.rubyonrails.org/i18n.html. 31 | 32 | en: 33 | hello: "Hello world" 34 | -------------------------------------------------------------------------------- /app/avo/resources/employee_resource.rb: -------------------------------------------------------------------------------- 1 | class EmployeeResource < Avo::BaseResource 2 | self.title = :first_name 3 | self.includes = [] 4 | 5 | field :id, as: :id 6 | field :name, as: :text do |employee| 7 | "#{employee.title_of_courtesy} #{employee.first_name} #{employee.last_name}" 8 | end 9 | 10 | with_options as: :text, hide_on: :index do 11 | field :first_name 12 | field :last_name 13 | field :title_of_courtesy 14 | end 15 | 16 | field :title, as: :text 17 | field :reports_to, as: :belongs_to 18 | field :hire_date, as: :date 19 | 20 | heading "Address" 21 | field :city, as: :text 22 | field :country, as: :text 23 | 24 | heading "Contact" 25 | field :home_phone, as: :text 26 | field :extension, as: :text 27 | 28 | sidebar do 29 | field :address, as: :text 30 | field :region, as: :text 31 | field :postal_code, as: :text 32 | field :birth_date, as: :date 33 | field :notes, as: :textarea 34 | end 35 | 36 | field :orders, as: :has_many 37 | field :employees, as: :has_many 38 | end 39 | -------------------------------------------------------------------------------- /app/avo/resources/order_resource.rb: -------------------------------------------------------------------------------- 1 | class OrderResource < Avo::BaseResource 2 | self.title = :id 3 | 4 | field :id, as: :id 5 | field :customer, as: :has_one 6 | field :employee, as: :belongs_to 7 | 8 | with_options as: :date, sortable: true do 9 | heading "Dates" 10 | field :order_date 11 | field :required_date 12 | field :shipped_date 13 | end 14 | 15 | field :ship_location, as: :text, only_on: :index do |order| 16 | "#{order.ship_city}, #{order.ship_country}" 17 | end 18 | 19 | with_options as: :text, hide_on: :index do 20 | heading "Address" 21 | field :ship_city, as: :text 22 | field :ship_country, as: :text 23 | field :ship_region, as: :text 24 | field :ship_address, as: :text 25 | field :ship_postal_code, as: :text 26 | end 27 | 28 | sidebar do 29 | heading "Shipping" 30 | field :ship_name, as: :text 31 | field :freight, as: :number 32 | field :ship_via_id, as: :number 33 | field :customer_code, as: :text 34 | end 35 | 36 | field :order_details, as: :has_many 37 | 38 | action ExportCsv 39 | end 40 | -------------------------------------------------------------------------------- /bin/setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require "fileutils" 3 | 4 | # path to your application root. 5 | APP_ROOT = File.expand_path("..", __dir__) 6 | 7 | def system!(*args) 8 | system(*args) || abort("\n== Command #{args} failed ==") 9 | end 10 | 11 | FileUtils.chdir APP_ROOT do 12 | # This script is a way to set up or update your development environment automatically. 13 | # This script is idempotent, so that you can run it at any time and get an expectable outcome. 14 | # Add necessary setup steps to this file. 15 | 16 | puts "== Installing dependencies ==" 17 | system! "gem install bundler --conservative" 18 | system("bundle check") || system!("bundle install") 19 | 20 | # puts "\n== Copying sample files ==" 21 | # unless File.exist?("config/database.yml") 22 | # FileUtils.cp "config/database.yml.sample", "config/database.yml" 23 | # end 24 | 25 | puts "\n== Preparing database ==" 26 | system! "bin/rails db:prepare" 27 | 28 | puts "\n== Removing old logs and tempfiles ==" 29 | system! "bin/rails log:clear tmp:clear" 30 | 31 | puts "\n== Restarting application server ==" 32 | system! "bin/rails restart" 33 | end 34 | -------------------------------------------------------------------------------- /config/initializers/content_security_policy.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Define an application-wide content security policy. 4 | # See the Securing Rails Applications Guide for more information: 5 | # https://guides.rubyonrails.org/security.html#content-security-policy-header 6 | 7 | # Rails.application.configure do 8 | # config.content_security_policy do |policy| 9 | # policy.default_src :self, :https 10 | # policy.font_src :self, :https, :data 11 | # policy.img_src :self, :https, :data 12 | # policy.object_src :none 13 | # policy.script_src :self, :https 14 | # policy.style_src :self, :https 15 | # # Specify URI for violation reports 16 | # # policy.report_uri "/csp-violation-report-endpoint" 17 | # end 18 | # 19 | # # Generate session nonces for permitted importmap and inline scripts 20 | # config.content_security_policy_nonce_generator = ->(request) { request.session.id.to_s } 21 | # config.content_security_policy_nonce_directives = %w(script-src) 22 | # 23 | # # Report violations without enforcing the policy. 24 | # # config.content_security_policy_report_only = true 25 | # end 26 | -------------------------------------------------------------------------------- /config/initializers/rails_admin.rb: -------------------------------------------------------------------------------- 1 | RailsAdmin.config do |config| 2 | config.asset_source = :sprockets 3 | 4 | ### Popular gems integration 5 | 6 | ## == Devise == 7 | # config.authenticate_with do 8 | # warden.authenticate! scope: :user 9 | # end 10 | # config.current_user_method(&:current_user) 11 | 12 | ## == CancanCan == 13 | # config.authorize_with :cancancan 14 | 15 | ## == Pundit == 16 | # config.authorize_with :pundit 17 | 18 | ## == PaperTrail == 19 | # config.audit_with :paper_trail, 'User', 'PaperTrail::Version' # PaperTrail >= 3.0.0 20 | 21 | ### More at https://github.com/railsadminteam/rails_admin/wiki/Base-configuration 22 | 23 | ## == Gravatar integration == 24 | ## To disable Gravatar integration in Navigation Bar set to false 25 | # config.show_gravatar = true 26 | 27 | config.actions do 28 | dashboard # mandatory 29 | index # mandatory 30 | new 31 | export 32 | bulk_delete 33 | show 34 | edit 35 | delete 36 | show_in_app 37 | 38 | ## With an audit adapter, you can add: 39 | # history_index 40 | # history_show 41 | end 42 | end if Object.const_defined?('RailsAdmin') 43 | -------------------------------------------------------------------------------- /app/avo/actions/export_csv.rb: -------------------------------------------------------------------------------- 1 | class ExportCsv < Avo::BaseAction 2 | self.name = "Export CSV" 3 | self.may_download_file = true 4 | 5 | field :id, as: :boolean 6 | field :order_date, as: :boolean 7 | field :required_date, as: :boolean 8 | field :shipped_date, as: :boolean 9 | field :ship_city, as: :boolean 10 | field :ship_country, as: :boolean 11 | field :ship_region, as: :boolean 12 | field :ship_address, as: :boolean 13 | field :ship_postal_code, as: :boolean 14 | field :ship_name, as: :boolean 15 | field :freight, as: :boolean 16 | field :ship_via_id, as: :boolean 17 | field :customer_code, as: :boolean 18 | 19 | def handle(models:, resource:, fields:, **) 20 | columns = get_columns_from_fields(fields) 21 | 22 | return error "No record selected" if models.blank? 23 | 24 | file = CSV.generate(headers: true) do |csv| 25 | csv << columns 26 | 27 | models.each do |record| 28 | csv << columns.map do |attr| 29 | record.send(attr) 30 | end 31 | end 32 | end 33 | 34 | download file, "#{resource.plural_name}.csv" 35 | end 36 | 37 | def get_columns_from_fields(fields) 38 | fields.select { |key, value| value }.keys 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /app/avo/resources/product_resource.rb: -------------------------------------------------------------------------------- 1 | class ProductResource < Avo::BaseResource 2 | self.title = :product_name 3 | self.includes = [:category, :order_details] 4 | self.description = "Product picture is a random image from https://picsum.photos/ just for the exmaple. Change to grid view to see the cover image." 5 | self.search_query = -> do 6 | scope.ransack(product_name_cont: params[:q], m: "or").result(distinct: false) 7 | end 8 | 9 | field :id, as: :id 10 | field :product_name, as: :text 11 | field :category, as: :belongs_to 12 | field :unit_price, as: :number 13 | field :discontinued, as: :boolean 14 | field :units_in_stock, as: :number 15 | field :units_on_order, as: :number 16 | field :reorder_level, as: :number 17 | field :quantity_per_unit, as: :text 18 | field :supplier_id, as: :number 19 | field :order_details, as: :has_many 20 | 21 | grid do 22 | cover :cover_photo, as: :external_image do |category| 23 | "https://picsum.photos/200" 24 | rescue 25 | nil 26 | end 27 | title :product_name, as: :text, required: true, link_to_resource: true 28 | body :description, as: :text do |product| 29 | "UnitPrice: #{product.unit_price}, Stock: #{product.units_in_stock}" 30 | end 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /app/avo/resources/customer_resource.rb: -------------------------------------------------------------------------------- 1 | class CustomerResource < Avo::BaseResource 2 | self.title = :company_name 3 | self.includes = [] 4 | self.search_query = -> do 5 | scope.ransack(company_name_cont: params[:q], m: "or").result(distinct: false) 6 | end 7 | 8 | field :id, as: :id 9 | field :company_code, as: :badge 10 | 11 | with_options as: :text do 12 | field :company_name 13 | field :city 14 | 15 | with_options as: :text, only_on: :index do 16 | field :country 17 | field :contact_name do |customer| 18 | "#{customer.contact_name} (#{customer.contact_title})" 19 | end 20 | field :phone 21 | end 22 | end 23 | 24 | 25 | heading "Address" 26 | with_options as: :text, hide_on: :index do 27 | field :address 28 | field :region 29 | field :postal_code 30 | field :country 31 | end 32 | 33 | sidebar do 34 | heading "Contact" 35 | field :contact_name, as: :text 36 | field :contact_title, as: :text 37 | 38 | field :phone, as: :text 39 | field :fax, as: :text 40 | end 41 | 42 | field :orders, as: :has_many 43 | 44 | field :search_result, as: :text, as_description: true, hide_on: :all do |customer| 45 | "#{customer.company_code} (#{customer.city})" 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /config/storage.yml: -------------------------------------------------------------------------------- 1 | test: 2 | service: Disk 3 | root: <%= Rails.root.join("tmp/storage") %> 4 | 5 | local: 6 | service: Disk 7 | root: <%= Rails.root.join("storage") %> 8 | 9 | # Use bin/rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key) 10 | # amazon: 11 | # service: S3 12 | # access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %> 13 | # secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %> 14 | # region: us-east-1 15 | # bucket: your_own_bucket-<%= Rails.env %> 16 | 17 | # Remember not to checkin your GCS keyfile to a repository 18 | # google: 19 | # service: GCS 20 | # project: your_project 21 | # credentials: <%= Rails.root.join("path/to/gcs.keyfile") %> 22 | # bucket: your_own_bucket-<%= Rails.env %> 23 | 24 | # Use bin/rails credentials:edit to set the Azure Storage secret (as azure_storage:storage_access_key) 25 | # microsoft: 26 | # service: AzureStorage 27 | # storage_account_name: your_account_name 28 | # storage_access_key: <%= Rails.application.credentials.dig(:azure_storage, :storage_access_key) %> 29 | # container: your_container_name-<%= Rails.env %> 30 | 31 | # mirror: 32 | # service: Mirror 33 | # primary: local 34 | # mirrors: [ amazon, google, microsoft ] 35 | -------------------------------------------------------------------------------- /config/routes.rb: -------------------------------------------------------------------------------- 1 | Rails.application.routes.draw do 2 | # Various Administrative Panels 3 | # (ordered alphabetically) 4 | 5 | # ActiveAdmin 6 | ActiveAdmin.routes(self) if Object.const_defined?('ActiveAdmin') 7 | 8 | # (ThoughtBot's Administrate is not yet included. It behaves more like a scaffolding 9 | # engine than any of the others, and would require a little different approach to 10 | # integrate.) 11 | 12 | # Avo 13 | mount Avo::Engine, at: Avo.configuration.root_path if Object.const_defined?('Avo') 14 | 15 | # Brick 16 | # Thie one adds routes on its own during Rails' #finalize! process. 17 | 18 | # Forest Admin 19 | mount ForestLiana::Engine => '/forest' if Object.const_defined?('ForestLiana') 20 | 21 | # Motor Admin 22 | mount Motor::Admin => '/motor' if Object.const_defined?('Motor') 23 | 24 | # RailsAdmin 25 | mount RailsAdmin::Engine => '/ra', as: 'rails_admin' if Object.const_defined?('RailsAdmin') 26 | 27 | mount Spina::Engine => '/spina' if Object.const_defined?('Spina') 28 | 29 | # Trestle 30 | # By default its Rails Engine is auto-mounted into a path defined in the trestle.rb initializer file. 31 | 32 | # ================================== 33 | 34 | # API documentation 35 | mount Rswag::Ui::Engine => '/api-docs' if Object.const_defined?('Rswag') 36 | end 37 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | max_threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 } 8 | min_threads_count = ENV.fetch("RAILS_MIN_THREADS") { max_threads_count } 9 | threads min_threads_count, max_threads_count 10 | 11 | # Specifies the `worker_timeout` threshold that Puma will use to wait before 12 | # terminating a worker in development environments. 13 | # 14 | worker_timeout 3600 if ENV.fetch("RAILS_ENV", "development") == "development" 15 | 16 | # Specifies the `port` that Puma will listen on to receive requests; default is 3000. 17 | # 18 | port ENV.fetch("PORT") { 3000 } 19 | 20 | # Specifies the `environment` that Puma will run in. 21 | # 22 | environment ENV.fetch("RAILS_ENV") { "development" } 23 | 24 | # Specifies the `pidfile` that Puma will use. 25 | pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" } 26 | 27 | # Specifies the number of `workers` to boot in clustered mode. 28 | # Workers are forked web server processes. If using threads and workers together 29 | # the concurrency of the application would be max `threads` * `workers`. 30 | # Workers do not work on JRuby or Windows (both of which do not support 31 | # processes). 32 | # 33 | # workers ENV.fetch("WEB_CONCURRENCY") { 2 } 34 | 35 | # Use the `preload_app!` method when specifying a `workers` number. 36 | # This directive tells Puma to first boot the application and load code 37 | # before forking the application. This takes advantage of Copy On Write 38 | # process behavior so workers use less memory. 39 | # 40 | # preload_app! 41 | 42 | # Allow puma to be restarted by `bin/rails restart` command. 43 | plugin :tmp_restart 44 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Compare Admin Panels! 2 | 3 | An analysis of six popular admin panel gems for use with Ruby on Rails: 4 | 5 | ## Active Admin 6 | * The "original" admin panel -- still widely used for new projects today 7 | * Ruby-centric markup design using Arbre 8 | * Has CSV, XML, and JSON export 9 | 10 | https://activeadmin.info/ 11 | 12 | ## Avo 13 | * Attractive interface using the newest front-end technology 14 | * Paid option adds dashboards / menu editing / inline editing 15 | * Built by Adrian Marin 16 | 17 | https://avohq.io/ 18 | 19 | ## Forest 20 | * Semi-Saas where you keep the database, and the Forest servers only know the tables, columns, and associations. Data is delivered by an agent to the forest servers which render pages. 21 | * Paid option adds visualisation / charting / workflow enhancements 22 | * Lots of traction, having secured significant funding 23 | 24 | https://www.forestadmin.com/ 25 | 26 | ## Motor Admin 27 | * Very lean 28 | * Has GUI Form Builder / CSV export 29 | * Configuration all done in database tables instead of an initializer file 30 | * Paid option available 31 | * Built by Pete Matsyburka 32 | 33 | https://www.getmotoradmin.com/ruby-on-rails 34 | 35 | ## Rails Admin 36 | * The "original" sexier alternative admin panel 37 | * Has CSV export 38 | * Built by a very dedicated soul -- Mitsuhiro Shibuya 39 | 40 | https://github.com/railsadminteam/rails_admin 41 | 42 | ## Trestle 43 | * Automatically adds routes without having to modify routes.rb 44 | * Offers a Ruby-centric DSL via a well thought out set of helpers 45 | * Pretty lean 46 | * Built by Sam Pohlenz 47 | 48 | https://trestle.io/ 49 | 50 | --- 51 | 52 | Also considering adding ThoughtBot's [Administrate](https://github.com/thoughtbot/administrate) and 53 | Chris Oliver's [madmin](https://github.com/excid3/madmin). 54 | 55 | ### Troubleshooting 56 | 57 | If you get: 58 | ``` 59 | The asset "active_admin.css" is not present in the asset pipeline. 60 | ``` 61 | then do this: 62 | ``` 63 | bin/rails g active_admin:assets 64 | ``` 65 | (But it really should already be there.) 66 | -------------------------------------------------------------------------------- /config/environments/test.rb: -------------------------------------------------------------------------------- 1 | require "active_support/core_ext/integer/time" 2 | 3 | # The test environment is used exclusively to run your application's 4 | # test suite. You never need to work with it otherwise. Remember that 5 | # your test database is "scratch space" for the test suite and is wiped 6 | # and recreated between test runs. Don't rely on the data there! 7 | 8 | Rails.application.configure do 9 | # Settings specified here will take precedence over those in config/application.rb. 10 | 11 | # Turn false under Spring and add config.action_view.cache_template_loading = true. 12 | config.cache_classes = true 13 | 14 | # Eager loading loads your whole application. When running a single test locally, 15 | # this probably isn't necessary. It's a good idea to do in a continuous integration 16 | # system, or in some way before deploying your code. 17 | config.eager_load = ENV["CI"].present? 18 | 19 | # Configure public file server for tests with Cache-Control for performance. 20 | config.public_file_server.enabled = true 21 | config.public_file_server.headers = { 22 | "Cache-Control" => "public, max-age=#{1.hour.to_i}" 23 | } 24 | 25 | # Show full error reports and disable caching. 26 | config.consider_all_requests_local = true 27 | config.action_controller.perform_caching = false 28 | config.cache_store = :null_store 29 | 30 | # Raise exceptions instead of rendering exception templates. 31 | config.action_dispatch.show_exceptions = false 32 | 33 | # Disable request forgery protection in test environment. 34 | config.action_controller.allow_forgery_protection = false 35 | 36 | # Store uploaded files on the local file system in a temporary directory. 37 | config.active_storage.service = :test 38 | 39 | config.action_mailer.perform_caching = false 40 | 41 | # Tell Action Mailer not to deliver emails to the real world. 42 | # The :test delivery method accumulates sent emails in the 43 | # ActionMailer::Base.deliveries array. 44 | config.action_mailer.delivery_method = :test 45 | 46 | # Print deprecation notices to the stderr. 47 | config.active_support.deprecation = :stderr 48 | 49 | # Raise exceptions for disallowed deprecations. 50 | config.active_support.disallowed_deprecation = :raise 51 | 52 | # Tell Active Support which deprecation messages to disallow. 53 | config.active_support.disallowed_deprecation_warnings = [] 54 | 55 | # Raises error for missing translations. 56 | # config.i18n.raise_on_missing_translations = true 57 | 58 | # Annotate rendered view with file names. 59 | # config.action_view.annotate_rendered_view_with_filenames = true 60 | end 61 | -------------------------------------------------------------------------------- /config/environments/development.rb: -------------------------------------------------------------------------------- 1 | require "active_support/core_ext/integer/time" 2 | 3 | Rails.application.configure do 4 | # Settings specified here will take precedence over those in config/application.rb. 5 | 6 | # In the development environment your application's code is reloaded any time 7 | # it changes. This slows down response time but is perfect for development 8 | # since you don't have to restart the web server when you make code changes. 9 | config.cache_classes = false 10 | 11 | # Do not eager load code on boot. 12 | config.eager_load = false 13 | 14 | # Show full error reports. 15 | config.consider_all_requests_local = true 16 | 17 | # Enable server timing 18 | config.server_timing = true 19 | 20 | # Enable/disable caching. By default caching is disabled. 21 | # Run rails dev:cache to toggle caching. 22 | if Rails.root.join("tmp/caching-dev.txt").exist? 23 | config.action_controller.perform_caching = true 24 | config.action_controller.enable_fragment_cache_logging = true 25 | 26 | config.cache_store = :memory_store 27 | config.public_file_server.headers = { 28 | "Cache-Control" => "public, max-age=#{2.days.to_i}" 29 | } 30 | else 31 | config.action_controller.perform_caching = false 32 | 33 | config.cache_store = :null_store 34 | end 35 | 36 | # Store uploaded files on the local file system (see config/storage.yml for options). 37 | config.active_storage.service = :local 38 | 39 | # Don't care if the mailer can't send. 40 | config.action_mailer.raise_delivery_errors = false 41 | 42 | config.action_mailer.perform_caching = false 43 | 44 | # Print deprecation notices to the Rails logger. 45 | config.active_support.deprecation = :log 46 | 47 | # Raise exceptions for disallowed deprecations. 48 | config.active_support.disallowed_deprecation = :raise 49 | 50 | # Tell Active Support which deprecation messages to disallow. 51 | config.active_support.disallowed_deprecation_warnings = [] 52 | 53 | # Raise an error on page load if there are pending migrations. 54 | config.active_record.migration_error = :page_load 55 | 56 | # Highlight code that triggered database queries in logs. 57 | config.active_record.verbose_query_logs = true 58 | 59 | # Suppress logger output for asset requests. 60 | config.assets.quiet = true 61 | 62 | # Raises error for missing translations. 63 | # config.i18n.raise_on_missing_translations = true 64 | 65 | # Annotate rendered view with file names. 66 | # config.action_view.annotate_rendered_view_with_filenames = true 67 | 68 | # Uncomment if you wish to allow Action Cable access from any origin. 69 | # config.action_cable.disable_request_forgery_protection = true 70 | end 71 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | git_source(:github) { |repo| "https://github.com/#{repo}.git" } 3 | 4 | ruby "3.2.0" 5 | 6 | # Bundle edge Rails instead: gem "rails", github: "rails/rails", branch: "main" 7 | gem "rails", "~> 7.0.4", ">= 7.0.4.2" 8 | 9 | # The original asset pipeline for Rails [https://github.com/rails/sprockets-rails] 10 | gem "sprockets-rails" 11 | 12 | # Use postgresql as the database for Active Record 13 | gem "pg", "~> 1.1" 14 | 15 | gem 'brick' # Auto-creates models and compatibility layers for various admin gems 16 | gem 'composite_primary_keys' # Useful for sakila or adventureworks sample databases 17 | gem 'rgeo' # Support geospatial data types 18 | gem 'rswag-ui' # Support OpenAPI 3.0 documentation 19 | 20 | # Administrative panel gems 21 | gem 'activeadmin' 22 | # gem 'administrate' 23 | gem 'avo' 24 | gem 'forest_liana', '~> 7' 25 | gem 'motor-admin' 26 | gem 'rails_admin' 27 | gem 'spina' 28 | gem 'trestle' 29 | 30 | # For Avo 31 | gem 'ransack' 32 | 33 | # Use Sass to process CSS 34 | gem 'sassc' 35 | # gem "sassc-rails" # For ActiveAdmin, Rails Admin and Trestle (which really only requires sassc) 36 | gem 'country-select' 37 | 38 | gem 'duty_free' # For importing sample data during: bin/rails db:seed 39 | 40 | # Use the Puma web server [https://github.com/puma/puma] 41 | gem "puma", "~> 5.0" 42 | 43 | # Use JavaScript with ESM import maps [https://github.com/rails/importmap-rails] 44 | gem "importmap-rails" 45 | 46 | # Hotwire's SPA-like page accelerator [https://turbo.hotwired.dev] 47 | gem "turbo-rails" 48 | 49 | # Hotwire's modest JavaScript framework [https://stimulus.hotwired.dev] 50 | gem "stimulus-rails" 51 | 52 | # Build JSON APIs with ease [https://github.com/rails/jbuilder] 53 | gem "jbuilder" 54 | 55 | # Use Redis adapter to run Action Cable in production 56 | # gem "redis", "~> 4.0" 57 | 58 | # Use Kredis to get higher-level data types in Redis [https://github.com/rails/kredis] 59 | # gem "kredis" 60 | 61 | # Use Active Model has_secure_password [https://guides.rubyonrails.org/active_model_basics.html#securepassword] 62 | # gem "bcrypt", "~> 3.1.7" 63 | 64 | # Windows does not include zoneinfo files, so bundle the tzinfo-data gem 65 | gem "tzinfo-data", platforms: %i[ mingw mswin x64_mingw jruby ] 66 | 67 | # Reduces boot times through caching; required in config/boot.rb 68 | gem "bootsnap", require: false 69 | 70 | # Use Active Storage variants [https://guides.rubyonrails.org/active_storage_overview.html#transforming-images] 71 | # gem "image_processing", "~> 1.2" 72 | 73 | group :development, :test do 74 | # See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem 75 | # gem "debug", platforms: %i[ mri mingw x64_mingw ] 76 | gem "pry-byebug" 77 | end 78 | 79 | group :development do 80 | # Use console on exceptions pages [https://github.com/rails/web-console] 81 | gem "web-console" 82 | 83 | # Add speed badges [https://github.com/MiniProfiler/rack-mini-profiler] 84 | # gem "rack-mini-profiler" 85 | 86 | # Speed up commands on slow machines / big apps [https://github.com/rails/spring] 87 | # gem "spring" 88 | end 89 | 90 | group :test do 91 | # Use system testing [https://guides.rubyonrails.org/testing.html#system-testing] 92 | gem "capybara" 93 | gem "selenium-webdriver" 94 | gem "webdrivers" 95 | end 96 | -------------------------------------------------------------------------------- /config/database.yml: -------------------------------------------------------------------------------- 1 | # PostgreSQL. Versions 9.3 and up are supported. 2 | # 3 | # Install the pg driver: 4 | # gem install pg 5 | # On macOS with Homebrew: 6 | # gem install pg -- --with-pg-config=/usr/local/bin/pg_config 7 | # On macOS with MacPorts: 8 | # gem install pg -- --with-pg-config=/opt/local/lib/postgresql84/bin/pg_config 9 | # On Windows: 10 | # gem install pg 11 | # Choose the win32 build. 12 | # Install PostgreSQL and put its /bin directory on your path. 13 | # 14 | # Configure Using Gemfile 15 | # gem "pg" 16 | # 17 | default: &default 18 | adapter: postgresql 19 | encoding: unicode 20 | # For details on connection pooling, see Rails configuration guide 21 | # https://guides.rubyonrails.org/configuring.html#database-pooling 22 | pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> 23 | 24 | development: 25 | <<: *default 26 | database: northwind 27 | 28 | # The specified database role being used to connect to postgres. 29 | # To create additional roles in postgres see `$ createuser --help`. 30 | # When left blank, postgres will use the default role. This is 31 | # the same name as the operating system user running Rails. 32 | #username: admin_panel_comparison 33 | 34 | # The password associated with the postgres role (username). 35 | #password: 36 | 37 | # Connect on a TCP socket. Omitted by default since the client uses a 38 | # domain socket that doesn't need configuration. Windows does not have 39 | # domain sockets, so uncomment these lines. 40 | #host: localhost 41 | 42 | # The TCP port the server listens on. Defaults to 5432. 43 | # If your server runs on a different port number, change accordingly. 44 | #port: 5432 45 | 46 | # Schema search path. The server defaults to $user,public 47 | #schema_search_path: myapp,sharedapp,public 48 | 49 | # Minimum log levels, in increasing order: 50 | # debug5, debug4, debug3, debug2, debug1, 51 | # log, notice, warning, error, fatal, and panic 52 | # Defaults to warning. 53 | #min_messages: notice 54 | 55 | # Warning: The database defined as "test" will be erased and 56 | # re-generated from your development database when you run "rake". 57 | # Do not set this db to the same as development or production. 58 | test: 59 | <<: *default 60 | database: admin_panel_comparison_test 61 | 62 | # As with config/credentials.yml, you never want to store sensitive information, 63 | # like your database password, in your source code. If your source code is 64 | # ever seen by anyone, they now have access to your database. 65 | # 66 | # Instead, provide the password or a full connection URL as an environment 67 | # variable when you boot the app. For example: 68 | # 69 | # DATABASE_URL="postgres://myuser:mypass@localhost/somedatabase" 70 | # 71 | # If the connection URL is provided in the special DATABASE_URL environment 72 | # variable, Rails will automatically merge its configuration values on top of 73 | # the values provided in this file. Alternatively, you can specify a connection 74 | # URL environment variable explicitly: 75 | # 76 | # production: 77 | # url: <%= ENV["MY_APP_DATABASE_URL"] %> 78 | # 79 | # Read https://guides.rubyonrails.org/configuring.html#configuring-a-database 80 | # for a full overview on how database connection configuration can be specified. 81 | # 82 | production: 83 | <<: *default 84 | database: admin_panel_comparison_production 85 | username: admin_panel_comparison 86 | password: <%= ENV["ADMIN_PANEL_COMPARISON_DATABASE_PASSWORD"] %> 87 | -------------------------------------------------------------------------------- /config/environments/production.rb: -------------------------------------------------------------------------------- 1 | require "active_support/core_ext/integer/time" 2 | 3 | Rails.application.configure do 4 | # Settings specified here will take precedence over those in config/application.rb. 5 | 6 | # Code is not reloaded between requests. 7 | config.cache_classes = true 8 | 9 | # Eager load code on boot. This eager loads most of Rails and 10 | # your application in memory, allowing both threaded web servers 11 | # and those relying on copy on write to perform better. 12 | # Rake tasks automatically ignore this option for performance. 13 | config.eager_load = true 14 | 15 | # Full error reports are disabled and caching is turned on. 16 | config.consider_all_requests_local = false 17 | config.action_controller.perform_caching = true 18 | 19 | # Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"] 20 | # or in config/master.key. This key is used to decrypt credentials (and other encrypted files). 21 | # config.require_master_key = true 22 | 23 | # Disable serving static files from the `/public` folder by default since 24 | # Apache or NGINX already handles this. 25 | config.public_file_server.enabled = ENV["RAILS_SERVE_STATIC_FILES"].present? 26 | 27 | # Compress CSS using a preprocessor. 28 | # config.assets.css_compressor = :sass 29 | 30 | # Do not fallback to assets pipeline if a precompiled asset is missed. 31 | config.assets.compile = false 32 | 33 | # Enable serving of images, stylesheets, and JavaScripts from an asset server. 34 | # config.asset_host = "http://assets.example.com" 35 | 36 | # Specifies the header that your server uses for sending files. 37 | # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for Apache 38 | # config.action_dispatch.x_sendfile_header = "X-Accel-Redirect" # for NGINX 39 | 40 | # Store uploaded files on the local file system (see config/storage.yml for options). 41 | config.active_storage.service = :local 42 | 43 | # Mount Action Cable outside main process or domain. 44 | # config.action_cable.mount_path = nil 45 | # config.action_cable.url = "wss://example.com/cable" 46 | # config.action_cable.allowed_request_origins = [ "http://example.com", /http:\/\/example.*/ ] 47 | 48 | # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. 49 | # config.force_ssl = true 50 | 51 | # Include generic and useful information about system operation, but avoid logging too much 52 | # information to avoid inadvertent exposure of personally identifiable information (PII). 53 | config.log_level = :info 54 | 55 | # Prepend all log lines with the following tags. 56 | config.log_tags = [ :request_id ] 57 | 58 | # Use a different cache store in production. 59 | # config.cache_store = :mem_cache_store 60 | 61 | # Use a real queuing backend for Active Job (and separate queues per environment). 62 | # config.active_job.queue_adapter = :resque 63 | # config.active_job.queue_name_prefix = "admin_panel_comparison_production" 64 | 65 | config.action_mailer.perform_caching = false 66 | 67 | # Ignore bad email addresses and do not raise email delivery errors. 68 | # Set this to true and configure the email server for immediate delivery to raise delivery errors. 69 | # config.action_mailer.raise_delivery_errors = false 70 | 71 | # Enable locale fallbacks for I18n (makes lookups for any locale fall back to 72 | # the I18n.default_locale when a translation cannot be found). 73 | config.i18n.fallbacks = true 74 | 75 | # Don't log any deprecations. 76 | config.active_support.report_deprecations = false 77 | 78 | # Use default logging formatter so that PID and timestamp are not suppressed. 79 | config.log_formatter = ::Logger::Formatter.new 80 | 81 | # Use a different logger for distributed setups. 82 | # require "syslog/logger" 83 | # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new "app-name") 84 | 85 | if ENV["RAILS_LOG_TO_STDOUT"].present? 86 | logger = ActiveSupport::Logger.new(STDOUT) 87 | logger.formatter = config.log_formatter 88 | config.logger = ActiveSupport::TaggedLogging.new(logger) 89 | end 90 | 91 | # Do not dump schema after migrations. 92 | config.active_record.dump_schema_after_migration = false 93 | end 94 | -------------------------------------------------------------------------------- /config/locales/avo.nn.yml: -------------------------------------------------------------------------------- 1 | --- 2 | nn: 3 | avo: 4 | action_ran_successfully: Suksess! 5 | actions: Handlingar 6 | and_x_other_resources: og %{count} andre ressursar 7 | are_you_sure: Er du sikker? 8 | are_you_sure_detach_item: Er du sikker på at du vil koble frå %{item}. 9 | are_you_sure_you_want_to_run_this_option: Er du sikker? 10 | attach: Legg til 11 | attach_and_attach_another: Legg til & Legg til ny 12 | attach_item: Legg til %{item} 13 | attachment_class_attached: "%{attachment_class} lagt til." 14 | attachment_class_detached: "%{attachment_class} fjerna." 15 | attachment_destroyed: Vedlegg sletta 16 | cancel: Avbryt 17 | choose_a_country: Vel eit land 18 | choose_an_option: Vel eit alternativ 19 | choose_item: Vel %{item} 20 | clear_value: Nullstill verdi 21 | click_to_reveal_filters: Vis filter 22 | confirm: Stadfest 23 | create_new_item: Lag ny %{item} 24 | dashboard: Dashboard 25 | dashboards: Dashboards 26 | delete: slett 27 | delete_file: Slett fil 28 | delete_item: Slett %{item} 29 | detach_item: koble frå %{item} 30 | details: detaljar 31 | download: Last ned 32 | download_file: Last ned fil 33 | download_item: Last ned %{item} 34 | edit: endre 35 | edit_item: endre %{item} 36 | empty_dashboard_message: Legg til kort i dette dashbordet 37 | failed: Feila 38 | failed_to_find_attachment: Fann ikkje vedlegg 39 | failed_to_load: Lasting feila 40 | field_translations: 41 | file: 42 | one: fil 43 | other: filer 44 | zero: filer 45 | people: 46 | one: person 47 | other: personar 48 | zero: personar 49 | filter_by: Filtrer etter 50 | filters: Filter 51 | go_back: Gå tilbake 52 | grid_view: Gridvisning 53 | hide_content: Skjul innhald 54 | home: Heim 55 | key_value_field: 56 | add_row: Legg til rad 57 | delete_row: Slett rad 58 | key: Nøkkel 59 | value: Verdi 60 | list_is_empty: Lista er tom 61 | loading: Lastar 62 | more: Meir 63 | new: ny 64 | next_page: Neste side 65 | no_cards_present: Ingen kort til stades 66 | no_item_found: Fann ingen 67 | no_options_available: Ingen tilgjengelege alternativ 68 | no_related_item_found: Fann ingen relaterte 69 | not_authorized: Du er ikkje autorisert til å gjere denne handlinga. 70 | number_of_items: 71 | one: en %{item} 72 | other: "%{count} %{item}" 73 | zero: ingen %{item} 74 | oops_nothing_found: Oops! Fann ikkje noko... 75 | order: 76 | higher: Flytt elementet opp 77 | lower: Flytt elementet ned 78 | reorder_record: Sorter element 79 | to_bottom: Flytt elementet til botnen 80 | to_top: Flytt elementet til toppen 81 | per_page: Per side 82 | prev_page: Førre side 83 | remove_selection: Fjern val 84 | reset_filters: Nullstill filter 85 | resource_created: Ressurs generert 86 | resource_destroyed: Ressurs sletta 87 | resource_translations: 88 | user: 89 | one: brukar 90 | other: brukarar 91 | zero: brukarar 92 | resource_updated: Ressurs oppdatert 93 | resources: Ressursar 94 | run: Køyr 95 | save: Lagre 96 | search: 97 | cancel_button: Avbryt 98 | placeholder: Søk 99 | select_all: Vel alle 100 | select_all_matching: Vel alle samsvarende 101 | select_item: Vel 102 | show_content: Vis innhald 103 | sign_out: Logg ut 104 | switch_to_view: Bytt til %{view_type} vis 105 | table_view: Tabellvisning 106 | tools: Reiskapane 107 | type_to_search: Søk. 108 | unauthorized: Ikkje autorisert 109 | undo: angre 110 | view: Vis 111 | view_item: vis %{item} 112 | was_successfully_created: vart oppretta 113 | was_successfully_updated: vart oppdatert 114 | x_items_more: 115 | one: eitt element til 116 | other: "%{count} fleire element" 117 | zero: ingen fleire element 118 | x_records_selected_from_a_total_of_x_html: %{selected} valde postar på denne sida av totalt %{count} 119 | x_records_selected_from_all_pages_html: %{count} valde postar frå alle sider 120 | you_missed_something_check_form: Her manglar du noko. Ver venleg og sjekk skjemaet. 121 | -------------------------------------------------------------------------------- /config/locales/avo.nb.yml: -------------------------------------------------------------------------------- 1 | --- 2 | nb: 3 | avo: 4 | action_ran_successfully: Suksess! 5 | actions: Handlinger 6 | and_x_other_resources: og %{count} andre ressurser 7 | are_you_sure: Er du sikker? 8 | are_you_sure_detach_item: Er du sikker på at du vil koble fra %{item}. 9 | are_you_sure_you_want_to_run_this_option: Er du sikker? 10 | attach: Legg til 11 | attach_and_attach_another: Legg til & Legg til ny 12 | attach_item: Legg til %{item} 13 | attachment_class_attached: "%{attachment_class} lagt til." 14 | attachment_class_detached: "%{attachment_class} fjernet." 15 | attachment_destroyed: Vedlett slettet 16 | cancel: Avbryt 17 | choose_a_country: Velg et land 18 | choose_an_option: Velg et alternativ 19 | choose_item: Velge %{item} 20 | clear_value: Nullstill verdi 21 | click_to_reveal_filters: Vis filter 22 | confirm: Bekreft 23 | create_new_item: Lag ny %{item} 24 | dashboard: Dashboard 25 | dashboards: Dashboards 26 | delete: slett 27 | delete_file: Slett fil 28 | delete_item: Slett %{item} 29 | detach_item: koble fra %{item} 30 | details: detaljer 31 | download: Last ned 32 | download_file: Last ned fil 33 | download_item: Last ned %{item} 34 | edit: endre 35 | edit_item: endre %{item} 36 | empty_dashboard_message: Legg til kort i dette dashbordet 37 | failed: Feilet 38 | failed_to_find_attachment: Fant ikke vedlegg 39 | failed_to_load: Lasting feilet 40 | field_translations: 41 | file: 42 | one: fil 43 | other: filer 44 | zero: filer 45 | people: 46 | one: person 47 | other: personer 48 | zero: personer 49 | filter_by: Filtrer etter 50 | filters: Filter 51 | go_back: Gå tilbake 52 | grid_view: Grid visning 53 | hide_content: Skjul innhold 54 | home: Hjem 55 | key_value_field: 56 | add_row: Legg til rad 57 | delete_row: Slett rad 58 | key: Nøkkel 59 | value: Verdi 60 | list_is_empty: Listen er tom 61 | loading: Laster 62 | more: Mer 63 | new: ny 64 | next_page: Neste side 65 | no_cards_present: Ingen kort til stede 66 | no_item_found: Ingen funnet 67 | no_options_available: Ingen tilgjengelige alternativer 68 | no_related_item_found: Ingen relaterte funnet 69 | not_authorized: Du er ikke autorisert til å gjøre denne handlingen. 70 | number_of_items: 71 | one: en %{item} 72 | other: "%{count} %{item}" 73 | zero: ingen %{item} 74 | oops_nothing_found: Oops! Ingen ting funnet... 75 | order: 76 | higher: Flytt elementet høyere 77 | lower: Flytt elementet lavere 78 | reorder_record: Sorter elementer 79 | to_bottom: Flytt elementet til bunnen 80 | to_top: Flytt elementet til toppen 81 | per_page: Per side 82 | prev_page: Forrige side 83 | remove_selection: Fjern valg 84 | reset_filters: Nullstill filter 85 | resource_created: Ressurs generert 86 | resource_destroyed: Ressurs slettet 87 | resource_translations: 88 | user: 89 | one: bruker 90 | other: brukere 91 | zero: brukere 92 | resource_updated: Ressurs oppdatert 93 | resources: Ressurser 94 | run: Kjør 95 | save: Lagre 96 | search: 97 | cancel_button: Avbryt 98 | placeholder: Søk 99 | select_all: Velg alle 100 | select_all_matching: Velg alle samsvarende 101 | select_item: Velg 102 | show_content: Vis innhold 103 | sign_out: Logg ut 104 | switch_to_view: Bytt til %{view_type} vis 105 | table_view: Tabell visning 106 | tools: Redskapene 107 | type_to_search: Søk. 108 | unauthorized: Ikke autorisert 109 | undo: angre 110 | view: Vis 111 | view_item: vis %{item} 112 | was_successfully_created: ble opprettet 113 | was_successfully_updated: ble oppdatert 114 | x_items_more: 115 | one: ett element til 116 | other: "%{count} flere elementer" 117 | zero: ingen flere elementer 118 | x_records_selected_from_a_total_of_x_html: %{selected} poster valgt på denne siden fra totalt %{count} 119 | x_records_selected_from_all_pages_html: %{count} poster valgt fra alle sider 120 | you_missed_something_check_form: Her mangler du noe. Vennligst sjekk skjemaet. 121 | -------------------------------------------------------------------------------- /config/locales/avo.en.yml: -------------------------------------------------------------------------------- 1 | --- 2 | en: 3 | avo: 4 | action_ran_successfully: Action ran successfully! 5 | actions: Actions 6 | and_x_other_resources: and %{count} other resources 7 | are_you_sure: Are you sure? 8 | are_you_sure_detach_item: Are you sure you want to detach this %{item}. 9 | are_you_sure_you_want_to_run_this_option: Are you sure you want to run this action? 10 | attach: Attach 11 | attach_and_attach_another: Attach & Attach another 12 | attach_item: Attach %{item} 13 | attachment_class_attached: "%{attachment_class} attached." 14 | attachment_class_detached: "%{attachment_class} detached." 15 | attachment_destroyed: Attachment destroyed 16 | cancel: Cancel 17 | choose_a_country: Choose a country 18 | choose_an_option: Choose an option 19 | choose_item: Choose %{item} 20 | clear_value: Clear value 21 | click_to_reveal_filters: Click to reveal filters 22 | confirm: Confirm 23 | create_new_item: Create new %{item} 24 | dashboard: Dashboard 25 | dashboards: Dashboards 26 | delete: delete 27 | delete_file: Delete file 28 | delete_item: Delete %{item} 29 | detach_item: detach %{item} 30 | details: details 31 | download: Download 32 | download_file: Download file 33 | download_item: Download %{item} 34 | edit: edit 35 | edit_item: edit %{item} 36 | empty_dashboard_message: Add cards to this dashboard 37 | failed: Failed 38 | failed_to_find_attachment: Failed to find attachment 39 | failed_to_load: Failed to load 40 | field_translations: 41 | file: 42 | one: file 43 | other: files 44 | zero: files 45 | people: 46 | one: peep 47 | other: peeps 48 | zero: peeps 49 | filter_by: Filter by 50 | filters: Filters 51 | go_back: Go back 52 | grid_view: Grid view 53 | hide_content: Hide content 54 | home: Home 55 | key_value_field: 56 | add_row: Add row 57 | delete_row: Delete row 58 | key: Key 59 | value: Value 60 | list_is_empty: List is empty 61 | loading: Loading 62 | more: More 63 | new: new 64 | next_page: Next page 65 | no_cards_present: No cards present 66 | no_item_found: No record found 67 | no_options_available: No options available 68 | no_related_item_found: No related record found 69 | not_authorized: You are not authorized to perform this action. 70 | number_of_items: 71 | one: one %{item} 72 | other: "%{count} %{item}" 73 | zero: no %{item} 74 | oops_nothing_found: Oops! Nothing found... 75 | order: 76 | higher: Move record higher 77 | lower: Move record lower 78 | reorder_record: Reorder record 79 | to_bottom: Move record to bottom 80 | to_top: Move record to top 81 | per_page: Per page 82 | prev_page: Previous page 83 | remove_selection: Remove selection 84 | reset_filters: Reset filters 85 | resource_created: Record created 86 | resource_destroyed: Record destroyed 87 | resource_translations: 88 | user: 89 | one: user 90 | other: users 91 | zero: users 92 | resource_updated: Record updated 93 | resources: Resources 94 | run: Run 95 | save: Save 96 | search: 97 | cancel_button: Cancel 98 | placeholder: Search 99 | select_all: Select all 100 | select_all_matching: Select all matching 101 | select_item: Select item 102 | show_content: Show content 103 | sign_out: Sign out 104 | switch_to_view: Switch to %{view_type} view 105 | table_view: Table view 106 | tools: Tools 107 | type_to_search: Type to search. 108 | unauthorized: Unauthorized 109 | undo: undo 110 | view: View 111 | view_item: view %{item} 112 | was_successfully_created: was successfully created 113 | was_successfully_updated: was successfully updated 114 | x_items_more: 115 | one: one more item 116 | other: "%{count} more items" 117 | zero: no more items 118 | x_records_selected_from_a_total_of_x_html: %{selected} records selected on this page from a total of %{count} 119 | x_records_selected_from_all_pages_html: %{count} records selected from all pages 120 | you_missed_something_check_form: You might have missed something. Please check the form. 121 | -------------------------------------------------------------------------------- /config/locales/avo.tr.yml: -------------------------------------------------------------------------------- 1 | --- 2 | tr: 3 | avo: 4 | action_ran_successfully: Eylem başarıyla gerçekleşti! 5 | actions: Aksiyonlar 6 | and_x_other_resources: ve %{count} diğer kaynak 7 | are_you_sure: Emin misiniz? 8 | are_you_sure_detach_item: "%{item} öğesini ayırmak istediğinizden emin misiniz?" 9 | are_you_sure_you_want_to_run_this_option: Bu işlemi gerçekleştirmek istediğinize emin misiniz? 10 | attach: İlişkilendir 11 | attach_and_attach_another: İlişkilendir & Bir başka daha İlişkilendir 12 | attach_item: "%{item} öğesini ilişkilendir" 13 | attachment_class_attached: "%{attachment_class} ilişkilendirildi." 14 | attachment_class_detached: "%{attachment_class} ilişkisi kesildi." 15 | attachment_destroyed: Ek silindi 16 | cancel: İptal et 17 | choose_a_country: Bir ülke seç 18 | choose_an_option: Bir seçenek seç 19 | choose_item: "%{item} seçin" 20 | clear_value: Değeri temizle 21 | click_to_reveal_filters: Filtreleri ortaya çıkarmak için tıklayın 22 | confirm: Onayla 23 | create_new_item: Yeni bir %{item} oluşturun 24 | dashboard: Yönetim Paneli 25 | dashboards: Yönetim Panelleri 26 | delete: sil 27 | delete_file: Dosyayı sil 28 | delete_item: "%{item} öğresini sil" 29 | detach_item: "%{item} öğesinin ilişkisini kes" 30 | details: detaylar 31 | download: İndir 32 | download_file: Dosya indir 33 | download_item: "%{item} öğesini indir" 34 | edit: düzenle 35 | edit_item: "%{item} öğesini düzenle" 36 | empty_dashboard_message: Kartları yönetim paneline ekle 37 | failed: Başarısız 38 | failed_to_find_attachment: Ek bulunamadı 39 | failed_to_load: Yüklenemedi 40 | field_translations: 41 | file: 42 | one: dosya 43 | other: dosya 44 | zero: dosya 45 | people: 46 | one: kişi 47 | other: kişi 48 | zero: kişi 49 | filter_by: Tarafından filtre 50 | filters: Filtreler 51 | go_back: Geri dön 52 | grid_view: Grid görünümü 53 | hide_content: İçeriği gizle 54 | home: Anasayfa 55 | key_value_field: 56 | add_row: Satır ekle 57 | delete_row: Satır sil 58 | key: Anahtar 59 | value: Değer 60 | list_is_empty: Boş liste 61 | loading: Yükleniyor 62 | more: Daha fazla 63 | new: yeni 64 | next_page: Sonraki sayfa 65 | no_cards_present: Kart yok 66 | no_item_found: Hiç bulunamadı 67 | no_options_available: Seçenek yok 68 | no_related_item_found: İlişkili bulunamadı 69 | not_authorized: Bu eylemi gerçekleştirme yetkiniz yok. 70 | number_of_items: 71 | one: bir %{item} 72 | other: "%{count} %{item}" 73 | zero: sıfır %{item} 74 | oops_nothing_found: Hata! Hiçbir şey bulunamadı 75 | order: 76 | higher: Kaydı yüksekten sırala 77 | lower: Kaydı düşükten sırala 78 | reorder_record: Kaydı yeniden sırala 79 | to_bottom: Kaydı en alta taşı 80 | to_top: Kaydı en üste taşı 81 | per_page: Sayfa başına 82 | prev_page: Önceki sayfa 83 | remove_selection: Seçimi sil 84 | reset_filters: Filtreleri sıfırla 85 | resource_created: Kayıt oluşturuldu 86 | resource_destroyed: Kayıt silindi 87 | resource_translations: 88 | user: 89 | one: kullanıcı 90 | other: kullanıcı 91 | zero: kullanıcı 92 | resource_updated: Kayıt güncellendi 93 | resources: Kaynaklar 94 | run: Başlat 95 | save: Kaydet 96 | search: 97 | cancel_button: İptal et 98 | placeholder: Ara 99 | select_all: Tümünü seç 100 | select_all_matching: Tüm eşleşenleri seç 101 | select_item: Öğe seç 102 | show_content: İçeriği göster 103 | sign_out: Çıkış yap 104 | switch_to_view: "%{view_type} görünümüne kay" 105 | table_view: Tablo görünümü 106 | tools: Araçlar 107 | type_to_search: Aramak için yazın. 108 | unauthorized: Yetkisiz 109 | undo: geri al 110 | view: Görünüm 111 | view_item: "%{item} öğresini görüntüle" 112 | was_successfully_created: başarıyla oluşturuldu 113 | was_successfully_updated: başarıyla güncellendi 114 | x_items_more: 115 | one: bir öğe daha 116 | other: "%{count} öğe daha" 117 | zero: daha fazla öğe yok 118 | x_records_selected_from_a_total_of_x_html: %{selected} bu sayfada seçilen toplam kayıtlar %{count} 119 | x_records_selected_from_all_pages_html: %{count} tüm sayfalardan seçilen kayıtlar 120 | you_missed_something_check_form: Bir şeyleri kaçırmış olabilirsiniz. Lütfen formu kontrol edin. 121 | -------------------------------------------------------------------------------- /config/locales/avo.pt.yml: -------------------------------------------------------------------------------- 1 | --- 2 | pt: 3 | avo: 4 | action_ran_successfully: Ação executada com sucesso! 5 | actions: Ações 6 | and_x_other_resources: e %{count} outros recursos 7 | are_you_sure: Tem a certeza? 8 | are_you_sure_detach_item: Tem a certeza que deseja separar este %{item}. 9 | are_you_sure_you_want_to_run_this_option: Tem a certeza que deseja executar esta ação? 10 | attach: Anexar 11 | attach_and_attach_another: Anexar & anexar outro 12 | attach_item: Anexar %{item} 13 | attachment_class_attached: "%{attachment_class} anexado." 14 | attachment_class_detached: "%{attachment_class} separado." 15 | attachment_destroyed: Anexo destruído 16 | cancel: Cancelar 17 | choose_a_country: Escolha um país 18 | choose_an_option: Escolha uma opção 19 | choose_item: Escolher %{item} 20 | clear_value: Apagar valor 21 | click_to_reveal_filters: Clique para mostrar os filtros 22 | confirm: Confirmar 23 | create_new_item: Criar novo %{item} 24 | dashboard: Painel 25 | dashboards: Painéis 26 | delete: apagar 27 | delete_file: Apagar arquivo 28 | delete_item: Apagar %{item} 29 | detach_item: separar %{item} 30 | details: detalhe 31 | download: Download 32 | download_file: Download do ficheiro 33 | download_item: Download %{item} 34 | edit: editar 35 | edit_item: editar %{item} 36 | empty_dashboard_message: Adicionar cartões a este painel 37 | failed: Falhou 38 | failed_to_find_attachment: Falha ao encontrar anexo 39 | failed_to_load: Falhou ao carregar 40 | field_translations: 41 | file: 42 | one: ficheiro 43 | other: ficheiros 44 | zero: ficheiros 45 | people: 46 | one: pessoa 47 | other: pessoas 48 | zero: ninguém 49 | filter_by: Filtrar por 50 | filters: Filtros 51 | go_back: Voltar 52 | grid_view: Visualização em grelha 53 | hide_content: Esconder conteúdo 54 | home: Início 55 | key_value_field: 56 | add_row: Adicionar linha 57 | delete_row: Apagar linha 58 | key: Chave 59 | value: Valor 60 | list_is_empty: Lista vazia 61 | loading: A carregar 62 | more: Mais 63 | new: novo 64 | next_page: Próxima página 65 | no_cards_present: Nenhum cartão presente 66 | no_item_found: Nenhum registro encontrado 67 | no_options_available: Nenhuma opção disponível 68 | no_related_item_found: Nenhum registro relacionado encontrado 69 | not_authorized: Não está autorizado a executar essa ação. 70 | number_of_items: 71 | one: um %{item} 72 | other: "%{count} %{item}" 73 | zero: sem %{item} 74 | oops_nothing_found: Oops! Nada encontrado... 75 | order: 76 | higher: Mover recurso para cima 77 | lower: Mover recuros para baixo 78 | reorder_record: Reordenar recurso 79 | to_bottom: Mover recurso para o fundo 80 | to_top: Mover recurso para o topo 81 | per_page: Por página 82 | prev_page: Página anterior 83 | remove_selection: Remover seleção 84 | reset_filters: Limpar filtros 85 | resource_created: Recurso criado 86 | resource_destroyed: Recurso destruído 87 | resource_translations: 88 | user: 89 | one: utilizador 90 | other: utilizadores 91 | zero: utilizadores 92 | resource_updated: Recurso atualizado 93 | resources: Recursos 94 | run: Executar 95 | save: Guardar 96 | search: 97 | cancel_button: Cancelar 98 | placeholder: Procurar 99 | select_all: Selecionar tudo 100 | select_all_matching: Selecionar todas as correspondências 101 | select_item: Selecionar item 102 | show_content: Mostrar conteúdo 103 | sign_out: Terminar sessão 104 | switch_to_view: Alterar para visão %{view_type} 105 | table_view: Visualização em tabela 106 | tools: Ferramentas 107 | type_to_search: Escreva para pesquisar. 108 | unauthorized: Não autorizado 109 | undo: desfazer 110 | view: Ver 111 | view_item: ver %{item} 112 | was_successfully_created: foi criado com sucesso 113 | was_successfully_updated: foi atualizado com sucesso 114 | x_items_more: 115 | one: mais um item 116 | other: "%{count} mais items" 117 | zero: mais nenhum item 118 | x_records_selected_from_a_total_of_x_html: %{selected} itens selecionados nesta página de um total de %{count} 119 | x_records_selected_from_all_pages_html: %{count} itens selecionados de todas as páginas 120 | you_missed_something_check_form: Pode ter-se esquecido algo. Por favor, verifique o formulário. 121 | -------------------------------------------------------------------------------- /config/locales/avo.pt-BR.yml: -------------------------------------------------------------------------------- 1 | --- 2 | pt-BR: 3 | avo: 4 | action_ran_successfully: Ação executada com sucesso! 5 | actions: Ações 6 | and_x_other_resources: e %{count} outros recursos 7 | are_you_sure: Você tem certeza? 8 | are_you_sure_detach_item: Você tem certeza que deseja separar este %{item}. 9 | are_you_sure_you_want_to_run_this_option: Você tem certeza que deseja executar esta ação? 10 | attach: Anexar 11 | attach_and_attach_another: Anexar & anexar outro 12 | attach_item: Anexar %{item} 13 | attachment_class_attached: "%{attachment_class} anexado." 14 | attachment_class_detached: "%{attachment_class} separado." 15 | attachment_destroyed: Anexo destruído 16 | cancel: Cancelar 17 | choose_a_country: Escolha um país 18 | choose_an_option: Escolha uma opção 19 | choose_item: Escolher %{item} 20 | clear_value: Limpar valor 21 | click_to_reveal_filters: Clique para revelar os filtros 22 | confirm: Confirmar 23 | create_new_item: Criar novo %{item} 24 | dashboard: Painel 25 | dashboards: Painéis 26 | delete: deletar 27 | delete_file: Deletar arquivo 28 | delete_item: Deletar %{item} 29 | detach_item: separar %{item} 30 | details: detalhe 31 | download: Baixar 32 | download_file: Baixar arquivo 33 | download_item: Baixar %{item} 34 | edit: editar 35 | edit_item: editar %{item} 36 | empty_dashboard_message: Adicionar cartões a este painel 37 | failed: Falhou 38 | failed_to_find_attachment: Falhou ao achar anexo 39 | failed_to_load: Falha ao carregar 40 | field_translations: 41 | file: 42 | one: arquivo 43 | other: arquivos 44 | zero: arquivos 45 | people: 46 | one: pessoa 47 | other: pessoas 48 | zero: ninguém 49 | filter_by: Filtrar por 50 | filters: Filtros 51 | go_back: Voltar 52 | grid_view: Visualização em grade 53 | hide_content: Esconder conteúdo 54 | home: Início 55 | key_value_field: 56 | add_row: Adicionar linha 57 | delete_row: Remover linha 58 | key: Chave 59 | value: Valor 60 | list_is_empty: Lista vazia 61 | loading: Carregando 62 | more: Mais 63 | new: novo 64 | next_page: Próxima página 65 | no_cards_present: Nenhum cartão presente 66 | no_item_found: Nenhum registro encontrado 67 | no_options_available: Nenhuma opção disponível 68 | no_related_item_found: Nenhum registro relacionado encontrado 69 | not_authorized: Você não está autorizado à executar essa ação. 70 | number_of_items: 71 | one: um %{item} 72 | other: "%{count} %{item}" 73 | zero: sem %{item} 74 | oops_nothing_found: Oops! Nada encontrado... 75 | order: 76 | higher: Mover registro um para cima 77 | lower: Mover registro um para baixo 78 | reorder_record: Reordenar registro 79 | to_bottom: Mover registro para baixo 80 | to_top: Mover registro para cima 81 | per_page: Por página 82 | prev_page: Página anterior 83 | remove_selection: Remover seleção 84 | reset_filters: Limpar filtros 85 | resource_created: Recurso criado 86 | resource_destroyed: Recurso destruído 87 | resource_translations: 88 | user: 89 | one: usuário 90 | other: usuários 91 | zero: usuários 92 | resource_updated: Recurso atualizado 93 | resources: Recursos 94 | run: Executar 95 | save: Salvar 96 | search: 97 | cancel_button: Cancelar 98 | placeholder: Procurar 99 | select_all: Selecionar tudo 100 | select_all_matching: Selecione todas as correspondências 101 | select_item: Selecionar item 102 | show_content: Mostrar conteúdo 103 | sign_out: sair 104 | switch_to_view: Alterar para visão %{view_type} 105 | table_view: Visualização em tabela 106 | tools: Ferramentas 107 | type_to_search: Digite para buscar. 108 | unauthorized: Não autorizado 109 | undo: desfazer 110 | view: Visualizar 111 | view_item: visualizar %{item} 112 | was_successfully_created: foi criado com sucesso 113 | was_successfully_updated: foi atualizado com sucesso 114 | x_items_more: 115 | one: mais um item 116 | other: "%{count} mais items" 117 | zero: mais nenhum item 118 | x_records_selected_from_a_total_of_x_html: %{selected} registros selecionados nesta página de um total de %{count} 119 | x_records_selected_from_all_pages_html: %{count} registros selecionados de todas as páginas 120 | you_missed_something_check_form: Você pode ter esquecido algo. Por favor, cheque o formulário. 121 | -------------------------------------------------------------------------------- /config/locales/avo.ro.yml: -------------------------------------------------------------------------------- 1 | --- 2 | ro: 3 | avo: 4 | action_ran_successfully: Acțiunea a rulat cu succes! 5 | actions: Acțiuni 6 | and_x_other_resources: plus alte %{count} recorduri 7 | are_you_sure: Ești sigur? 8 | are_you_sure_detach_item: Sigur vrei să detașezi asta %{item}. 9 | are_you_sure_you_want_to_run_this_option: Ești sigur că vrei să rulezi aceasta acțiune? 10 | attach: Atașează 11 | attach_and_attach_another: Atașează și atașează inca unul 12 | attach_item: Atașează %{item} 13 | attachment_class_attached: "%{attachment_class} anexat." 14 | attachment_class_detached: "%{attachment_class} separat." 15 | attachment_destroyed: Atașamentul a fost distrus 16 | cancel: Anulează 17 | choose_a_country: Alege o țară 18 | choose_an_option: Alege o opțiune 19 | choose_item: Alege %{item} 20 | clear_value: Șterge valoarea 21 | click_to_reveal_filters: Faceți clic pentru a afișa filtrele 22 | confirm: Confirm 23 | create_new_item: Creează %{item} 24 | dashboard: Panou de control 25 | dashboards: Panouri de control 26 | delete: șterge 27 | delete_file: Șterge fișierul 28 | delete_item: Șterge %{item} 29 | detach_item: detașează %{item} 30 | details: detalii 31 | download: Descarcă 32 | download_file: Descarcă fișier 33 | download_item: Descarcă %{item} 34 | edit: modifică 35 | edit_item: modifică %{item} 36 | empty_dashboard_message: Adaugă carduri în acest dashboard 37 | failed: A eșuat 38 | failed_to_find_attachment: Atașamentul nu a fost găsit 39 | failed_to_load: Încărcarea a eșuat 40 | field_translations: 41 | file: 42 | one: fișier 43 | other: fișiere 44 | zero: fișiere 45 | people: 46 | one: peep 47 | other: peeps 48 | zero: peeps 49 | filter_by: Filtează după 50 | filters: Filtre 51 | go_back: Înapoi 52 | grid_view: Vezi sub formă de grid 53 | hide_content: Ascunde conținutul 54 | home: Acasă 55 | key_value_field: 56 | add_row: Adaugă rând 57 | delete_row: Șterge rând 58 | key: Cheie 59 | value: Valoare 60 | list_is_empty: Lista este goală 61 | loading: Se incarcă 62 | more: Mai multe 63 | new: nou 64 | next_page: Pagina următoare 65 | no_cards_present: Niciun card disponibil 66 | no_item_found: Nici un articol găsit 67 | no_options_available: Nicio opțiune disponibilă 68 | no_related_item_found: Nici un articol asociat găsit 69 | not_authorized: Nu sunteți autorizat să efectuați această acțiune. 70 | number_of_items: 71 | one: un %{item} 72 | other: "%{count} %{item}" 73 | zero: 0 %{item} 74 | oops_nothing_found: Oups! Nu am găsit rezultate... 75 | order: 76 | higher: Mutați înregistrarea mai sus 77 | lower: Mutați înregistrarea mai jos 78 | reorder_record: Reordonați înregistrarea 79 | to_bottom: Mutați înregistrarea jos de tot 80 | to_top: Mutați înregistrarea sus de tot 81 | per_page: Pe pagină 82 | prev_page: Pagina anterioara 83 | remove_selection: Șterge selecția 84 | reset_filters: Resetați filtrele 85 | resource_created: Resursă creata 86 | resource_destroyed: Resursă ștearsă 87 | resource_translations: 88 | user: 89 | one: utilizator 90 | other: utilizatori 91 | zero: utilizatori 92 | resource_updated: Resursă actualizata 93 | resources: Resurse 94 | run: Rulează 95 | save: Salvează 96 | search: 97 | cancel_button: Anulare 98 | placeholder: Caută 99 | select_all: Selectează totul 100 | select_all_matching: Selectează toate care se potrivesc 101 | select_item: Selectează record 102 | show_content: Arată conținutul 103 | sign_out: Delogare 104 | switch_to_view: Comutați la vizualizarea %{view_type} 105 | table_view: Vezi sub formă de tabel 106 | tools: Instrumente 107 | type_to_search: Caută aici... 108 | unauthorized: Neautorizat 109 | undo: Anulează 110 | view: vezi 111 | view_item: vezi %{item} 112 | was_successfully_created: a fost creat 113 | was_successfully_updated: a fost actualizat 114 | x_items_more: 115 | one: încă un articol 116 | other: "%{count} mai multe articole" 117 | zero: zero articole 118 | x_records_selected_from_a_total_of_x_html: %{selected} selectate dintr-un total de %{count} 119 | x_records_selected_from_all_pages_html: %{count} selectate din toate paginile 120 | you_missed_something_check_form: S-ar putea să fi omis ceva. Vă rugăm să verificați formularul. 121 | -------------------------------------------------------------------------------- /config/initializers/trestle.rb: -------------------------------------------------------------------------------- 1 | Trestle.configure do |config| 2 | # == Customization Options 3 | # 4 | # Set the page title shown in the main header within the admin. 5 | # 6 | config.site_title = "Evaluate Admin Panels" 7 | 8 | # Specify a custom image to be used in place of the site title for mobile and 9 | # expanded/desktop navigation. These images should be placed within your 10 | # asset paths, e.g. app/assets/images. 11 | # 12 | # config.site_logo = "logo.png" 13 | 14 | # Specify a custom image to be used for the collapsed/tablet navigation. 15 | # 16 | # config.site_logo_small = "logo-small.png" 17 | 18 | # Specify a favicon to be used within the admin. 19 | # 20 | # config.favicon = "favicon.ico" 21 | 22 | # Set the text shown in the page footer within the admin. 23 | # Defaults to 'Powered by Trestle'. 24 | # 25 | # config.footer = "Powered by Trestle" 26 | 27 | # Sets the default precision for timestamps (either :minutes or :seconds). 28 | # Defaults to :minutes. 29 | # 30 | # config.timestamp_precision = :minutes 31 | 32 | # == Mounting Options 33 | # 34 | # Set the path at which to mount the Trestle admin. Defaults to /admin. 35 | # 36 | config.path = "/trestle" 37 | 38 | # Toggle whether Trestle should automatically mount the admin within your 39 | # Rails application's routes. Defaults to true. 40 | # 41 | # config.automount = false 42 | 43 | # == Navigation Options 44 | # 45 | # Set the path to consider the application root (for title links and breadcrumbs). 46 | # Defaults to the same value as `config.path`. 47 | # 48 | # config.root = "/" 49 | 50 | # Set the initial breadcrumbs to display in the breadcrumb trail. 51 | # Defaults to a breadcrumb labeled 'Home' linking to to the application root. 52 | # 53 | # config.root_breadcrumbs = -> { [Trestle::Breadcrumb.new("Home", Trestle.config.root)] } 54 | 55 | # Set the default icon class to use when it is not explicitly provided. 56 | # Defaults to "fa fa-arrow-circle-o-right". 57 | # 58 | # config.default_navigation_icon = "fa fa-arrow-circle-o-right" 59 | 60 | # Add an explicit menu block to be added to the admin navigation. 61 | # 62 | # config.menu do 63 | # group "Custom Group" do 64 | # item "Custom Link", "/admin/custom", icon: "fa fa-car", badge: { text: "NEW!", class: "label-success" }, priority: :first 65 | # end 66 | # end 67 | 68 | # == Extension Options 69 | # 70 | # Specify helper modules to expose to the admin. 71 | # 72 | # config.helper :all 73 | # config.helper -> { CustomHelper } 74 | 75 | # Register callbacks to run before, after or around all Trestle actions. 76 | # 77 | # config.before_action do |controller| 78 | # Rails.logger.debug("Before action") 79 | # end 80 | # 81 | # config.after_action do |controller| 82 | # Rails.logger.debug("After action") 83 | # end 84 | # 85 | # config.around_action do |controller, block| 86 | # Rails.logger.debug("Around action (before)") 87 | # block.call 88 | # Rails.logger.debug("Around action (after)") 89 | # end 90 | 91 | # Specify a custom hook to be injected into the admin. 92 | # 93 | # config.hook(:stylesheets) do 94 | # stylesheet_link_tag "custom" 95 | # end 96 | 97 | # Toggle whether Turbolinks is enabled within the admin. 98 | # Defaults to true if Turbolinks is available. 99 | # 100 | # config.turbolinks = false 101 | 102 | # Specify the parameters that should persist across requests when 103 | # paginating or reordering. Defaults to [:sort, :order, :scope]. 104 | # 105 | # config.persistent_params << :query 106 | 107 | # List of methods to try calling on an instance when displayed by the `display` helper. 108 | # Defaults to [:display_name, :full_name, :name, :title, :username, :login, :email]. 109 | # 110 | # config.display_methods.unshift(:admin_label) 111 | 112 | # Customize the default adapter class used by all admin resources. 113 | # See the documentation on Trestle::Adapters::Adapter for details on 114 | # the adapter methods that can be customized. 115 | # 116 | # config.default_adapter = Trestle::Adapters.compose(Trestle::Adapters::SequelAdapter) 117 | # config.default_adapter.include MyAdapterExtensions 118 | 119 | # Register a form field type to be made available to the Trestle form builder. 120 | # Field types should conform to the following method definition: 121 | # 122 | # class CustomFormField 123 | # def initialize(builder, template, name, options={}, &block); end 124 | # def render; end 125 | # end 126 | # 127 | # config.form_field :custom, -> { CustomFormField } 128 | 129 | # == Debugging Options 130 | # 131 | # Enable debugging of form errors. Defaults to true in development mode. 132 | # 133 | # config.debug_form_errors = true 134 | end if Object.const_defined?('Trestle') 135 | -------------------------------------------------------------------------------- /config/locales/avo.fr.yml: -------------------------------------------------------------------------------- 1 | --- 2 | fr: 3 | avo: 4 | action_ran_successfully: L'action s'est exécutée avec succès ! 5 | actions: Actions 6 | and_x_other_resources: et %{count} autres ressources 7 | are_you_sure: Êtes-vous sûr ? 8 | are_you_sure_detach_item: Êtes-vous sûr de vouloir détacher %{item}. 9 | are_you_sure_you_want_to_run_this_option: Etes-vous sûr de vouloir exécuter cette action ? 10 | attach: Attacher 11 | attach_and_attach_another: joindre et joindre un autre 12 | attach_item: Attacher %{item} 13 | attachment_class_attached: "%{attachment_class} attaché." 14 | attachment_class_detached: "%{attachment_class} détaché." 15 | attachment_destroyed: Pièce jointe détruite 16 | cancel: Annuler 17 | choose_a_country: Sélectionnez un pays 18 | choose_an_option: Sélectionnez une option 19 | choose_item: Choisir %{item} 20 | clear_value: Effacer la valeur 21 | click_to_reveal_filters: Cliquez pour révéler les filtres 22 | confirm: Confirmer 23 | create_new_item: Créer un nouveau %{item} 24 | dashboard: Tableau de bord 25 | dashboards: Tableaux de bord 26 | delete: supprimer 27 | delete_file: Supprimer le fichier 28 | delete_item: Supprimer %{item} 29 | detach_item: détacher %{item} 30 | details: détails 31 | download: Télécharger 32 | download_file: Télécharger le fichier 33 | download_item: Télécharger %{item} 34 | edit: éditer 35 | edit_item: éditer %{item} 36 | empty_dashboard_message: Ajouter des cartes à ce tableau de bord 37 | failed: Échec 38 | failed_to_find_attachment: Impossible de trouver la pièce jointe 39 | failed_to_load: Impossible de charger 40 | field_translations: 41 | file: 42 | one: fichier 43 | other: fichiers 44 | zero: fichier 45 | people: 46 | one: personne 47 | other: personnes 48 | zero: personne 49 | filter_by: Filtrer par 50 | filters: Filtres 51 | go_back: Retourner en arrière 52 | grid_view: Vue grille 53 | hide_content: Cacher le contenu 54 | home: Accueil 55 | key_value_field: 56 | add_row: Ajouter une ligne 57 | delete_row: Supprimer une ligne 58 | key: Clé 59 | value: Valeur 60 | list_is_empty: La liste est vide 61 | loading: Chargement 62 | more: Plus 63 | new: Nouveau 64 | next_page: Page suivante 65 | no_cards_present: Aucune carte présente 66 | no_item_found: Enregistrement non trouvé 67 | no_options_available: Aucune option disponible 68 | no_related_item_found: Enregistrement connexe introuvable 69 | not_authorized: Vous n'êtes pas autorisé à effectuer cette action. 70 | number_of_items: 71 | one: un %{item} 72 | other: "%{count} %{item}" 73 | zero: aucun %{item} 74 | oops_nothing_found: Oups ! Rien n'a été trouvé... 75 | order: 76 | higher: Déplacer plus haut 77 | lower: Déplacer plus bas 78 | reorder_record: Réorganiser 79 | to_bottom: Déplacer tout en bas 80 | to_top: Déplacer tout en haut 81 | per_page: Par page 82 | prev_page: Page précédente 83 | remove_selection: Supprimer la sélection 84 | reset_filters: Réinitialiser les filtres 85 | resource_created: Ressource créee 86 | resource_destroyed: Ressource détruite 87 | resource_translations: 88 | user: 89 | one: utilisateurs 90 | other: utilisateurs 91 | zero: utilisateur 92 | resource_updated: Ressource mise à jour 93 | resources: Ressources 94 | run: Exécuter 95 | save: Enregistrer 96 | search: 97 | cancel_button: Annuler 98 | placeholder: Rechercher 99 | select_all: Sélectionner tout sur la page 100 | select_all_matching: Sélectionner toutes les correspondances 101 | select_item: Sélectionnez un élément 102 | show_content: Afficher le contenu 103 | sign_out: Se déconnecter 104 | switch_to_view: Passez à la vue %{view_type} 105 | table_view: Vue table 106 | tools: Outils 107 | type_to_search: Type à rechercher. 108 | unauthorized: Non autorisé 109 | undo: annuler 110 | view: Vue 111 | view_item: voir %{item} 112 | was_successfully_created: a été créé avec succès 113 | was_successfully_updated: a été mis à jour avec succès 114 | x_items_more: 115 | one: un élément de plus 116 | other: "%{count} éléments en plus" 117 | zero: aucun élément supplémentaire 118 | x_records_selected_from_a_total_of_x_html: %{selected} enregistrements sélectionnés sur cette page sur un total de %{count} 119 | x_records_selected_from_all_pages_html: %{count} enregistrements sélectionnés dans toutes les pages 120 | you_missed_something_check_form: Vous avez peut-être oublié quelque chose. Veuillez vérifier le formulaire 121 | -------------------------------------------------------------------------------- /config/initializers/avo.rb: -------------------------------------------------------------------------------- 1 | # For more information regarding these settings check out our docs https://docs.avohq.io 2 | Avo.configure do |config| 3 | ## == Routing == 4 | config.root_path = '/avo' 5 | 6 | # Where should the user be redirected when visting the `/avo` url 7 | # config.home_path = nil 8 | 9 | ## == Licensing == 10 | config.license = 'community' # change this to 'pro' when you add the license key 11 | # config.license_key = ENV['AVO_LICENSE_KEY'] 12 | 13 | ## == Set the context == 14 | config.set_context do 15 | # Return a context object that gets evaluated in Avo::ApplicationController 16 | end 17 | 18 | ## == Authentication == 19 | # config.current_user_method = {} 20 | # config.authenticate_with do 21 | # end 22 | 23 | ## == Authorization == 24 | # config.authorization_methods = { 25 | # index: 'index?', 26 | # show: 'show?', 27 | # edit: 'edit?', 28 | # new: 'new?', 29 | # update: 'update?', 30 | # create: 'create?', 31 | # destroy: 'destroy?', 32 | # } 33 | # config.raise_error_on_missing_policy = false 34 | # config.authorization_client = :pundit 35 | 36 | ## == Localization == 37 | # config.locale = 'en-US' 38 | 39 | ## == Resource options == 40 | # config.resource_controls_placement = :right 41 | # config.model_resource_mapping = {} 42 | # config.default_view_type = :table 43 | # config.per_page = 24 44 | # config.per_page_steps = [12, 24, 48, 72] 45 | # config.via_per_page = 8 46 | # config.id_links_to_resource = false 47 | # config.cache_resources_on_index_view = true 48 | ## permanent enable or disable cache_resource_filters, default value is false 49 | # config.cache_resource_filters = false 50 | ## provide a lambda to enable or disable cache_resource_filters per user/resource. 51 | # config.cache_resource_filters = ->(current_user:, resource:) { current_user.cache_resource_filters?} 52 | 53 | ## == Customization == 54 | # config.app_name = 'Avocadelicious' 55 | # config.timezone = 'UTC' 56 | # config.currency = 'USD' 57 | # config.hide_layout_when_printing = false 58 | # config.full_width_container = false 59 | # config.full_width_index_view = false 60 | # config.search_debounce = 300 61 | # config.view_component_path = "app/components" 62 | # config.display_license_request_timeout_error = true 63 | # config.disabled_features = [] 64 | # config.resource_controls = :right 65 | # config.tabs_style = :tabs # can be :tabs or :pills 66 | # config.buttons_on_form_footers = true 67 | # config.field_wrapper_layout = true 68 | 69 | ## == Branding == 70 | # config.branding = { 71 | # colors: { 72 | # background: "248 246 242", 73 | # 100 => "#CEE7F8", 74 | # 400 => "#399EE5", 75 | # 500 => "#0886DE", 76 | # 600 => "#066BB2", 77 | # }, 78 | # chart_colors: ["#0B8AE2", "#34C683", "#2AB1EE", "#34C6A8"], 79 | # logo: "/avo-assets/logo.png", 80 | # logomark: "/avo-assets/logomark.png", 81 | # placeholder: "/avo-assets/placeholder.svg", 82 | # favicon: "/avo-assets/favicon.ico" 83 | # } 84 | 85 | ## == Breadcrumbs == 86 | # config.display_breadcrumbs = true 87 | # config.set_initial_breadcrumbs do 88 | # add_breadcrumb "Home", '/avo' 89 | # end 90 | 91 | # == Menus == 92 | config.main_menu = -> { 93 | link_to "Avo Repo", "https://github.com/avo-hq/avo", target: :_blank 94 | resource :active_admin_comments 95 | 96 | section "E-commerce", icon: "shopping-cart" do 97 | resource :customers 98 | resource :orders 99 | resource :order_details 100 | end 101 | 102 | section "Warehouse", icon: "home-modern" do 103 | resource :products 104 | resource :employee 105 | resource :categories 106 | end 107 | 108 | section "Motor", icon: "cog", collapsable: true, collapsed: true do 109 | [ 110 | :motor_audits, 111 | :motor_forms, 112 | :motor_resources, 113 | :motor_configs, 114 | :motor_queries, 115 | :motor_dashboards, 116 | :motor_api_configs, 117 | ].each do |resource_sym| 118 | resource resource_sym, label: resource_sym.to_s.gsub("motor", "").titleize 119 | end 120 | 121 | group "Alerts", collapsable: true do 122 | resource :motor_alerts, label: "Alerts" 123 | resource :motor_alert_locks, label: "Alert Locks" 124 | resource :motor_notifications, label: "Notifications" 125 | resource :motor_reminders, label: "Reminders" 126 | end 127 | 128 | group "Notes", collapsable: true, collapsed: true do 129 | resource :motor_notes, label: "Notes" 130 | resource :motor_note_tags, label: "Note Tags" 131 | resource :motor_note_tag_tags, label: "Note Tag Tags" 132 | end 133 | 134 | group "Tags", collapsable: true, collapsed: true do 135 | resource :motor_taggable_tags, label: "Note Taggable Tags" 136 | resource :motor_tags, label: "Tags" 137 | end 138 | end 139 | } 140 | # config.profile_menu = -> { 141 | # link "Profile", path: "/avo/profile", icon: "user-circle" 142 | # } 143 | end if Object.const_defined?('Avo') 144 | -------------------------------------------------------------------------------- /db/migrate/20230221083939_install_motor_admin.rb: -------------------------------------------------------------------------------- 1 | class InstallMotorAdmin < ActiveRecord::Migration[7.0] 2 | def self.up 3 | create_table :motor_queries do |t| 4 | t.column :name, :string, null: false 5 | t.column :description, :text 6 | t.column :sql_body, :text, null: false 7 | t.column :preferences, :text, null: false 8 | t.column :author_id, :bigint 9 | t.column :author_type, :string 10 | t.column :deleted_at, :datetime 11 | 12 | t.timestamps 13 | 14 | t.index :updated_at 15 | t.index 'name', 16 | name: 'motor_queries_name_unique_index', 17 | unique: true, 18 | where: 'deleted_at IS NULL' 19 | end 20 | 21 | create_table :motor_dashboards do |t| 22 | t.column :title, :string, null: false 23 | t.column :description, :text 24 | t.column :preferences, :text, null: false 25 | t.column :author_id, :bigint 26 | t.column :author_type, :string 27 | t.column :deleted_at, :datetime 28 | 29 | t.timestamps 30 | 31 | t.index :updated_at 32 | t.index 'title', 33 | name: 'motor_dashboards_title_unique_index', 34 | unique: true, 35 | where: 'deleted_at IS NULL' 36 | end 37 | 38 | create_table :motor_forms do |t| 39 | t.column :name, :string, null: false 40 | t.column :description, :text 41 | t.column :api_path, :text, null: false 42 | t.column :http_method, :string, null: false 43 | t.column :preferences, :text, null: false 44 | t.column :author_id, :bigint 45 | t.column :author_type, :string 46 | t.column :deleted_at, :datetime 47 | t.column :api_config_name, :string, null: false 48 | 49 | t.timestamps 50 | 51 | t.index :updated_at 52 | t.index 'name', 53 | name: 'motor_forms_name_unique_index', 54 | unique: true, 55 | where: 'deleted_at IS NULL' 56 | end 57 | 58 | create_table :motor_resources do |t| 59 | t.column :name, :string, null: false, index: { unique: true } 60 | t.column :preferences, :text, null: false 61 | 62 | t.timestamps 63 | 64 | t.index :updated_at 65 | end 66 | 67 | create_table :motor_configs do |t| 68 | t.column :key, :string, null: false, index: { unique: true } 69 | t.column :value, :text, null: false 70 | 71 | t.timestamps 72 | 73 | t.index :updated_at 74 | end 75 | 76 | create_table :motor_alerts do |t| 77 | t.references :query, null: false, foreign_key: { to_table: :motor_queries }, index: true 78 | t.column :name, :string, null: false 79 | t.column :description, :text 80 | t.column :to_emails, :text, null: false 81 | t.column :is_enabled, :boolean, null: false, default: true 82 | t.column :preferences, :text, null: false 83 | t.column :author_id, :bigint 84 | t.column :author_type, :string 85 | t.column :deleted_at, :datetime 86 | 87 | t.timestamps 88 | 89 | t.index :updated_at 90 | t.index 'name', 91 | name: 'motor_alerts_name_unique_index', 92 | unique: true, 93 | where: 'deleted_at IS NULL' 94 | end 95 | 96 | create_table :motor_alert_locks do |t| 97 | t.references :alert, null: false, foreign_key: { to_table: :motor_alerts } 98 | t.column :lock_timestamp, :string, null: false 99 | 100 | t.timestamps 101 | 102 | t.index %i[alert_id lock_timestamp], unique: true 103 | end 104 | 105 | create_table :motor_tags do |t| 106 | t.column :name, :string, null: false 107 | 108 | t.timestamps 109 | 110 | t.index 'name', 111 | name: 'motor_tags_name_unique_index', 112 | unique: true 113 | end 114 | 115 | create_table :motor_taggable_tags do |t| 116 | t.references :tag, null: false, foreign_key: { to_table: :motor_tags }, index: true 117 | t.column :taggable_id, :bigint, null: false 118 | t.column :taggable_type, :string, null: false 119 | 120 | t.index %i[taggable_id taggable_type tag_id], 121 | name: 'motor_polymorphic_association_tag_index', 122 | unique: true 123 | end 124 | 125 | create_table :motor_audits do |t| 126 | t.column :auditable_id, :string 127 | t.column :auditable_type, :string 128 | t.column :associated_id, :string 129 | t.column :associated_type, :string 130 | t.column :user_id, :bigint 131 | t.column :user_type, :string 132 | t.column :username, :string 133 | t.column :action, :string 134 | t.column :audited_changes, :text 135 | t.column :version, :bigint, default: 0 136 | t.column :comment, :text 137 | t.column :remote_address, :string 138 | t.column :request_uuid, :string 139 | t.column :created_at, :datetime 140 | end 141 | 142 | create_table :motor_api_configs do |t| 143 | t.column :name, :string, null: false 144 | t.column :url, :string, null: false 145 | t.column :preferences, :text, null: false 146 | t.column :credentials, :text, null: false 147 | t.column :description, :text 148 | t.column :deleted_at, :datetime 149 | 150 | t.timestamps 151 | 152 | t.index 'name', 153 | name: 'motor_api_configs_name_unique_index', 154 | unique: true, 155 | where: 'deleted_at IS NULL' 156 | end 157 | 158 | create_table :motor_notes do |t| 159 | t.column :body, :text 160 | t.column :author_id, :bigint 161 | t.column :author_type, :string 162 | t.column :record_id, :string, null: false 163 | t.column :record_type, :string, null: false 164 | t.column :deleted_at, :datetime 165 | 166 | t.timestamps 167 | 168 | t.index %i[author_id author_type], 169 | name: 'motor_notes_author_id_author_type_index' 170 | end 171 | 172 | create_table :motor_note_tags do |t| 173 | t.column :name, :string, null: false 174 | 175 | t.timestamps 176 | 177 | t.index 'name', 178 | name: 'motor_note_tags_name_unique_index', 179 | unique: true 180 | end 181 | 182 | create_table :motor_note_tag_tags do |t| 183 | t.references :tag, null: false, foreign_key: { to_table: :motor_note_tags }, index: true 184 | t.references :note, null: false, foreign_key: { to_table: :motor_notes }, index: false 185 | 186 | t.index %i[note_id tag_id], 187 | name: 'motor_note_tags_note_id_tag_id_index', 188 | unique: true 189 | end 190 | 191 | create_table :motor_reminders do |t| 192 | t.column :author_id, :bigint, null: false 193 | t.column :author_type, :string, null: false 194 | t.column :recipient_id, :bigint, null: false 195 | t.column :recipient_type, :string, null: false 196 | t.column :record_id, :string 197 | t.column :record_type, :string 198 | t.column :scheduled_at, :datetime, null: false, index: true 199 | 200 | t.timestamps 201 | 202 | t.index %i[author_id author_type], 203 | name: 'motor_reminders_author_id_author_type_index' 204 | 205 | t.index %i[recipient_id recipient_type], 206 | name: 'motor_reminders_recipient_id_recipient_type_index' 207 | 208 | t.index %i[record_id record_type], 209 | name: 'motor_reminders_record_id_record_type_index' 210 | end 211 | 212 | create_table :motor_notifications do |t| 213 | t.column :title, :string, null: false 214 | t.column :description, :text 215 | t.column :recipient_id, :bigint, null: false 216 | t.column :recipient_type, :string, null: false 217 | t.column :record_id, :string 218 | t.column :record_type, :string 219 | t.column :status, :string, null: false 220 | 221 | t.timestamps 222 | 223 | t.index %i[recipient_id recipient_type], 224 | name: 'motor_notifications_recipient_id_recipient_type_index' 225 | 226 | t.index %i[record_id record_type], 227 | name: 'motor_notifications_record_id_record_type_index' 228 | end 229 | 230 | add_index :motor_audits, %i[auditable_type auditable_id version], name: 'motor_auditable_index' 231 | add_index :motor_audits, %i[associated_type associated_id], name: 'motor_auditable_associated_index' 232 | add_index :motor_audits, %i[user_id user_type], name: 'motor_auditable_user_index' 233 | add_index :motor_audits, :request_uuid 234 | add_index :motor_audits, :created_at 235 | 236 | model = Class.new(ApplicationRecord) 237 | 238 | model.table_name = 'motor_configs' 239 | 240 | model.create!(key: 'header.links', value: [{ 241 | name: '⭐ Star on GitHub', 242 | path: 'https://github.com/motor-admin/motor-admin-rails' 243 | }].to_json) 244 | 245 | model.table_name = 'motor_api_configs' 246 | 247 | model.create!(name: 'origin', url: '/', preferences: {}, credentials: {}) 248 | end 249 | 250 | def self.down 251 | drop_table :motor_audits 252 | drop_table :motor_alert_locks 253 | drop_table :motor_alerts 254 | drop_table :motor_forms 255 | drop_table :motor_taggable_tags 256 | drop_table :motor_tags 257 | drop_table :motor_resources 258 | drop_table :motor_configs 259 | drop_table :motor_queries 260 | drop_table :motor_dashboards 261 | drop_table :motor_api_configs 262 | drop_table :motor_note_tag_tags 263 | drop_table :motor_note_tags 264 | drop_table :motor_notes 265 | drop_table :motor_notifications 266 | drop_table :motor_reminders 267 | end 268 | end 269 | -------------------------------------------------------------------------------- /config/initializers/active_admin.rb: -------------------------------------------------------------------------------- 1 | ActiveAdmin.setup do |config| 2 | # == Site Title 3 | # 4 | # Set the title that is displayed on the main layout 5 | # for each of the active admin pages. 6 | # 7 | config.site_title = "Evaluate Admin Panels" 8 | 9 | # Set the link url for the title. For example, to take 10 | # users to your main site. Defaults to no link. 11 | # 12 | # config.site_title_link = "/" 13 | 14 | # Set an optional image to be displayed for the header 15 | # instead of a string (overrides :site_title) 16 | # 17 | # Note: Aim for an image that's 21px high so it fits in the header. 18 | # 19 | # config.site_title_image = "logo.png" 20 | 21 | # == Default Namespace 22 | # 23 | # Set the default namespace each administration resource 24 | # will be added to. 25 | # 26 | # eg: 27 | # config.default_namespace = :hello_world 28 | config.default_namespace = :aa 29 | # 30 | # This will create resources in the HelloWorld module and 31 | # will namespace routes to /hello_world/* 32 | # 33 | # To set no namespace by default, use: 34 | # config.default_namespace = false 35 | # 36 | # Default: 37 | # config.default_namespace = :admin 38 | # 39 | # You can customize the settings for each namespace by using 40 | # a namespace block. For example, to change the site title 41 | # within a namespace: 42 | # 43 | # config.namespace :admin do |admin| 44 | # admin.site_title = "Custom Admin Title" 45 | # end 46 | # 47 | # This will ONLY change the title for the admin section. Other 48 | # namespaces will continue to use the main "site_title" configuration. 49 | 50 | # == User Authentication 51 | # 52 | # Active Admin will automatically call an authentication 53 | # method in a before filter of all controller actions to 54 | # ensure that there is a currently logged in admin user. 55 | # 56 | # This setting changes the method which Active Admin calls 57 | # within the application controller. 58 | # config.authentication_method = :authenticate_admin_user! 59 | 60 | # == User Authorization 61 | # 62 | # Active Admin will automatically call an authorization 63 | # method in a before filter of all controller actions to 64 | # ensure that there is a user with proper rights. You can use 65 | # CanCanAdapter or make your own. Please refer to documentation. 66 | # config.authorization_adapter = ActiveAdmin::CanCanAdapter 67 | 68 | # In case you prefer Pundit over other solutions you can here pass 69 | # the name of default policy class. This policy will be used in every 70 | # case when Pundit is unable to find suitable policy. 71 | # config.pundit_default_policy = "MyDefaultPunditPolicy" 72 | 73 | # If you wish to maintain a separate set of Pundit policies for admin 74 | # resources, you may set a namespace here that Pundit will search 75 | # within when looking for a resource's policy. 76 | # config.pundit_policy_namespace = :admin 77 | 78 | # You can customize your CanCan Ability class name here. 79 | # config.cancan_ability_class = "Ability" 80 | 81 | # You can specify a method to be called on unauthorized access. 82 | # This is necessary in order to prevent a redirect loop which happens 83 | # because, by default, user gets redirected to Dashboard. If user 84 | # doesn't have access to Dashboard, he'll end up in a redirect loop. 85 | # Method provided here should be defined in application_controller.rb. 86 | # config.on_unauthorized_access = :access_denied 87 | 88 | # == Current User 89 | # 90 | # Active Admin will associate actions with the current 91 | # user performing them. 92 | # 93 | # This setting changes the method which Active Admin calls 94 | # (within the application controller) to return the currently logged in user. 95 | # config.current_user_method = :current_admin_user 96 | 97 | # == Logging Out 98 | # 99 | # Active Admin displays a logout link on each screen. These 100 | # settings configure the location and method used for the link. 101 | # 102 | # This setting changes the path where the link points to. If it's 103 | # a string, the strings is used as the path. If it's a Symbol, we 104 | # will call the method to return the path. 105 | # 106 | # Default: 107 | config.logout_link_path = :destroy_admin_user_session_path 108 | 109 | # This setting changes the http method used when rendering the 110 | # link. For example :get, :delete, :put, etc.. 111 | # 112 | # Default: 113 | # config.logout_link_method = :get 114 | 115 | # == Root 116 | # 117 | # Set the action to call for the root path. You can set different 118 | # roots for each namespace. 119 | # 120 | # Default: 121 | # config.root_to = 'dashboard#index' 122 | 123 | # == Admin Comments 124 | # 125 | # This allows your users to comment on any resource registered with Active Admin. 126 | # 127 | # You can completely disable comments: 128 | # config.comments = false 129 | # 130 | # You can change the name under which comments are registered: 131 | # config.comments_registration_name = 'AdminComment' 132 | # 133 | # You can change the order for the comments and you can change the column 134 | # to be used for ordering: 135 | # config.comments_order = 'created_at ASC' 136 | # 137 | # You can disable the menu item for the comments index page: 138 | # config.comments_menu = false 139 | # 140 | # You can customize the comment menu: 141 | # config.comments_menu = { parent: 'Admin', priority: 1 } 142 | 143 | # == Batch Actions 144 | # 145 | # Enable and disable Batch Actions 146 | # 147 | config.batch_actions = true 148 | 149 | # == Controller Filters 150 | # 151 | # You can add before, after and around filters to all of your 152 | # Active Admin resources and pages from here. 153 | # 154 | # config.before_action :do_something_awesome 155 | 156 | # == Attribute Filters 157 | # 158 | # You can exclude possibly sensitive model attributes from being displayed, 159 | # added to forms, or exported by default by ActiveAdmin 160 | # 161 | config.filter_attributes = [:encrypted_password, :password, :password_confirmation] 162 | 163 | # == Localize Date/Time Format 164 | # 165 | # Set the localize format to display dates and times. 166 | # To understand how to localize your app with I18n, read more at 167 | # https://guides.rubyonrails.org/i18n.html 168 | # 169 | # You can run `bin/rails runner 'puts I18n.t("date.formats")'` to see the 170 | # available formats in your application. 171 | # 172 | config.localize_format = :long 173 | 174 | # == Setting a Favicon 175 | # 176 | # config.favicon = 'favicon.ico' 177 | 178 | # == Meta Tags 179 | # 180 | # Add additional meta tags to the head element of active admin pages. 181 | # 182 | # Add tags to all pages logged in users see: 183 | # config.meta_tags = { author: 'My Company' } 184 | 185 | # By default, sign up/sign in/recover password pages are excluded 186 | # from showing up in search engine results by adding a robots meta 187 | # tag. You can reset the hash of meta tags included in logged out 188 | # pages: 189 | # config.meta_tags_for_logged_out_pages = {} 190 | 191 | # == Removing Breadcrumbs 192 | # 193 | # Breadcrumbs are enabled by default. You can customize them for individual 194 | # resources or you can disable them globally from here. 195 | # 196 | # config.breadcrumb = false 197 | 198 | # == Create Another Checkbox 199 | # 200 | # Create another checkbox is disabled by default. You can customize it for individual 201 | # resources or you can enable them globally from here. 202 | # 203 | # config.create_another = true 204 | 205 | # == Register Stylesheets & Javascripts 206 | # 207 | # We recommend using the built in Active Admin layout and loading 208 | # up your own stylesheets / javascripts to customize the look 209 | # and feel. 210 | # 211 | # To load a stylesheet: 212 | # config.register_stylesheet 'my_stylesheet.css' 213 | # 214 | # You can provide an options hash for more control, which is passed along to stylesheet_link_tag(): 215 | # config.register_stylesheet 'my_print_stylesheet.css', media: :print 216 | # 217 | # To load a javascript file: 218 | # config.register_javascript 'my_javascript.js' 219 | 220 | # == CSV options 221 | # 222 | # Set the CSV builder separator 223 | # config.csv_options = { col_sep: ';' } 224 | # 225 | # Force the use of quotes 226 | # config.csv_options = { force_quotes: true } 227 | 228 | # == Menu System 229 | # 230 | # You can add a navigation menu to be used in your application, or configure a provided menu 231 | # 232 | # To change the default utility navigation to show a link to your website & a logout btn 233 | # 234 | # config.namespace :admin do |admin| 235 | # admin.build_menu :utility_navigation do |menu| 236 | # menu.add label: "My Great Website", url: "http://www.mygreatwebsite.com", html_options: { target: :blank } 237 | # admin.add_logout_button_to_menu menu 238 | # end 239 | # end 240 | # 241 | # If you wanted to add a static menu item to the default menu provided: 242 | # 243 | # config.namespace :admin do |admin| 244 | # admin.build_menu :default do |menu| 245 | # menu.add label: "My Great Website", url: "http://www.mygreatwebsite.com", html_options: { target: :blank } 246 | # end 247 | # end 248 | 249 | # == Download Links 250 | # 251 | # You can disable download links on resource listing pages, 252 | # or customize the formats shown per namespace/globally 253 | # 254 | # To disable/customize for the :admin namespace: 255 | # 256 | # config.namespace :admin do |admin| 257 | # 258 | # # Disable the links entirely 259 | # admin.download_links = false 260 | # 261 | # # Only show XML & PDF options 262 | # admin.download_links = [:xml, :pdf] 263 | # 264 | # # Enable/disable the links based on block 265 | # # (for example, with cancan) 266 | # admin.download_links = proc { can?(:view_download_links) } 267 | # 268 | # end 269 | 270 | # == Pagination 271 | # 272 | # Pagination is enabled by default for all resources. 273 | # You can control the default per page count for all resources here. 274 | # 275 | # config.default_per_page = 30 276 | # 277 | # You can control the max per page count too. 278 | # 279 | # config.max_per_page = 10_000 280 | 281 | # == Filters 282 | # 283 | # By default the index screen includes a "Filters" sidebar on the right 284 | # hand side with a filter for each attribute of the registered model. 285 | # You can enable or disable them for all resources here. 286 | # 287 | # config.filters = true 288 | # 289 | # By default the filters include associations in a select, which means 290 | # that every record will be loaded for each association (up 291 | # to the value of config.maximum_association_filter_arity). 292 | # You can enabled or disable the inclusion 293 | # of those filters by default here. 294 | # 295 | # config.include_default_association_filters = true 296 | 297 | # config.maximum_association_filter_arity = 256 # default value of :unlimited will change to 256 in a future version 298 | # config.filter_columns_for_large_association = [ 299 | # :display_name, 300 | # :full_name, 301 | # :name, 302 | # :username, 303 | # :login, 304 | # :title, 305 | # :email, 306 | # ] 307 | # config.filter_method_for_large_association = '_starts_with' 308 | 309 | # == Head 310 | # 311 | # You can add your own content to the site head like analytics. Make sure 312 | # you only pass content you trust. 313 | # 314 | # config.head = ''.html_safe 315 | 316 | # == Footer 317 | # 318 | # By default, the footer shows the current Active Admin version. You can 319 | # override the content of the footer here. 320 | # 321 | # config.footer = 'my custom footer text' 322 | 323 | # == Sorting 324 | # 325 | # By default ActiveAdmin::OrderClause is used for sorting logic 326 | # You can inherit it with own class and inject it for all resources 327 | # 328 | # config.order_clause = MyOrderClause 329 | 330 | # == Webpacker 331 | # 332 | # By default, Active Admin uses Sprocket's asset pipeline. 333 | # You can switch to using Webpacker here. 334 | # 335 | # config.use_webpacker = true 336 | end if Object.const_defined?('ActiveAdmin') 337 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | actioncable (7.0.4.2) 5 | actionpack (= 7.0.4.2) 6 | activesupport (= 7.0.4.2) 7 | nio4r (~> 2.0) 8 | websocket-driver (>= 0.6.1) 9 | actionmailbox (7.0.4.2) 10 | actionpack (= 7.0.4.2) 11 | activejob (= 7.0.4.2) 12 | activerecord (= 7.0.4.2) 13 | activestorage (= 7.0.4.2) 14 | activesupport (= 7.0.4.2) 15 | mail (>= 2.7.1) 16 | net-imap 17 | net-pop 18 | net-smtp 19 | actionmailer (7.0.4.2) 20 | actionpack (= 7.0.4.2) 21 | actionview (= 7.0.4.2) 22 | activejob (= 7.0.4.2) 23 | activesupport (= 7.0.4.2) 24 | mail (~> 2.5, >= 2.5.4) 25 | net-imap 26 | net-pop 27 | net-smtp 28 | rails-dom-testing (~> 2.0) 29 | actionpack (7.0.4.2) 30 | actionview (= 7.0.4.2) 31 | activesupport (= 7.0.4.2) 32 | rack (~> 2.0, >= 2.2.0) 33 | rack-test (>= 0.6.3) 34 | rails-dom-testing (~> 2.0) 35 | rails-html-sanitizer (~> 1.0, >= 1.2.0) 36 | actiontext (7.0.4.2) 37 | actionpack (= 7.0.4.2) 38 | activerecord (= 7.0.4.2) 39 | activestorage (= 7.0.4.2) 40 | activesupport (= 7.0.4.2) 41 | globalid (>= 0.6.0) 42 | nokogiri (>= 1.8.5) 43 | actionview (7.0.4.2) 44 | activesupport (= 7.0.4.2) 45 | builder (~> 3.1) 46 | erubi (~> 1.4) 47 | rails-dom-testing (~> 2.0) 48 | rails-html-sanitizer (~> 1.1, >= 1.2.0) 49 | active_link_to (1.0.5) 50 | actionpack 51 | addressable 52 | activeadmin (2.13.1) 53 | arbre (~> 1.2, >= 1.2.1) 54 | formtastic (>= 3.1, < 5.0) 55 | formtastic_i18n (~> 0.4) 56 | inherited_resources (~> 1.7) 57 | jquery-rails (~> 4.2) 58 | kaminari (~> 1.0, >= 1.2.1) 59 | railties (>= 6.1, < 7.1) 60 | ransack (>= 2.1.1, < 4) 61 | activejob (7.0.4.2) 62 | activesupport (= 7.0.4.2) 63 | globalid (>= 0.3.6) 64 | activemodel (7.0.4.2) 65 | activesupport (= 7.0.4.2) 66 | activemodel-serializers-xml (1.0.2) 67 | activemodel (> 5.x) 68 | activesupport (> 5.x) 69 | builder (~> 3.1) 70 | activerecord (7.0.4.2) 71 | activemodel (= 7.0.4.2) 72 | activesupport (= 7.0.4.2) 73 | activestorage (7.0.4.2) 74 | actionpack (= 7.0.4.2) 75 | activejob (= 7.0.4.2) 76 | activerecord (= 7.0.4.2) 77 | activesupport (= 7.0.4.2) 78 | marcel (~> 1.0) 79 | mini_mime (>= 1.1.0) 80 | activesupport (7.0.4.2) 81 | concurrent-ruby (~> 1.0, >= 1.0.2) 82 | i18n (>= 1.6, < 2) 83 | minitest (>= 5.1) 84 | tzinfo (~> 2.0) 85 | addressable (2.8.1) 86 | public_suffix (>= 2.0.2, < 6.0) 87 | aes_key_wrap (1.1.0) 88 | ancestry (4.2.0) 89 | activerecord (>= 5.2.6) 90 | ar_lazy_preload (1.1.2) 91 | rails (>= 5.2) 92 | arbre (1.5.0) 93 | activesupport (>= 3.0.0, < 7.1) 94 | ruby2_keywords (>= 0.0.2, < 1.0) 95 | arel-helpers (2.14.0) 96 | activerecord (>= 3.1.0, < 8) 97 | attr_json (2.0.1) 98 | activerecord (>= 6.0.0, < 7.1) 99 | attr_required (1.0.1) 100 | audited (5.3.2) 101 | activerecord (>= 5.0, < 7.1) 102 | avo (2.27.1) 103 | actionview (>= 6.0) 104 | active_link_to 105 | activerecord (>= 6.0) 106 | addressable 107 | docile 108 | dry-initializer 109 | httparty 110 | inline_svg 111 | meta-tags 112 | pagy 113 | turbo-rails 114 | view_component 115 | zeitwerk (>= 2.6.2) 116 | babosa (2.0.0) 117 | bcrypt (3.1.18) 118 | bindata (2.4.15) 119 | bindex (0.8.1) 120 | bootsnap (1.16.0) 121 | msgpack (~> 1.2) 122 | breadcrumbs_on_rails (4.1.0) 123 | railties (>= 5.0) 124 | brick (1.0.120) 125 | activerecord (>= 3.0) 126 | fancy_gets 127 | browser (5.3.1) 128 | builder (3.2.4) 129 | byebug (11.1.3) 130 | cancancan (3.4.0) 131 | capybara (3.38.0) 132 | addressable 133 | matrix 134 | mini_mime (>= 0.1.3) 135 | nokogiri (~> 1.8) 136 | rack (>= 1.6.0) 137 | rack-test (>= 0.6.3) 138 | regexp_parser (>= 1.5, < 3.0) 139 | xpath (~> 3.2) 140 | coderay (1.1.3) 141 | composite_primary_keys (14.0.6) 142 | activerecord (~> 7.0.2) 143 | concurrent-ruby (1.2.2) 144 | country-select (1.2.1) 145 | crass (1.0.6) 146 | date (3.3.3) 147 | docile (1.4.0) 148 | dry-initializer (3.1.1) 149 | duty_free (1.0.9) 150 | activerecord (>= 3.0) 151 | erubi (1.12.0) 152 | et-orbi (1.2.7) 153 | tzinfo 154 | fancy_gets (0.1.10) 155 | ffi (1.15.5) 156 | forest_liana (7.8.0) 157 | arel-helpers 158 | bcrypt 159 | forestadmin-jsonapi-serializers (>= 0.14.0) 160 | groupdate (>= 5.0.0) 161 | httparty 162 | ipaddress 163 | json 164 | json-jwt (~> 1.15.0) 165 | jwt 166 | openid_connect (= 1.4.2) 167 | rack-cors 168 | rails (>= 4.0) 169 | useragent 170 | forestadmin-jsonapi-serializers (2.0.0.pre.beta.2) 171 | activesupport 172 | formtastic (4.0.0) 173 | actionpack (>= 5.2.0) 174 | formtastic_i18n (0.7.0) 175 | fugit (1.8.1) 176 | et-orbi (~> 1, >= 1.2.7) 177 | raabro (~> 1.4) 178 | globalid (1.1.0) 179 | activesupport (>= 5.0) 180 | groupdate (6.2.0) 181 | activesupport (>= 5.2) 182 | has_scope (0.8.1) 183 | actionpack (>= 5.2) 184 | activesupport (>= 5.2) 185 | httparty (0.21.0) 186 | mini_mime (>= 1.0.0) 187 | multi_xml (>= 0.5.2) 188 | httpclient (2.8.3) 189 | i18n (1.12.0) 190 | concurrent-ruby (~> 1.0) 191 | image_processing (1.12.2) 192 | mini_magick (>= 4.9.5, < 5) 193 | ruby-vips (>= 2.0.17, < 3) 194 | importmap-rails (1.1.5) 195 | actionpack (>= 6.0.0) 196 | railties (>= 6.0.0) 197 | inherited_resources (1.13.1) 198 | actionpack (>= 5.2, < 7.1) 199 | has_scope (~> 0.6) 200 | railties (>= 5.2, < 7.1) 201 | responders (>= 2, < 4) 202 | inline_svg (1.8.0) 203 | activesupport (>= 3.0) 204 | nokogiri (>= 1.6) 205 | ipaddress (0.8.3) 206 | jbuilder (2.11.5) 207 | actionview (>= 5.0.0) 208 | activesupport (>= 5.0.0) 209 | jquery-rails (4.5.1) 210 | rails-dom-testing (>= 1, < 3) 211 | railties (>= 4.2.0) 212 | thor (>= 0.14, < 2.0) 213 | json (2.6.3) 214 | json-jwt (1.15.3) 215 | activesupport (>= 4.2) 216 | aes_key_wrap 217 | bindata 218 | httpclient 219 | jsonapi-serializer (2.2.0) 220 | activesupport (>= 4.2) 221 | jwt (2.7.0) 222 | kaminari (1.2.2) 223 | activesupport (>= 4.1.0) 224 | kaminari-actionview (= 1.2.2) 225 | kaminari-activerecord (= 1.2.2) 226 | kaminari-core (= 1.2.2) 227 | kaminari-actionview (1.2.2) 228 | actionview 229 | kaminari-core (= 1.2.2) 230 | kaminari-activerecord (1.2.2) 231 | activerecord 232 | kaminari-core (= 1.2.2) 233 | kaminari-core (1.2.2) 234 | loofah (2.19.1) 235 | crass (~> 1.0.2) 236 | nokogiri (>= 1.5.9) 237 | mail (2.8.1) 238 | mini_mime (>= 0.1.1) 239 | net-imap 240 | net-pop 241 | net-smtp 242 | marcel (1.0.2) 243 | matrix (0.4.2) 244 | meta-tags (2.18.0) 245 | actionpack (>= 3.2.0, < 7.1) 246 | method_source (1.0.0) 247 | mini_magick (4.12.0) 248 | mini_mime (1.1.2) 249 | minitest (5.17.0) 250 | mobility (1.2.9) 251 | i18n (>= 0.6.10, < 2) 252 | request_store (~> 1.0) 253 | motor-admin (0.4.7) 254 | ar_lazy_preload (~> 1.0) 255 | audited (~> 5.0) 256 | cancancan (~> 3.0) 257 | fugit (~> 1.0) 258 | rails (>= 5.2) 259 | msgpack (1.6.0) 260 | multi_xml (0.6.0) 261 | nested_form (0.3.2) 262 | net-imap (0.3.4) 263 | date 264 | net-protocol 265 | net-pop (0.1.2) 266 | net-protocol 267 | net-protocol (0.2.1) 268 | timeout 269 | net-smtp (0.3.3) 270 | net-protocol 271 | nio4r (2.5.8) 272 | nokogiri (1.14.2-arm64-darwin) 273 | racc (~> 1.4) 274 | nokogiri (1.14.2-x86_64-linux) 275 | racc (~> 1.4) 276 | openid_connect (1.4.2) 277 | activemodel 278 | attr_required (>= 1.0.0) 279 | json-jwt (>= 1.15.0) 280 | net-smtp 281 | rack-oauth2 (~> 1.21) 282 | swd (~> 1.3) 283 | tzinfo 284 | validate_email 285 | validate_url 286 | webfinger (~> 1.2) 287 | pagy (6.0.2) 288 | pg (1.4.5) 289 | pry (0.14.2) 290 | coderay (~> 1.1) 291 | method_source (~> 1.0) 292 | pry-byebug (3.10.1) 293 | byebug (~> 11.0) 294 | pry (>= 0.13, < 0.15) 295 | public_suffix (5.0.1) 296 | puma (5.6.5) 297 | nio4r (~> 2.0) 298 | raabro (1.4.0) 299 | racc (1.6.2) 300 | rack (2.2.6.2) 301 | rack-cors (2.0.0) 302 | rack (>= 2.0.0) 303 | rack-oauth2 (1.21.3) 304 | activesupport 305 | attr_required 306 | httpclient 307 | json-jwt (>= 1.11.0) 308 | rack (>= 2.1.0) 309 | rack-rewrite (1.5.1) 310 | rack-test (2.0.2) 311 | rack (>= 1.3) 312 | rails (7.0.4.2) 313 | actioncable (= 7.0.4.2) 314 | actionmailbox (= 7.0.4.2) 315 | actionmailer (= 7.0.4.2) 316 | actionpack (= 7.0.4.2) 317 | actiontext (= 7.0.4.2) 318 | actionview (= 7.0.4.2) 319 | activejob (= 7.0.4.2) 320 | activemodel (= 7.0.4.2) 321 | activerecord (= 7.0.4.2) 322 | activestorage (= 7.0.4.2) 323 | activesupport (= 7.0.4.2) 324 | bundler (>= 1.15.0) 325 | railties (= 7.0.4.2) 326 | rails-dom-testing (2.0.3) 327 | activesupport (>= 4.2.0) 328 | nokogiri (>= 1.6) 329 | rails-html-sanitizer (1.5.0) 330 | loofah (~> 2.19, >= 2.19.1) 331 | rails_admin (3.1.1) 332 | activemodel-serializers-xml (>= 1.0) 333 | kaminari (>= 0.14, < 2.0) 334 | nested_form (~> 0.3) 335 | rails (>= 6.0, < 8) 336 | turbo-rails (~> 1.0) 337 | railties (7.0.4.2) 338 | actionpack (= 7.0.4.2) 339 | activesupport (= 7.0.4.2) 340 | method_source 341 | rake (>= 12.2) 342 | thor (~> 1.0) 343 | zeitwerk (~> 2.5) 344 | rake (13.0.6) 345 | ransack (3.2.1) 346 | activerecord (>= 6.1.5) 347 | activesupport (>= 6.1.5) 348 | i18n 349 | regexp_parser (2.7.0) 350 | request_store (1.5.1) 351 | rack (>= 1.4) 352 | responders (3.1.0) 353 | actionpack (>= 5.2) 354 | railties (>= 5.2) 355 | rexml (3.2.5) 356 | rgeo (3.0.0) 357 | rswag-ui (2.8.0) 358 | actionpack (>= 3.1, < 7.1) 359 | railties (>= 3.1, < 7.1) 360 | ruby-vips (2.1.4) 361 | ffi (~> 1.12) 362 | ruby2_keywords (0.0.5) 363 | rubyzip (2.3.2) 364 | sassc (2.4.0) 365 | ffi (~> 1.9) 366 | selenium-webdriver (4.8.1) 367 | rexml (~> 3.2, >= 3.2.5) 368 | rubyzip (>= 1.2.2, < 3.0) 369 | websocket (~> 1.0) 370 | spina (2.14.0) 371 | ancestry 372 | attr_json 373 | babosa 374 | bcrypt 375 | breadcrumbs_on_rails 376 | browser 377 | image_processing 378 | importmap-rails (>= 0.7.6) 379 | jsonapi-serializer 380 | kaminari 381 | mobility (>= 1.1.3) 382 | pg 383 | rack-rewrite (>= 1.5.0) 384 | rails (>= 6.0) 385 | sprockets-rails 386 | stimulus-rails (>= 0.7.0) 387 | tailwindcss-rails (>= 2.0.0) 388 | turbo-rails (>= 0.9, < 2.0) 389 | view_component (~> 2.32) 390 | sprockets (4.2.0) 391 | concurrent-ruby (~> 1.0) 392 | rack (>= 2.2.4, < 4) 393 | sprockets-rails (3.4.2) 394 | actionpack (>= 5.2) 395 | activesupport (>= 5.2) 396 | sprockets (>= 3.0.0) 397 | stimulus-rails (1.2.1) 398 | railties (>= 6.0.0) 399 | swd (1.3.0) 400 | activesupport (>= 3) 401 | attr_required (>= 0.0.5) 402 | httpclient (>= 2.4) 403 | tailwindcss-rails (2.0.23-arm64-darwin) 404 | railties (>= 6.0.0) 405 | thor (1.2.1) 406 | timeout (0.3.2) 407 | trestle (0.9.7) 408 | activemodel (>= 4.2.0) 409 | kaminari (>= 1.1.0) 410 | railties (>= 4.2.0) 411 | sprockets-rails (>= 2.0.0) 412 | turbo-rails (1.3.3) 413 | actionpack (>= 6.0.0) 414 | activejob (>= 6.0.0) 415 | railties (>= 6.0.0) 416 | tzinfo (2.0.6) 417 | concurrent-ruby (~> 1.0) 418 | useragent (0.16.10) 419 | validate_email (0.1.6) 420 | activemodel (>= 3.0) 421 | mail (>= 2.2.5) 422 | validate_url (1.0.15) 423 | activemodel (>= 3.0.0) 424 | public_suffix 425 | view_component (2.82.0) 426 | activesupport (>= 5.2.0, < 8.0) 427 | concurrent-ruby (~> 1.0) 428 | method_source (~> 1.0) 429 | web-console (4.2.0) 430 | actionview (>= 6.0.0) 431 | activemodel (>= 6.0.0) 432 | bindex (>= 0.4.0) 433 | railties (>= 6.0.0) 434 | webdrivers (5.2.0) 435 | nokogiri (~> 1.6) 436 | rubyzip (>= 1.3.0) 437 | selenium-webdriver (~> 4.0) 438 | webfinger (1.2.0) 439 | activesupport 440 | httpclient (>= 2.4) 441 | websocket (1.2.9) 442 | websocket-driver (0.7.5) 443 | websocket-extensions (>= 0.1.0) 444 | websocket-extensions (0.1.5) 445 | xpath (3.2.0) 446 | nokogiri (~> 1.8) 447 | zeitwerk (2.6.7) 448 | 449 | PLATFORMS 450 | arm64-darwin-22 451 | x86_64-linux 452 | 453 | DEPENDENCIES 454 | activeadmin 455 | avo 456 | bootsnap 457 | brick 458 | capybara 459 | composite_primary_keys 460 | country-select 461 | duty_free 462 | forest_liana (~> 7) 463 | importmap-rails 464 | jbuilder 465 | motor-admin 466 | pg (~> 1.1) 467 | pry-byebug 468 | puma (~> 5.0) 469 | rails (~> 7.0.4, >= 7.0.4.2) 470 | rails_admin 471 | ransack 472 | rgeo 473 | rswag-ui 474 | sassc 475 | selenium-webdriver 476 | spina 477 | sprockets-rails 478 | stimulus-rails 479 | trestle 480 | turbo-rails 481 | tzinfo-data 482 | web-console 483 | webdrivers 484 | 485 | RUBY VERSION 486 | ruby 3.2.0p0 487 | 488 | BUNDLED WITH 489 | 2.4.7 490 | -------------------------------------------------------------------------------- /config/initializers/brick.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Settings for the Brick gem 4 | # (By default this auto-creates models, controllers, views, and routes on-the-fly.) 5 | 6 | if ActiveRecord::Base.respond_to?(:brick_select) && !::Brick.initializer_loaded 7 | # Mode -- generally :on or :off, or only in :development. Also available is :diag_env which enables only 8 | # when the environment variable BRICK is set. 9 | Brick.mode = :development 10 | # Can be further overridden by placing this line in development.rb / test.rb / production.rb: 11 | # # Brick.mode = :on # (or :off to entirely disable) 12 | 13 | # Custom path prefix to apply to all auto-generated Brick routes. Also causes auto-generated controllers 14 | # to be created inside a module with the same name. 15 | ::Brick.path_prefix = 'brick' 16 | 17 | # # Normally all are enabled in development mode, and for security reasons only models are enabled in production 18 | # # and test. This allows you to either (a) turn off models entirely, or (b) enable controllers, views, and routes 19 | # # in production. 20 | # Brick.enable_routes = true # Setting this to "false" will disable routes in development 21 | # Brick.enable_models = false 22 | # Brick.enable_controllers = true # Setting this to "false" will disable controllers in development 23 | # Brick.enable_views = true # Setting this to "false" will disable views in development 24 | 25 | # If The Brick sees that RSwag gem is present, it allows for API resources to be automatically served out. 26 | # You can configure one or more root path(s) for these resources, and when there are multiple then an attempt 27 | # is made to return data from that version of the view or table name, or the most recent prior to that version: 28 | ::Brick.api_roots = ['/api/v1/'] 29 | # # You may also want to add an OpenAPI 3.0 documentation endpoint using Rswag::Ui: 30 | Rswag::Ui.configure do |config| 31 | config.swagger_endpoint '/api-docs/v1/swagger.json', 'API V1 Docs' 32 | end 33 | 34 | # # By default models are auto-created for database views, and set to be read-only. This can be skipped. 35 | # Brick.skip_database_views = true 36 | 37 | # # Any tables or views you'd like to skip when auto-creating models 38 | # Brick.exclude_tables = ['custom_metadata', 'version_info'] 39 | 40 | # # Class that auto-generated models should inherit from 41 | # Brick.models_inherit_from = ApplicationRecord 42 | 43 | # # When table names have specific prefixes automatically place them in their own module with a table_name_prefix. 44 | # Brick.table_name_prefixes = { 'nav_' => 'Navigation' } 45 | 46 | # # COLUMN SEQUENCING AND INCLUSION / EXCLUSION 47 | 48 | # # By default if there is a primary key present then rows in an index view are ordered by this primary key. To 49 | # # use a different rule for doing ORDER BY, you can override this default ordering done by The Brick, for instance 50 | # # to have the rows in a contact list sorted by email: 51 | # Brick.order = { 'contacts' => { _brick_default: :email } } 52 | # # or by last name then first name: 53 | # Brick.order = { 'contacts' => { _brick_default: [:lastname, :firstname] } } 54 | # # Totally legitimate to have the default order be the name of a belongs_to or has_many association instead of an 55 | # # actual column name, in which case for has_many it just orders by the count of how many records are associated, 56 | # # and for belongs_to it's based on the primary table's DSL if any is defined (since that is what is used to 57 | # # calculate what is shown when a foreign table lists out related records). If contacts relates to addresses, 58 | # # then this is perfectly fine: 59 | # Brick.order = { 'contacts' => { _brick_default: :address } } 60 | # # You can even have a specific custom clause used in the ORDER BY. In this case it is recommended to include a 61 | # # special placeholder for the table name with the sequence "^^^". Here is an example of having the default 62 | # # ordering happening on the "code" column, and also defining custom sorting to be done, in this case proper 63 | # # ordering if that code is stored as a dotted numeric value: 64 | # Brick.order = { 'document_trees' => { _brick_default: :code, 65 | # code: "ORDER BY STRING_TO_ARRAY(^^^.code, '.')::int[]" } } 66 | 67 | # # Sequence of columns for each model. This also allows you to add read-only calculated columns in the same 68 | # # kind of way that they can be added in the include: portion of include/exclude columns, below. 69 | # # Designated by { => [, ] } 70 | # Brick.column_sequence = { 'users' => ['email', 'profile.firstname', 'profile.lastname'] } 71 | 72 | # # Specific columns to include or exclude for each model. If there are only inclusions then only those 73 | # # columns show. If there are any exclusions then all non-excluded columns are attempted to be shown, 74 | # # which negates the usefulness of inclusions except to add calculated column detail built from DSL. 75 | # # Designated by
. 76 | # Brick.column_sequence = { 'users' => { include: ['email', 'profile.firstname', 'profile.lastname'] }, 77 | # 'profile' => { exclude: ['birthdate'] } } 78 | 79 | # # EXTRA FOREIGN KEYS AND OTHER HAS_MANY SETTINGS 80 | 81 | # # Additional table references which are used to create has_many / belongs_to associations inside auto-created 82 | # # models. (You can consider these to be "virtual foreign keys" if you wish)... You only have to add these 83 | # # in cases where your database for some reason does not have foreign key constraints defined. Sometimes for 84 | # # performance reasons or just out of sheer laziness these might be missing. 85 | # # Each of these virtual foreign keys is defined as an array having three values: 86 | # # foreign table name / foreign key column / primary table name. 87 | # # (We boldly expect that the primary key identified by ActiveRecord on the primary table will be accurate, 88 | # # usually this is "id" but there are some good smarts that are used in case some other column has been set 89 | # # to be the primary key.) 90 | # Brick.additional_references = [['orders', 'customer_id', 'customer'], 91 | # ['customer', 'region_id', 'regions']] 92 | Brick.additional_references = [['employees', 'reports_to_id', 'employees']] 93 | # # Columns named somewhat like a foreign key which you may want to consider: 94 | # # hr.d.departmentid, hr.e.businessentityid, hr.e.loginid, hr.e.rowguid, hr.edh.businessentityid, hr.edh.shiftid, hr.edh.departmentid, hr.eph.businessentityid, hr.jc.jobcandidateid, hr.jc.businessentityid, hr.s.shiftid, humanresources.vemployee.businessentityid, humanresources.vemployeedepartment.businessentityid, humanresources.vemployeedepartmenthistory.businessentityid, humanresources.vjobcandidate.jobcandidateid, humanresources.vjobcandidate.businessentityid, humanresources.vjobcandidateeducation.jobcandidateid, humanresources.vjobcandidateemployment.jobcandidateid, humanresources.employee.loginid, humanresources.employee.rowguid, pe.a.rowguid, pe.a.addressid, pe.a.stateprovinceid, pe.at.addresstypeid, pe.at.rowguid, pe.be.rowguid, pe.be.businessentityid, pe.bea.addresstypeid, pe.bea.rowguid, pe.bea.addressid, pe.bea.businessentityid, pe.bec.rowguid, pe.bec.contacttypeid, pe.bec.personid, pe.bec.businessentityid, pe.ct.contacttypeid, pe.e.businessentityid, pe.e.emailaddressid, pe.e.rowguid, pe.p.businessentityid, pe.p.rowguid, pe.pa.rowguid, pe.pa.businessentityid, pe.pnt.phonenumbertypeid, pe.pp.phonenumbertypeid, pe.pp.businessentityid, pe.sp.territoryid, pe.sp.stateprovinceid, pe.sp.rowguid, person.vadditionalcontactinfo.businessentityid, person.vadditionalcontactinfo.rowguid, person.address.rowguid, person.addresstype.rowguid, person.businessentity.rowguid, person.businessentityaddress.rowguid, person.businessentitycontact.rowguid, person.emailaddress.rowguid, person.password.rowguid, person.person.rowguid, person.stateprovince.rowguid, pr.bom.billofmaterialsid, pr.bom.productassemblyid, pr.bom.componentid, pr.c.cultureid, pr.d.rowguid, pr.i.illustrationid, pr.l.locationid, pr.p.productid, pr.p.productsubcategoryid, pr.p.productmodelid, pr.p.rowguid, pr.pc.rowguid, pr.pc.productcategoryid, pr.pch.productid, pr.pd.rowguid, pr.pd.productdescriptionid, pr.pdoc.productid, pr.pi.productid, pr.pi.locationid, pr.pi.rowguid, pr.plph.productid, pr.pm.rowguid, pr.pm.productmodelid, pr.pmi.illustrationid, pr.pmi.productmodelid, pr.pmpdc.cultureid, pr.pmpdc.productdescriptionid, pr.pmpdc.productmodelid, pr.pp.productphotoid, pr.ppp.productid, pr.ppp.productphotoid, pr.pr.productreviewid, pr.pr.productid, pr.psc.rowguid, pr.psc.productsubcategoryid, pr.psc.productcategoryid, pr.sr.scrapreasonid, pr.th.productid, pr.th.referenceorderlineid, pr.th.referenceorderid, pr.th.transactionid, pr.tha.referenceorderlineid, pr.tha.referenceorderid, pr.tha.productid, pr.tha.transactionid, pr.w.productid, pr.w.scrapreasonid, pr.w.workorderid, pr.wr.locationid, pr.wr.workorderid, pr.wr.productid, production.vproductmodelcatalogdescription.productmodelid, production.vproductmodelcatalogdescription.rowguid, production.vproductmodelcatalogdescription.productphotoid, production.vproductmodelinstructions.LocationID, production.vproductmodelinstructions.rowguid, production.vproductmodelinstructions.productmodelid, production.document.rowguid, production.product.rowguid, production.productcategory.rowguid, production.productdescription.rowguid, production.productinventory.rowguid, production.productmodel.rowguid, production.productsubcategory.rowguid, production.transactionhistory.referenceorderlineid, production.transactionhistory.referenceorderid, production.transactionhistoryarchive.productid, production.transactionhistoryarchive.referenceorderid, production.transactionhistoryarchive.referenceorderlineid, pu.pod.productid, pu.pod.purchaseorderdetailid, pu.pod.purchaseorderid, pu.poh.purchaseorderid, pu.poh.employeeid, pu.poh.vendorid, pu.poh.shipmethodid, pu.pv.productid, pu.pv.businessentityid, pu.sm.shipmethodid, pu.sm.rowguid, pu.v.businessentityid, purchasing.vvendorwithaddresses.businessentityid, purchasing.vvendorwithcontacts.businessentityid, purchasing.shipmethod.rowguid, sa.c.customerid, sa.c.personid, sa.c.rowguid, sa.c.territoryid, sa.c.storeid, sa.cc.creditcardid, sa.cr.currencyrateid, sa.pcc.businessentityid, sa.pcc.creditcardid, sa.s.businessentityid, sa.s.salespersonid, sa.s.rowguid, sa.sci.productid, sa.sci.shoppingcartid, sa.sci.shoppingcartitemid, sa.so.rowguid, sa.so.specialofferid, sa.sod.specialofferid, sa.sod.rowguid, sa.sod.salesorderid, sa.sod.salesorderdetailid, sa.sod.productid, sa.soh.shipmethodid, sa.soh.shiptoaddressid, sa.soh.billtoaddressid, sa.soh.territoryid, sa.soh.salespersonid, sa.soh.customerid, sa.soh.creditcardid, sa.soh.salesorderid, sa.soh.rowguid, sa.soh.currencyrateid, sa.sohsr.salesorderid, sa.sohsr.salesreasonid, sa.sop.specialofferid, sa.sop.productid, sa.sop.rowguid, sa.sp.rowguid, sa.sp.territoryid, sa.sp.businessentityid, sa.spqh.rowguid, sa.spqh.businessentityid, sa.sr.salesreasonid, sa.st.rowguid, sa.st.territoryid, sa.sth.businessentityid, sa.sth.territoryid, sa.sth.rowguid, sa.tr.salestaxrateid, sa.tr.stateprovinceid, sa.tr.rowguid, sales.vindividualcustomer.businessentityid, sales.vpersondemographics.businessentityid, sales.vsalesperson.businessentityid, sales.vsalespersonsalesbyfiscalyears.SalesPersonID, sales.vsalespersonsalesbyfiscalyearsdata.salespersonid, sales.vstorewithaddresses.businessentityid, sales.vstorewithcontacts.businessentityid, sales.vstorewithdemographics.businessentityid, sales.customer.rowguid, sales.salesorderdetail.rowguid, sales.salesorderdetail.productid, sales.salesorderdetail.specialofferid, sales.salesorderheader.rowguid, sales.salesperson.rowguid, sales.salespersonquotahistory.rowguid, sales.salestaxrate.rowguid, sales.salesterritory.rowguid, sales.salesterritoryhistory.rowguid, sales.shoppingcartitem.shoppingcartid, sales.specialoffer.rowguid, sales.specialofferproduct.rowguid, sales.store.rowguid 95 | 96 | # # Custom columns to add to a table, minimally defined with a name and DSL string. 97 | # Brick.custom_columns = { 'users' => { messages: ['[COUNT(messages)] messages', 'messages'] }, 98 | # 'orders' => { salesperson: '[salesperson.first] [salesperson.last]', 99 | # products: ['[COUNT(order_items.product)] products', 'order_items.product' ] } 100 | # } 101 | 102 | # # Skip creating a has_many association for these (only retain the belongs_to built from this additional_reference). 103 | # # (Uses the same exact three-part format as would define an additional_reference) 104 | # # Say for instance that we didn't care to display the favourite colours that users have: 105 | # Brick.exclude_hms = [['users', 'favourite_colour_id', 'colours']] 106 | 107 | # # Skip showing counts for these specific has_many associations when building auto-generated #index views. 108 | # # When there are related tables with a significant number of records (generally 100,000 or more), this can lessen 109 | # # the load on the database considerably, sometimes fixing what might appear to be an index page that just "hangs" 110 | # # for no apparent reason. 111 | # Brick.skip_index_hms = ['User.litany_of_woes'] 112 | 113 | # # By default primary tables involved in a foreign key relationship will indicate a "has_many" relationship pointing 114 | # # back to the foreign table. In order to represent a "has_one" association instead, an override can be provided 115 | # # using the primary model name and the association name which you instead want to have treated as a "has_one": 116 | # Brick.has_ones = [['User', 'user_profile']] 117 | # # If you want to use an alternate name for the "has_one", such as in the case above calling the association "profile" 118 | # # instead of "user_profile", then apply that as a third parameter like this: 119 | # Brick.has_ones = [['User', 'user_profile', 'profile']] 120 | 121 | # # We normally don't show the timestamp columns "created_at", "updated_at", and "deleted_at", and also do 122 | # # not consider them when finding associative tables to support an N:M association. (That is, ones that can be a 123 | # # part of a has_many :through association.) If you want to use different exclusion columns than our defaults 124 | # # then this setting resets that list. For instance, here is an override that is useful in the Sakila sample 125 | # # database: 126 | # Brick.metadata_columns = ['last_update'] 127 | 128 | # # Columns for which to add a validate presence: true even though the database doesn't have them marked as NOT NULL. 129 | # # Designated by
. 130 | # Brick.not_nullables = ['users.name'] 131 | 132 | # # String or text columns which for editing purposes should be treated as JSON. 133 | # Brick.json_columns = { 'users' => ['info'] } 134 | 135 | # # FRIENDLY DSL 136 | 137 | # # A simple DSL is available to allow more user-friendly display of objects. Normally a user object might be shown 138 | # # as its first non-metadata column, or if that is not available then something like "User #42" where 42 is that 139 | # # object's ID. If there is no primary key then even that is not possible, so the object's .to_s is called. To 140 | # # override these defaults and specify exactly what you want shown, such as first names and last names for a user, 141 | # # then you can do something like this: 142 | Brick.model_descrips = { 'Order' => '[customer.company_code] ([customer.company_name]), [order_date]', 143 | 'OrderDetail' => '[quantity] [product.product_name] ($[unit_price])' } 144 | 145 | # # SINGLE TABLE INHERITANCE 146 | 147 | # # Specify STI subclasses either directly by name or as a general module prefix that should always relate to a specific 148 | # # parent STI class. The prefixed :: here for these examples is mandatory. Also having a suffixed :: means instead of 149 | # # a class reference, this is for a general namespace reference. So in this case requests for, say, either of the 150 | # # non-existent classes Animals::Cat or Animals::Goat (or anything else with the module prefix of "Animals::" would 151 | # # build a model that inherits from Animal. And a request specifically for the class Snake would build a new model 152 | # # that inherits from Reptile, and no other request would do this -- only specifically for Snake. The ending :: 153 | # # indicates that it's a module prefix instead of a specific class name. 154 | # Brick.sti_namespace_prefixes = { '::Animals::' => 'Animal', 155 | # '::Snake' => 'Reptile' } 156 | 157 | # # Custom inheritance_column to be used for STI. This is by default "type", and applies to all models. With this 158 | # # option you can change this either for specific models, or apply a new overall name generally: 159 | # Brick.sti_type_column = 'sti_type' 160 | # Brick.sti_type_column = { 'rails_type' => ['sales.specialoffer'] } 161 | 162 | # # POLYMORPHIC ASSOCIATIONS 163 | 164 | # # Polymorphic associations are set up by providing a model name and polymorphic association name like this: 165 | # Brick.polymorphics = { 166 | # 'comments.commentable' => nil, 167 | # 'images.imageable' => nil 168 | # } 169 | 170 | # # For multi-tenant databases that use a separate schema for each tenant, a single representative database schema 171 | # # can be analysed to determine the range of polymorphic classes that can be used for each association. Hopefully 172 | # # the schema chosen is one loaded with existing data that is representative of all possible polymorphic 173 | # # associations. 174 | # Brick.schema_behavior = :namespaced 175 | # Brick.schema_behavior = { multitenant: { schema_to_analyse: 'engineering' } } 176 | 177 | # # DEFAULT ROOT ROUTE 178 | 179 | # # If a default route is not supplied, Brick attempts to find the most "central" table and wires up the default 180 | # # route to go to the :index action for what would be a controller for that table. You can specify any controller 181 | # # name and action you wish in order to override this and have that be the default route when none other has been 182 | # # specified in routes.rb or elsewhere. (Or just use an empty string in order to disable this behaviour.) 183 | # This defaults to "customers#index", and if there was also a prefix set called "admin" then it would instead 184 | # go to "admin/customers#index". 185 | # Brick.default_route_fallback = 'customers' 186 | # Brick.default_route_fallback = 'orders#outstanding' # Example of a non-RESTful route 187 | # Brick.default_route_fallback = '' # Omits setting a default route in the absence of any other 188 | end 189 | -------------------------------------------------------------------------------- /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 | # This file is the source Rails uses to define your schema when running `bin/rails 6 | # db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to 7 | # be faster and is potentially less error prone than running all of your 8 | # migrations from scratch. Old migrations may fail to apply correctly if those 9 | # migrations use external dependencies or application code. 10 | # 11 | # It's strongly recommended that you check this file into your version control system. 12 | 13 | ActiveRecord::Schema[7.0].define(version: 2023_03_02_064251) do 14 | # These are extensions that must be enabled in order to support this database 15 | enable_extension "plpgsql" 16 | 17 | create_table "active_admin_comments", force: :cascade do |t| 18 | t.string "namespace" 19 | t.text "body" 20 | t.string "resource_type" 21 | t.bigint "resource_id" 22 | t.string "author_type" 23 | t.bigint "author_id" 24 | t.datetime "created_at", null: false 25 | t.datetime "updated_at", null: false 26 | t.index ["author_type", "author_id"], name: "index_active_admin_comments_on_author" 27 | t.index ["namespace"], name: "index_active_admin_comments_on_namespace" 28 | t.index ["resource_type", "resource_id"], name: "index_active_admin_comments_on_resource" 29 | end 30 | 31 | create_table "active_storage_attachments", force: :cascade do |t| 32 | t.string "name", null: false 33 | t.string "record_type", null: false 34 | t.bigint "record_id", null: false 35 | t.bigint "blob_id", null: false 36 | t.datetime "created_at", null: false 37 | t.index ["blob_id"], name: "index_active_storage_attachments_on_blob_id" 38 | t.index ["record_type", "record_id", "name", "blob_id"], name: "index_active_storage_attachments_uniqueness", unique: true 39 | end 40 | 41 | create_table "active_storage_blobs", force: :cascade do |t| 42 | t.string "key", null: false 43 | t.string "filename", null: false 44 | t.string "content_type" 45 | t.text "metadata" 46 | t.string "service_name", null: false 47 | t.bigint "byte_size", null: false 48 | t.string "checksum" 49 | t.datetime "created_at", null: false 50 | t.index ["key"], name: "index_active_storage_blobs_on_key", unique: true 51 | end 52 | 53 | create_table "active_storage_variant_records", force: :cascade do |t| 54 | t.bigint "blob_id", null: false 55 | t.string "variation_digest", null: false 56 | t.index ["blob_id", "variation_digest"], name: "index_active_storage_variant_records_uniqueness", unique: true 57 | end 58 | 59 | create_table "categories", id: :serial, force: :cascade do |t| 60 | t.string "category_name" 61 | t.string "description" 62 | t.binary "picture" 63 | end 64 | 65 | create_table "customers", id: :serial, force: :cascade do |t| 66 | t.string "company_code" 67 | t.string "company_name" 68 | t.string "contact_name" 69 | t.string "contact_title" 70 | t.string "address" 71 | t.string "city" 72 | t.string "region" 73 | t.string "postal_code" 74 | t.string "country" 75 | t.string "phone" 76 | t.string "fax" 77 | end 78 | 79 | create_table "employees", id: :serial, force: :cascade do |t| 80 | t.string "first_name" 81 | t.string "last_name" 82 | t.string "title" 83 | t.string "title_of_courtesy" 84 | t.integer "reports_to_id" 85 | t.date "birth_date" 86 | t.date "hire_date" 87 | t.binary "photo" 88 | t.string "address" 89 | t.string "city" 90 | t.string "region" 91 | t.string "postal_code" 92 | t.string "country" 93 | t.string "home_phone" 94 | t.string "extension" 95 | t.text "notes" 96 | t.index ["reports_to_id"], name: "index_employees_on_reports_to_id" 97 | end 98 | 99 | create_table "mobility_string_translations", force: :cascade do |t| 100 | t.string "locale", null: false 101 | t.string "key", null: false 102 | t.string "value" 103 | t.string "translatable_type" 104 | t.bigint "translatable_id" 105 | t.datetime "created_at", null: false 106 | t.datetime "updated_at", null: false 107 | t.index ["translatable_id", "translatable_type", "key"], name: "index_mobility_string_translations_on_translatable_attribute" 108 | t.index ["translatable_id", "translatable_type", "locale", "key"], name: "index_mobility_string_translations_on_keys", unique: true 109 | t.index ["translatable_type", "key", "value", "locale"], name: "index_mobility_string_translations_on_query_keys" 110 | end 111 | 112 | create_table "mobility_text_translations", force: :cascade do |t| 113 | t.string "locale", null: false 114 | t.string "key", null: false 115 | t.text "value" 116 | t.string "translatable_type" 117 | t.bigint "translatable_id" 118 | t.datetime "created_at", null: false 119 | t.datetime "updated_at", null: false 120 | t.index ["translatable_id", "translatable_type", "key"], name: "index_mobility_text_translations_on_translatable_attribute" 121 | t.index ["translatable_id", "translatable_type", "locale", "key"], name: "index_mobility_text_translations_on_keys", unique: true 122 | end 123 | 124 | create_table "motor_alert_locks", force: :cascade do |t| 125 | t.bigint "alert_id", null: false 126 | t.string "lock_timestamp", null: false 127 | t.datetime "created_at", null: false 128 | t.datetime "updated_at", null: false 129 | t.index ["alert_id", "lock_timestamp"], name: "index_motor_alert_locks_on_alert_id_and_lock_timestamp", unique: true 130 | t.index ["alert_id"], name: "index_motor_alert_locks_on_alert_id" 131 | end 132 | 133 | create_table "motor_alerts", force: :cascade do |t| 134 | t.bigint "query_id", null: false 135 | t.string "name", null: false 136 | t.text "description" 137 | t.text "to_emails", null: false 138 | t.boolean "is_enabled", default: true, null: false 139 | t.text "preferences", null: false 140 | t.bigint "author_id" 141 | t.string "author_type" 142 | t.datetime "deleted_at" 143 | t.datetime "created_at", null: false 144 | t.datetime "updated_at", null: false 145 | t.index ["name"], name: "motor_alerts_name_unique_index", unique: true, where: "(deleted_at IS NULL)" 146 | t.index ["query_id"], name: "index_motor_alerts_on_query_id" 147 | t.index ["updated_at"], name: "index_motor_alerts_on_updated_at" 148 | end 149 | 150 | create_table "motor_api_configs", force: :cascade do |t| 151 | t.string "name", null: false 152 | t.string "url", null: false 153 | t.text "preferences", null: false 154 | t.text "credentials", null: false 155 | t.text "description" 156 | t.datetime "deleted_at" 157 | t.datetime "created_at", null: false 158 | t.datetime "updated_at", null: false 159 | t.index ["name"], name: "motor_api_configs_name_unique_index", unique: true, where: "(deleted_at IS NULL)" 160 | end 161 | 162 | create_table "motor_audits", force: :cascade do |t| 163 | t.string "auditable_id" 164 | t.string "auditable_type" 165 | t.string "associated_id" 166 | t.string "associated_type" 167 | t.bigint "user_id" 168 | t.string "user_type" 169 | t.string "username" 170 | t.string "action" 171 | t.text "audited_changes" 172 | t.bigint "version", default: 0 173 | t.text "comment" 174 | t.string "remote_address" 175 | t.string "request_uuid" 176 | t.datetime "created_at" 177 | t.index ["associated_type", "associated_id"], name: "motor_auditable_associated_index" 178 | t.index ["auditable_type", "auditable_id", "version"], name: "motor_auditable_index" 179 | t.index ["created_at"], name: "index_motor_audits_on_created_at" 180 | t.index ["request_uuid"], name: "index_motor_audits_on_request_uuid" 181 | t.index ["user_id", "user_type"], name: "motor_auditable_user_index" 182 | end 183 | 184 | create_table "motor_configs", force: :cascade do |t| 185 | t.string "key", null: false 186 | t.text "value", null: false 187 | t.datetime "created_at", null: false 188 | t.datetime "updated_at", null: false 189 | t.index ["key"], name: "index_motor_configs_on_key", unique: true 190 | t.index ["updated_at"], name: "index_motor_configs_on_updated_at" 191 | end 192 | 193 | create_table "motor_dashboards", force: :cascade do |t| 194 | t.string "title", null: false 195 | t.text "description" 196 | t.text "preferences", null: false 197 | t.bigint "author_id" 198 | t.string "author_type" 199 | t.datetime "deleted_at" 200 | t.datetime "created_at", null: false 201 | t.datetime "updated_at", null: false 202 | t.index ["title"], name: "motor_dashboards_title_unique_index", unique: true, where: "(deleted_at IS NULL)" 203 | t.index ["updated_at"], name: "index_motor_dashboards_on_updated_at" 204 | end 205 | 206 | create_table "motor_forms", force: :cascade do |t| 207 | t.string "name", null: false 208 | t.text "description" 209 | t.text "api_path", null: false 210 | t.string "http_method", null: false 211 | t.text "preferences", null: false 212 | t.bigint "author_id" 213 | t.string "author_type" 214 | t.datetime "deleted_at" 215 | t.string "api_config_name", null: false 216 | t.datetime "created_at", null: false 217 | t.datetime "updated_at", null: false 218 | t.index ["name"], name: "motor_forms_name_unique_index", unique: true, where: "(deleted_at IS NULL)" 219 | t.index ["updated_at"], name: "index_motor_forms_on_updated_at" 220 | end 221 | 222 | create_table "motor_note_tag_tags", force: :cascade do |t| 223 | t.bigint "tag_id", null: false 224 | t.bigint "note_id", null: false 225 | t.index ["note_id", "tag_id"], name: "motor_note_tags_note_id_tag_id_index", unique: true 226 | t.index ["tag_id"], name: "index_motor_note_tag_tags_on_tag_id" 227 | end 228 | 229 | create_table "motor_note_tags", force: :cascade do |t| 230 | t.string "name", null: false 231 | t.datetime "created_at", null: false 232 | t.datetime "updated_at", null: false 233 | t.index ["name"], name: "motor_note_tags_name_unique_index", unique: true 234 | end 235 | 236 | create_table "motor_notes", force: :cascade do |t| 237 | t.text "body" 238 | t.bigint "author_id" 239 | t.string "author_type" 240 | t.string "record_id", null: false 241 | t.string "record_type", null: false 242 | t.datetime "deleted_at" 243 | t.datetime "created_at", null: false 244 | t.datetime "updated_at", null: false 245 | t.index ["author_id", "author_type"], name: "motor_notes_author_id_author_type_index" 246 | end 247 | 248 | create_table "motor_notifications", force: :cascade do |t| 249 | t.string "title", null: false 250 | t.text "description" 251 | t.bigint "recipient_id", null: false 252 | t.string "recipient_type", null: false 253 | t.string "record_id" 254 | t.string "record_type" 255 | t.string "status", null: false 256 | t.datetime "created_at", null: false 257 | t.datetime "updated_at", null: false 258 | t.index ["recipient_id", "recipient_type"], name: "motor_notifications_recipient_id_recipient_type_index" 259 | t.index ["record_id", "record_type"], name: "motor_notifications_record_id_record_type_index" 260 | end 261 | 262 | create_table "motor_queries", force: :cascade do |t| 263 | t.string "name", null: false 264 | t.text "description" 265 | t.text "sql_body", null: false 266 | t.text "preferences", null: false 267 | t.bigint "author_id" 268 | t.string "author_type" 269 | t.datetime "deleted_at" 270 | t.datetime "created_at", null: false 271 | t.datetime "updated_at", null: false 272 | t.index ["name"], name: "motor_queries_name_unique_index", unique: true, where: "(deleted_at IS NULL)" 273 | t.index ["updated_at"], name: "index_motor_queries_on_updated_at" 274 | end 275 | 276 | create_table "motor_reminders", force: :cascade do |t| 277 | t.bigint "author_id", null: false 278 | t.string "author_type", null: false 279 | t.bigint "recipient_id", null: false 280 | t.string "recipient_type", null: false 281 | t.string "record_id" 282 | t.string "record_type" 283 | t.datetime "scheduled_at", null: false 284 | t.datetime "created_at", null: false 285 | t.datetime "updated_at", null: false 286 | t.index ["author_id", "author_type"], name: "motor_reminders_author_id_author_type_index" 287 | t.index ["recipient_id", "recipient_type"], name: "motor_reminders_recipient_id_recipient_type_index" 288 | t.index ["record_id", "record_type"], name: "motor_reminders_record_id_record_type_index" 289 | t.index ["scheduled_at"], name: "index_motor_reminders_on_scheduled_at" 290 | end 291 | 292 | create_table "motor_resources", force: :cascade do |t| 293 | t.string "name", null: false 294 | t.text "preferences", null: false 295 | t.datetime "created_at", null: false 296 | t.datetime "updated_at", null: false 297 | t.index ["name"], name: "index_motor_resources_on_name", unique: true 298 | t.index ["updated_at"], name: "index_motor_resources_on_updated_at" 299 | end 300 | 301 | create_table "motor_taggable_tags", force: :cascade do |t| 302 | t.bigint "tag_id", null: false 303 | t.bigint "taggable_id", null: false 304 | t.string "taggable_type", null: false 305 | t.index ["tag_id"], name: "index_motor_taggable_tags_on_tag_id" 306 | t.index ["taggable_id", "taggable_type", "tag_id"], name: "motor_polymorphic_association_tag_index", unique: true 307 | end 308 | 309 | create_table "motor_tags", force: :cascade do |t| 310 | t.string "name", null: false 311 | t.datetime "created_at", null: false 312 | t.datetime "updated_at", null: false 313 | t.index ["name"], name: "motor_tags_name_unique_index", unique: true 314 | end 315 | 316 | create_table "order_details", id: :serial, force: :cascade do |t| 317 | t.decimal "unit_price" 318 | t.integer "quantity" 319 | t.decimal "discount" 320 | t.integer "order_id" 321 | t.integer "product_id" 322 | t.index ["order_id"], name: "index_order_details_on_order_id" 323 | t.index ["product_id"], name: "index_order_details_on_product_id" 324 | end 325 | 326 | create_table "orders", id: :serial, force: :cascade do |t| 327 | t.date "order_date" 328 | t.integer "customer_id" 329 | t.integer "employee_id" 330 | t.date "required_date" 331 | t.date "shipped_date" 332 | t.integer "ship_via_id" 333 | t.decimal "freight" 334 | t.string "ship_name" 335 | t.string "ship_address" 336 | t.string "ship_city" 337 | t.string "ship_region" 338 | t.string "ship_postal_code" 339 | t.string "ship_country" 340 | t.string "customer_code" 341 | t.index ["customer_id"], name: "index_orders_on_customer_id" 342 | t.index ["employee_id"], name: "index_orders_on_employee_id" 343 | end 344 | 345 | create_table "products", id: :serial, force: :cascade do |t| 346 | t.string "product_name" 347 | t.integer "category_id" 348 | t.decimal "unit_price" 349 | t.boolean "discontinued" 350 | t.integer "units_in_stock" 351 | t.integer "units_on_order" 352 | t.integer "reorder_level" 353 | t.string "quantity_per_unit" 354 | t.integer "supplier_id" 355 | t.index ["category_id"], name: "index_products_on_category_id" 356 | end 357 | 358 | create_table "spina_accounts", id: :serial, force: :cascade do |t| 359 | t.string "name" 360 | t.string "address" 361 | t.string "postal_code" 362 | t.string "city" 363 | t.string "phone" 364 | t.string "email" 365 | t.text "preferences" 366 | t.datetime "created_at", precision: nil, null: false 367 | t.datetime "updated_at", precision: nil, null: false 368 | t.boolean "robots_allowed", default: false 369 | t.jsonb "json_attributes" 370 | end 371 | 372 | create_table "spina_attachment_collections", id: :serial, force: :cascade do |t| 373 | t.datetime "created_at", precision: nil, null: false 374 | t.datetime "updated_at", precision: nil, null: false 375 | end 376 | 377 | create_table "spina_attachment_collections_attachments", id: :serial, force: :cascade do |t| 378 | t.integer "attachment_collection_id" 379 | t.integer "attachment_id" 380 | end 381 | 382 | create_table "spina_attachments", id: :serial, force: :cascade do |t| 383 | t.string "file" 384 | t.datetime "created_at", precision: nil, null: false 385 | t.datetime "updated_at", precision: nil, null: false 386 | end 387 | 388 | create_table "spina_image_collections", force: :cascade do |t| 389 | t.datetime "created_at", precision: nil, null: false 390 | t.datetime "updated_at", precision: nil, null: false 391 | end 392 | 393 | create_table "spina_image_collections_images", id: :serial, force: :cascade do |t| 394 | t.integer "image_collection_id" 395 | t.integer "image_id" 396 | t.integer "position" 397 | t.index ["image_collection_id"], name: "index_spina_image_collections_images_on_image_collection_id" 398 | t.index ["image_id"], name: "index_spina_image_collections_images_on_image_id" 399 | end 400 | 401 | create_table "spina_images", force: :cascade do |t| 402 | t.integer "media_folder_id" 403 | t.datetime "created_at", precision: nil, null: false 404 | t.datetime "updated_at", precision: nil, null: false 405 | t.index ["media_folder_id"], name: "index_spina_images_on_media_folder_id" 406 | end 407 | 408 | create_table "spina_layout_parts", id: :serial, force: :cascade do |t| 409 | t.string "title" 410 | t.string "name" 411 | t.integer "layout_partable_id" 412 | t.string "layout_partable_type" 413 | t.datetime "created_at", precision: nil 414 | t.datetime "updated_at", precision: nil 415 | t.integer "account_id" 416 | end 417 | 418 | create_table "spina_line_translations", id: :serial, force: :cascade do |t| 419 | t.integer "spina_line_id", null: false 420 | t.string "locale", null: false 421 | t.string "content" 422 | t.datetime "created_at", precision: nil, null: false 423 | t.datetime "updated_at", precision: nil, null: false 424 | t.index ["locale"], name: "index_spina_line_translations_on_locale" 425 | t.index ["spina_line_id"], name: "index_spina_line_translations_on_spina_line_id" 426 | end 427 | 428 | create_table "spina_lines", id: :serial, force: :cascade do |t| 429 | t.datetime "created_at", precision: nil 430 | t.datetime "updated_at", precision: nil 431 | end 432 | 433 | create_table "spina_media_folders", force: :cascade do |t| 434 | t.string "name" 435 | t.datetime "created_at", precision: nil, null: false 436 | t.datetime "updated_at", precision: nil, null: false 437 | end 438 | 439 | create_table "spina_navigation_items", id: :serial, force: :cascade do |t| 440 | t.integer "page_id", null: false 441 | t.integer "navigation_id", null: false 442 | t.integer "position", default: 0, null: false 443 | t.string "ancestry" 444 | t.datetime "created_at", precision: nil 445 | t.datetime "updated_at", precision: nil 446 | t.index ["page_id", "navigation_id"], name: "index_spina_navigation_items_on_page_id_and_navigation_id", unique: true 447 | end 448 | 449 | create_table "spina_navigations", id: :serial, force: :cascade do |t| 450 | t.string "name", null: false 451 | t.string "label", null: false 452 | t.boolean "auto_add_pages", default: false, null: false 453 | t.integer "position", default: 0, null: false 454 | t.datetime "created_at", precision: nil 455 | t.datetime "updated_at", precision: nil 456 | t.index ["name"], name: "index_spina_navigations_on_name", unique: true 457 | end 458 | 459 | create_table "spina_options", id: :serial, force: :cascade do |t| 460 | t.string "value" 461 | t.datetime "created_at", precision: nil, null: false 462 | t.datetime "updated_at", precision: nil, null: false 463 | end 464 | 465 | create_table "spina_page_parts", id: :serial, force: :cascade do |t| 466 | t.string "title" 467 | t.string "name" 468 | t.datetime "created_at", precision: nil, null: false 469 | t.datetime "updated_at", precision: nil, null: false 470 | t.integer "page_id" 471 | t.integer "page_partable_id" 472 | t.string "page_partable_type" 473 | end 474 | 475 | create_table "spina_page_translations", id: :serial, force: :cascade do |t| 476 | t.integer "spina_page_id", null: false 477 | t.string "locale", null: false 478 | t.string "title" 479 | t.string "menu_title" 480 | t.string "description" 481 | t.string "seo_title" 482 | t.string "materialized_path" 483 | t.datetime "created_at", precision: nil, null: false 484 | t.datetime "updated_at", precision: nil, null: false 485 | t.string "url_title" 486 | t.index ["locale"], name: "index_spina_page_translations_on_locale" 487 | t.index ["spina_page_id"], name: "index_spina_page_translations_on_spina_page_id" 488 | end 489 | 490 | create_table "spina_pages", id: :serial, force: :cascade do |t| 491 | t.boolean "show_in_menu", default: true 492 | t.string "slug" 493 | t.boolean "deletable", default: true 494 | t.datetime "created_at", precision: nil, null: false 495 | t.datetime "updated_at", precision: nil, null: false 496 | t.string "name" 497 | t.boolean "skip_to_first_child", default: false 498 | t.string "view_template" 499 | t.string "layout_template" 500 | t.boolean "draft", default: false 501 | t.string "link_url" 502 | t.string "ancestry" 503 | t.integer "position" 504 | t.boolean "active", default: true 505 | t.integer "resource_id" 506 | t.jsonb "json_attributes" 507 | t.integer "ancestry_depth", default: 0 508 | t.integer "ancestry_children_count" 509 | t.index ["resource_id"], name: "index_spina_pages_on_resource_id" 510 | end 511 | 512 | create_table "spina_resources", force: :cascade do |t| 513 | t.string "name", null: false 514 | t.string "label" 515 | t.string "view_template" 516 | t.string "order_by" 517 | t.datetime "created_at", precision: nil, null: false 518 | t.datetime "updated_at", precision: nil, null: false 519 | t.jsonb "slug" 520 | end 521 | 522 | create_table "spina_rewrite_rules", id: :serial, force: :cascade do |t| 523 | t.string "old_path" 524 | t.string "new_path" 525 | t.datetime "created_at", precision: nil 526 | t.datetime "updated_at", precision: nil 527 | end 528 | 529 | create_table "spina_settings", id: :serial, force: :cascade do |t| 530 | t.string "plugin" 531 | t.jsonb "preferences", default: {} 532 | t.datetime "created_at", precision: nil, null: false 533 | t.datetime "updated_at", precision: nil, null: false 534 | t.index ["plugin"], name: "index_spina_settings_on_plugin" 535 | end 536 | 537 | create_table "spina_structure_items", id: :serial, force: :cascade do |t| 538 | t.integer "structure_id" 539 | t.integer "position" 540 | t.datetime "created_at", precision: nil 541 | t.datetime "updated_at", precision: nil 542 | t.index ["structure_id"], name: "index_spina_structure_items_on_structure_id" 543 | end 544 | 545 | create_table "spina_structure_parts", id: :serial, force: :cascade do |t| 546 | t.integer "structure_item_id" 547 | t.integer "structure_partable_id" 548 | t.string "structure_partable_type" 549 | t.string "name" 550 | t.string "title" 551 | t.datetime "created_at", precision: nil 552 | t.datetime "updated_at", precision: nil 553 | t.index ["structure_item_id"], name: "index_spina_structure_parts_on_structure_item_id" 554 | t.index ["structure_partable_id"], name: "index_spina_structure_parts_on_structure_partable_id" 555 | end 556 | 557 | create_table "spina_structures", id: :serial, force: :cascade do |t| 558 | t.datetime "created_at", precision: nil 559 | t.datetime "updated_at", precision: nil 560 | end 561 | 562 | create_table "spina_text_translations", id: :serial, force: :cascade do |t| 563 | t.integer "spina_text_id", null: false 564 | t.string "locale", null: false 565 | t.text "content" 566 | t.datetime "created_at", precision: nil, null: false 567 | t.datetime "updated_at", precision: nil, null: false 568 | t.index ["locale"], name: "index_spina_text_translations_on_locale" 569 | t.index ["spina_text_id"], name: "index_spina_text_translations_on_spina_text_id" 570 | end 571 | 572 | create_table "spina_texts", id: :serial, force: :cascade do |t| 573 | t.datetime "created_at", precision: nil 574 | t.datetime "updated_at", precision: nil 575 | end 576 | 577 | create_table "spina_users", id: :serial, force: :cascade do |t| 578 | t.string "name" 579 | t.string "email" 580 | t.string "password_digest" 581 | t.boolean "admin", default: false 582 | t.datetime "created_at", precision: nil, null: false 583 | t.datetime "updated_at", precision: nil, null: false 584 | t.datetime "last_logged_in", precision: nil 585 | t.string "password_reset_token" 586 | t.datetime "password_reset_sent_at", precision: nil 587 | end 588 | 589 | add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id" 590 | add_foreign_key "active_storage_variant_records", "active_storage_blobs", column: "blob_id" 591 | add_foreign_key "motor_alert_locks", "motor_alerts", column: "alert_id" 592 | add_foreign_key "motor_alerts", "motor_queries", column: "query_id" 593 | add_foreign_key "motor_note_tag_tags", "motor_note_tags", column: "tag_id" 594 | add_foreign_key "motor_note_tag_tags", "motor_notes", column: "note_id" 595 | add_foreign_key "motor_taggable_tags", "motor_tags", column: "tag_id" 596 | add_foreign_key "order_details", "orders" 597 | add_foreign_key "order_details", "products" 598 | add_foreign_key "orders", "customers" 599 | add_foreign_key "orders", "employees" 600 | add_foreign_key "products", "categories" 601 | end 602 | --------------------------------------------------------------------------------