Check ruby version (has to be at least 3.0.0).
ruby -v
Install ruby 3 via rbenv
rbenv install 3.0.0
rbenv local 3.0.0
echo "source 'https://rubygems.org'" > Gemfile
echo "gem 'rails', '7.0.0'" >> Gemfile
bundle install
bundle exec rails new . --force --css=bootstrap -d=postgresql
inside app/controllers/home_controller.rb
class HomeController < ApplicationController
end
inside config/routes.rb
Rails.application.routes.draw do
get "home/index"
root to: "home#index"
end
app/views/home/index.html.erb
<div class="container-fluid page__heading-container">
<div class="page__heading d-flex align-items-center">
<div class="flex">
<nav aria-label="breadcrumb">
<ol class="breadcrumb mb-0">
<li class="breadcrumb-item"><a href="#">Home</a></li>
<li class="breadcrumb-item active" aria-current="page">Dashboard</li>
</ol>
</nav>
<h1 class="m-0">Dashboard</h1>
</div>
<a href="" class="btn btn-success ms-3">New Report</a>
</div>
</div>
<div class="page__container container-fluid">
<button type="button"
class="btn btn-lg btn-danger"
data-toggle="sidebar"
data-target="#default-drawer">
Toggle Drawer
</button>
</div>
rails db:create
rails db:migrate
./bin/dev
package.json
{
"dependencies": {
"@fortawesome/fontawesome-free": "^5.4.1",
"@fortawesome/fontawesome-svg-core": "^1.2.6",
"@fortawesome/free-solid-svg-icons": "^6.0.0",
"@fortawesome/vue-fontawesome": "^3.0.0-5",
"@hotwired/stimulus": "^3.1.0",
"@hotwired/turbo-rails": "^7.1.3",
"@popperjs/core": "^2.11.6",
"bootstrap": "^5.2.1",
"bootstrap-icons": "^1.9.1",
"chart.js": "^2.7.3",
"daterangepicker": "^3.0.3",
"dragula": "^3.7.2",
"dropzone": "^5.5.1",
"flatpickr": "^4.5.2",
"fullcalendar": "3.9.0",
"ion-rangeslider": "^2.3.0",
"jquery": "^3.6.0",
"jquery-mask-plugin": "^1.14.15",
"jquery-ui-dist": "^1.12.1",
"jqvmap": "github:10bestdesign/jqvmap#master",
"list.js": "^1.5.0",
"material-design-icons-iconfont": "^3.0.3",
"material-design-kit": "^2.2.1",
"moment": "^2.22.2",
"moment-range": "^4.0.1",
"perfect-scrollbar": "^1.4.0",
"quill": "^1.3.6",
"select2": "^4.0.6-rc.1",
"sidebar-style-guide": "^2.0.0",
"toastr": "^2.1.4"
},
"devDependencies": {
"esbuild": "^0.15.7",
"sass": "^1.54.9"
}
}
Install
npm install
mkdir app/assets/stylesheets/educate
cp -rf ~/Code/educate/src/scss/* app/assets/stylesheets/educate/
app/assets/stylesheets/application.bootstrap.scss
// @import 'bootstrap/scss/bootstrap';
// @import 'bootstrap-icons/font/bootstrap-icons';
@import './educate/app.scss'
mkdir app/javascript/educate
cp -rf ~/Code/educate/src/js/* app/javascript/educate/
app/javascript/application.js
// Entry point for the build script in your package.json
import "@hotwired/turbo-rails"
import "./controllers"
// import * as bootstrap from "bootstrap"
import "./educate"
mkdir app/assets/images/educate
cp -rf ~/Code/educate/src/images/* app/assets/images/educate
Add node_modules to assets paths in config/application.rb
# ...
config.load_defaults 7.0
config.assets.paths << Rails.root.join("node_modules")
Add a custom variables file app/stylesheets/_variables.scss
$material-design-icons-font-path: 'material-design-icons-iconfont/dist/fonts/' !default;
Load it from the main application stylesheet app/stylesheets/application.bootstrap.scss
@import './variables';
@import './educate/app';
Restart dev server
./bin/dev
app/controller/home_controller.rb
class HomeController < ApplicationController
layout 'educate/application'
end
app/views/layouts/educate/application.html.erb
<!DOCTYPE html>
<html dir="ltr">
<head>
<title>RailsBs5Educate</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
<%= javascript_include_tag "application", "data-turbo-track": "reload", defer: true %>
<%= content_for :header %>
</head>
<body class="layout-default">
<div class="preloader"></div>
<!-- Header Layout -->
<div class="mdk-header-layout js-mdk-header-layout">
<!-- Header -->
<div id="header" class="mdk-header js-mdk-header m-0" data-fixed>
<div class="mdk-header__content">
<%= render 'layouts/educate/navbar' %>
</div>
</div>
<!-- // END Header -->
<!-- Header Layout Content -->
<div class="mdk-header-layout__content">
<div class="mdk-drawer-layout js-mdk-drawer-layout" data-push data-responsive-width="992px">
<div class="mdk-drawer-layout__content page">
<%= yield %>
</div>
<!-- // END drawer-layout__content -->
<%= render 'layouts/educate/drawer' %>
</div>
<!-- // END drawer-layout -->
</div>
<!-- // END header-layout__content -->
</div>
<!-- // END header-layout -->
<%= content_for :footer %>
</body>
</html>
app/views/layouts/educate/_navbar.html.erb
<div class="navbar navbar-expand-sm navbar-main navbar-dark bg-dark pe-0" id="navbar" data-primary>
<div class="container-fluid p-0">
<!-- Fluid / Mini Navbar toggler -->
<%# <button class="navbar-toggler navbar-toggler-custom navbar-toggler-right d-block" type="button" data-toggle="sidebar">
<span class="material-icons">apps</span>
</button> %>
<!-- App Navbar toggler -->
<button class="navbar-toggler navbar-toggler-right d-block d-md-none" type="button" data-toggle="sidebar">
<span class="navbar-toggler-icon"></span>
</button>
<!-- Navbar Brand -->
<a href="" class="navbar-brand ms-2 me-3">
<img class="navbar-brand-icon me-2" src="<%= image_path('educate/educate-logo-white.svg') %>" width="22" alt="Educate">
<span>Educate 2</span>
</a>
<form class="search-form d-none d-sm-flex flex" action="">
<button class="btn" type="submit" role="button"><i class="material-icons">search</i></button>
<input type="text" class="form-control" placeholder="Search">
</form>
<div class="flex"></div>
<ul class="nav navbar-nav ms-auto d-none d-md-flex">
<li class="nav-item">
<a href="" class="nav-link">
<i class="material-icons">help_outline</i> Get Help
</a>
</li>
<li class="nav-item me-3">
<a href="" class="btn btn-outline-warning">
<i class="material-icons">star</i> PRO
</a>
</li>
<li class="nav-item dropdown">
<a href="#notifications_menu" class="nav-link dropdown-toggle" data-bs-toggle="dropdown" data-caret="false">
<i class="material-icons nav-icon navbar-notifications-indicator">notifications</i>
</a>
<div id="notifications_menu" class="dropdown-menu dropdown-menu-end navbar-notifications-menu">
<div class="dropdown-item d-flex align-items-center py-2">
<span class="flex navbar-notifications-menu__title m-0">Notifications</span>
<a href="javascript:void(0)" class="text-muted"><small>Clear all</small></a>
</div>
<div class="navbar-notifications-menu__content" data-perfect-scrollbar>
<div class="py-2">
<% [1,2,3].each do %>
<div class="dropdown-item d-flex">
<div class="me-3">
<div class="avatar avatar-sm" style="width: 32px; height: 32px;">
<img src="<%= image_path('educate/256_daniel-gaffey-1060698-unsplash.jpg') %>" alt="Avatar" class="avatar-img rounded-circle">
</div>
</div>
<div class="flex">
<a href="">A.Demian</a> left a comment on <a href="">Educate</a><br>
<small class="text-muted">1 minute ago</small>
</div>
</div>
<div class="dropdown-item d-flex">
<div class="me-3">
<a href="#">
<div class="avatar avatar-xs" style="width: 32px; height: 32px;">
<span class="avatar-title bg-purple rounded-circle"><i class="material-icons icon-16pt">person_add</i></span>
</div>
</a>
</div>
<div class="flex">
New user <a href="#">Peter Parker</a> signed up.<br>
<small class="text-muted">1 hour ago</small>
</div>
</div>
<div class="dropdown-item d-flex">
<div class="me-3">
<a href="#">
<div class="avatar avatar-xs" style="width: 32px; height: 32px;">
<span class="avatar-title rounded-circle">JD</span>
</div>
</a>
</div>
<div class="flex">
<a href="#">Big Joe</a> <small class="text-muted">wrote:</small><br>
<div>Hey, how are you? What about our next meeting</div>
<small class="text-muted">2 minutes ago</small>
</div>
</div>
<% end %>
</div>
</div>
<a href="javascript:void(0);" class="dropdown-item text-center navbar-notifications-menu__footer">View All</a>
</div>
</li>
</ul>
<ul class="nav navbar-nav d-none d-sm-flex border-left navbar-height align-items-center">
<li class="nav-item dropdown">
<a href="#account_menu" class="nav-link dropdown-toggle" data-bs-toggle="dropdown" data-caret="false">
<img src="<%= image_path('educate/avatar/demi.png') %>" class="rounded-circle" width="32" alt="Frontted">
<span class="ms-1 d-flex-inline">
<span class="text-light">Adrian D.</span>
</span>
</a>
<div id="account_menu" class="dropdown-menu dropdown-menu-end">
<div class="dropdown-item-text dropdown-item-text--lh">
<div><strong>Adrian Demian</strong></div>
<div>@adriandemian</div>
</div>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="">Dashboard</a>
<a class="dropdown-item" href="">My profile</a>
<a class="dropdown-item" href="">Edit account</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="">Logout</a>
</div>
</li>
</ul>
</div>
</div>
app/views/layouts/educate/_drawer.html.erb
<div class="mdk-drawer js-mdk-drawer" id="default-drawer" data-align="start">
<div class="mdk-drawer__content">
<div class="sidebar sidebar-light sidebar-left" data-perfect-scrollbar>
<div class="d-flex align-items-center sidebar-p-a border-bottom sidebar-account">
<a href="" class="flex d-flex align-items-center text-underline-0 text-body">
<span class="avatar me-3">
<img src="<%= image_path('educate/avatar/demi.png') %>" alt="avatar" class="avatar-img rounded-circle">
</span>
<span class="flex d-flex flex-column">
<strong>Adrian Demian</strong>
<small class="text-muted text-uppercase">Account Manager</small>
</span>
</a>
<div class="dropdown ml-auto">
<a href="#" data-bs-toggle="dropdown" data-caret="false" class="text-muted"><i class="material-icons">more_vert</i></a>
<div class="dropdown-menu dropdown-menu-end">
<div class="dropdown-item-text dropdown-item-text--lh">
<div><strong>Adrian Demian</strong></div>
<div>@adriandemian</div>
</div>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="">Dashboard</a>
<a class="dropdown-item" href="">My profile</a>
<a class="dropdown-item" href="">Edit account</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="">Logout</a>
</div>
</div>
</div>
<div class="sidebar-p-a sidebar-b-y">
<div class="d-flex align-items-top mb-2">
<div class="sidebar-heading m-0 p-0 flex text-body js-text-body">Progress</div>
<div class="fw-bold text-success">60%</div>
</div>
<div class="progress">
<div class="progress-bar bg-success" role="progressbar" style="width: 60%" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100"></div>
</div>
</div>
<div class="sidebar-heading sidebar-m-t">Menu</div>
<div class="sidebar-block p-0">
<ul class="sidebar-menu">
<li class="sidebar-menu-item active">
<a class="sidebar-menu-button" href="">
<i class="sidebar-menu-icon sidebar-menu-icon--left material-icons">dvr</i>
<span class="sidebar-menu-text">Dashboard</span>
</a>
</li>
<li class="sidebar-menu-item">
<a class="sidebar-menu-button" data-bs-toggle="collapse" href="#layouts_menu" role="button" aria-expanded="false" aria-controls="layouts_menu">
<i class="sidebar-menu-icon sidebar-menu-icon--left material-icons">view_compact</i>
<span class="sidebar-menu-text">Layouts</span>
<span class="ms-auto sidebar-menu-toggle-icon"></span>
</a>
<ul class="sidebar-submenu collapse" id="layouts_menu">
<li class="sidebar-menu-item active">
<a class="sidebar-menu-button" href="">
<span class="sidebar-menu-text">App Layout</span>
</a>
</li>
<li class="sidebar-menu-item">
<a class="sidebar-menu-button" href="">
<span class="sidebar-menu-text">Fluid</span>
</a>
</li>
<li class="sidebar-menu-item">
<a class="sidebar-menu-button" href="">
<span class="sidebar-menu-text">Fixed</span>
</a>
</li>
<li class="sidebar-menu-item">
<a class="sidebar-menu-button" href="">
<span class="sidebar-menu-text">Mini</span>
</a>
</li>
</ul>
</li>
</ul>
</div>
</div>
</div>
</div>
Add route to
config/routes.rb
get "home/alerts", as: "alerts"
Add controller action to
app/controllers/home_controller.rb
class HomeController < ApplicationController
def alerts
end
end
Add menu item to
app/views/layouts/educate/_drawer.html.erb
<div class="sidebar-heading sidebar-m-t">UI Components</div>
<ul class="sidebar-menu">
<li class="sidebar-menu-item <% if current_page?(alerts_path) %>active<% end%>">
<a class="sidebar-menu-button" href="<%= alerts_path %>">
<i class="sidebar-menu-icon sidebar-menu-icon--left material-icons">notifications</i>
<span class="sidebar-menu-text">Alerts</span>
</a>
</li>
</ul>
Add view to
app/views/home/alerts.html.erb
<div class="container-fluid page__heading-container">
<div class="page__heading d-flex align-items-center">
<div class="flex">
<nav aria-label="breadcrumb">
<ol class="breadcrumb mb-0">
<li class="breadcrumb-item"><a href="#">Home</a></li>
<li class="breadcrumb-item active" aria-current="page">UI Components</li>
</ol>
</nav>
<h1 class="m-0">Alerts</h1>
</div>
</div>
</div>
<div class="page__container container-fluid">
<button
type="button"
class="btn btn-primary"
data-toggle="toastr"
data-toastr-type="primary"
data-toastr-title="Heads up!"
data-toastr-message="This alert needs your attention, but it is not super important.">
Click me
</button>
</div>
<% content_for :header do %>
<%= stylesheet_link_tag "toastr" %>
<%= javascript_include_tag "plugins/toastr", defer: true %>
<% end %>
Link toastr from
app/assets/config/manifest.js
//= link toastr/build/toastr.min.css
Update
package.json
to compile files fromapp/javascript/educate/plugins
{
"scripts": {
"build": "esbuild app/javascript/**/**/*.* --bundle --sourcemap --outdir=app/assets/builds --public-path=assets"
}
}
Remove
.vue
files fromapp/javascript/**
as esbuild is not configured yet to handle VueRemove or comment out the contents of
app/javascript/educate/page.ui-icons.js
as its loading.vue
filesWrap initializing code from
app/javascript/plugins/toastr.js
intodocument.addEventListener("turbo:load", () => {
import $ from 'jquery'
import toastr from 'toastr'
document.addEventListener("turbo:load", () => {
$('[data-toggle="toastr"]').on('click', function (e) {
// sample code
})
});
app/controllers/home_controller.rb
class HomeController < ApplicationController
before_action :set_layout
layout :layout_by
private
def set_layout
if params[:layout].present?
session[:layout] = "educate/#{params[:layout]}"
end
@layout = session[:layout] ||= "educate/application"
if @layout == "educate/application"
@containerClass = 'container-fluid'
@navbarContainerClass = 'container-fluid'
@bodyClass = 'layout-default'
elsif @layout == "educate/fluid"
@containerClass = 'container-fluid'
@navbarContainerClass = 'container-fluid p-0'
@bodyClass = 'layout-fluid layout-sticky-subnav'
end
end
def layout_by
@layout
end
end
app/views/layouts/educate/fluid.html.erb
<!DOCTYPE html>
<html dir="ltr">
<head>
<title>Full Width Navs | Educate 2 - Rails 7, Bootstrap 5</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
<%= javascript_include_tag "application", "data-turbo-track": "reload", defer: true %>
<%= content_for :header %>
</head>
<% @containerClass ||= 'container-fluid' %>
<% @navbarContainerClass ||= 'container-fluid p-0' %>
<% @bodyClass ||= 'layout-fluid layout-sticky-subnav' %>
<body class="<%= @bodyClass %>">
<%# <div class="preloader"></div> %>
<!-- Header Layout -->
<div class="mdk-header-layout js-mdk-header-layout">
<!-- Header -->
<div id="header" class="mdk-header bg-dark js-mdk-header m-0" data-fixed>
<div class="mdk-header__content">
<%= render 'layouts/educate/navbar' %>
</div>
</div>
<!-- // END Header -->
<!-- Header Layout Content -->
<div class="mdk-header-layout__content page">
<%= yield %>
</div>
<!-- // END header-layout__content -->
</div>
<!-- // END header-layout -->
<%= render 'layouts/educate/drawer' %>
<%= content_for :footer %>
</body>
</html>
Replace the following in
app/views/layouts/educate/application.html.erb
<body class="layout-default">
With:
<% @containerClass ||= 'container-fluid' %>
<% @navbarContainerClass ||= 'container-fluid' %>
<% @bodyClass ||= 'layout-default' %>
<body class="<%= @bodyClass %>">
Rails Admin Themes for your Rails Application Dashboard