diff --git a/.irbrc_history b/.irbrc_history new file mode 100644 index 0000000..614ad06 --- /dev/null +++ b/.irbrc_history @@ -0,0 +1,15 @@ +Check.last +Check.find(5) +exit +Element.delete_all +Element.delete_all +SuccessCriteria.all +SuccessCriterion.all +Element.delete_all +Element.destroy_all +Element.all +Element.all +Element.find(5) +Report.destroy_all +Report.all +exit diff --git a/.rubocop.yml b/.rubocop.yml index d771237..25b6323 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -4,6 +4,7 @@ require: AllCops: Exclude: + - '.bundle/**/*.rb' - 'config/**/*.rb' - 'db/**/*.rb' - 'vendor/**/*.rb' diff --git a/Gemfile b/Gemfile index 25bec68..4e90674 100644 --- a/Gemfile +++ b/Gemfile @@ -48,6 +48,7 @@ gem 'bootsnap', require: false # Use Active Storage variants [https://guides.rubyonrails.org/active_storage_overview.html#transforming-images] # gem "image_processing", "~> 1.2" +gem 'bootstrap_form' group :development, :test do # See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem diff --git a/Gemfile.lock b/Gemfile.lock index 4105ebe..4984631 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -83,6 +83,9 @@ GEM bindex (0.8.1) bootsnap (1.18.3) msgpack (~> 1.2) + bootstrap_form (5.4.0) + actionpack (>= 6.1) + activemodel (>= 6.1) builder (3.3.0) capybara (3.40.0) addressable @@ -301,6 +304,7 @@ PLATFORMS DEPENDENCIES bootsnap + bootstrap_form capybara cssbundling-rails debug diff --git a/app/assets/stylesheets/application.bootstrap.scss b/app/assets/stylesheets/application.bootstrap.scss index 62cd8a6..9c980a6 100644 --- a/app/assets/stylesheets/application.bootstrap.scss +++ b/app/assets/stylesheets/application.bootstrap.scss @@ -24,8 +24,8 @@ $font-family-sans-serif: // Emoji fonts "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji" !default; -$primary: #0074d9; -$danger: #ff4136; - @import 'bootstrap/scss/bootstrap'; @import 'bootstrap-icons/font/bootstrap-icons'; +@import "rails_bootstrap_forms.css"; + +@import "./layout.scss"; \ No newline at end of file diff --git a/app/assets/stylesheets/layout.scss b/app/assets/stylesheets/layout.scss new file mode 100644 index 0000000..29de506 --- /dev/null +++ b/app/assets/stylesheets/layout.scss @@ -0,0 +1,14 @@ +.action-row { + @extend .d-flex; + @extend .p-2; + @extend .mt-3; + + // background-color: map-get($theme-colors, "primary"); + background-color: var(--bs-tertiary-bg); + background-color: var(--bs-secondary-bg); + + * { + @extend .me-2; + @extend .my-auto; + } +} \ No newline at end of file diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index f7e7979..7593990 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -6,9 +6,12 @@ class ApplicationController < ActionController::Base private def initialize_navbar + @nav_path = controller_name @navbar_items = [ - { label: 'Dashboard', path: :root }, - { label: 'Home', path: :home } + { label: 'Dashboard', icon: :speedometer2, path: :root }, + { label: Report.model_name.human(count: 2), icon: :'journal-text', path: :reports }, + { label: Checklist.model_name.human(count: 2), icon: :'list-check', path: :checklists }, + { label: Check.model_name.human(count: 2), icon: :check, path: :checks } ] @search_url = nil # root_url end diff --git a/app/controllers/checklists_controller.rb b/app/controllers/checklists_controller.rb new file mode 100644 index 0000000..9418bff --- /dev/null +++ b/app/controllers/checklists_controller.rb @@ -0,0 +1,61 @@ +class ChecklistsController < ApplicationController + before_action :set_checklist, only: %i[show edit update destroy] + + # GET /checklists + def index + @checklists = Checklist.all + end + + # GET /checklists/1 + def show + end + + # GET /checklists/new + def new + @checklist = Checklist.new + end + + # GET /checklists/1/edit + def edit + @checklist.checklist_entries.build + end + + # POST /checklists + def create + @checklist = Checklist.new(checklist_params) + + if @checklist.save + redirect_to @checklist, notice: 'Checklist was successfully created.' + else + render :new, status: :unprocessable_entity + end + end + + # PATCH/PUT /checklists/1 + def update + if @checklist.update(checklist_params) + redirect_to @checklist, notice: 'Checklist was successfully updated.', status: :see_other + else + render :edit, status: :unprocessable_entity + end + end + + # DELETE /checklists/1 + def destroy + @checklist.destroy! + redirect_to checklists_url, notice: 'Checklist was successfully destroyed.', status: :see_other + end + + private + + # Use callbacks to share common setup or constraints between actions. + def set_checklist + @checklist = Checklist.find(params[:id]) + end + + # Only allow a list of trusted parameters through. + def checklist_params + params.require(:checklist).permit(:code, :name, :description, + checklist_entries_attributes: %i[id check_id position _destroy]) + end +end diff --git a/app/controllers/checks_controller.rb b/app/controllers/checks_controller.rb new file mode 100644 index 0000000..3757ca8 --- /dev/null +++ b/app/controllers/checks_controller.rb @@ -0,0 +1,80 @@ +class ChecksController < ApplicationController + before_action :set_check, only: %i[show edit update destroy] + + # GET /checks or /checks.json + def index + @checks = Check.all + end + + # GET /checks/1 or /checks/1.json + def show + end + + # GET /checks/new + def new + @check = Check.new + end + + # GET /checks/1/edit + def edit + end + + # POST /checks or /checks.json + def create + @check = Check.new(check_params) + + respond_to do |format| + if @check.save + format.html do + redirect_to check_url(@check), + notice: t('scaffold.model_created_successfully', model: @check.model_name.human) + end + format.json { render :show, status: :created, location: @check } + else + flash[:alert] = t('there_were_errors', count: @check.errors.size) + format.html { render :new, status: :unprocessable_entity } + format.json { render json: @check.errors, status: :unprocessable_entity } + end + end + end + + # PATCH/PUT /checks/1 or /checks/1.json + def update + respond_to do |format| + if @check.update(check_params) + format.html do + redirect_to check_url(@check), + notice: t('scaffold.model_updated_successfully', model: @check.model_name.human) + end + format.json { render :show, status: :ok, location: @check } + else + format.html { render :edit, status: :unprocessable_entity } + format.json { render json: @check.errors, status: :unprocessable_entity } + end + end + end + + # DELETE /checks/1 or /checks/1.json + def destroy + @check.destroy! + + respond_to do |format| + format.html do + redirect_to checks_url, notice: t('scaffold.model_destroyed_successfully', model: @check.model_name.human) + end + format.json { head :no_content } + end + end + + private + + # Use callbacks to share common setup or constraints between actions. + def set_check + @check = Check.find(params[:id]) + end + + # Only allow a list of trusted parameters through. + def check_params + params.require(:check).permit(:position, :name, :success_criterion, :level) + end +end diff --git a/app/controllers/elements_controller.rb b/app/controllers/elements_controller.rb new file mode 100644 index 0000000..e78b27d --- /dev/null +++ b/app/controllers/elements_controller.rb @@ -0,0 +1,64 @@ +class ElementsController < ApplicationController + before_action :set_element, only: %i[show edit update destroy] + + # GET /elements + def index + @elements = Element.all + end + + # GET /elements/1 + def show + end + + # GET /elements/new + def new + @element = Element.new + end + + # GET /elements/1/edit + def edit + end + + # POST /elements + def create + checklist_id = element_params.delete(:checklist_id) + checklist = Checklist.find(checklist_id) + @element = Element.new(element_params.merge(title: checklist.name)) + + if @element.save + checklist.checks.each do |check| + @element.success_criteria.create!(title: check.name, description: check.success_criterion, level: check.level) + end + redirect_to [:work, @element.report], notice: 'Element was successfully created.' + else + render :new, status: :unprocessable_entity + end + end + + # PATCH/PUT /elements/1 + def update + if @element.update(element_params) + redirect_to @element, notice: 'Element was successfully updated.', status: :see_other + else + render :edit, status: :unprocessable_entity + end + end + + # DELETE /elements/1 + def destroy + @element.destroy! + redirect_to elements_url, notice: 'Element was successfully destroyed.', status: :see_other + end + + private + + # Use callbacks to share common setup or constraints between actions. + def set_element + @element = Element.find(params[:id]) + end + + # Only allow a list of trusted parameters through. + def element_params + params.require(:element).permit(:report_id, :path, :title, :description, :checklist_id) + end +end diff --git a/app/controllers/reports_controller.rb b/app/controllers/reports_controller.rb new file mode 100644 index 0000000..b92bfac --- /dev/null +++ b/app/controllers/reports_controller.rb @@ -0,0 +1,63 @@ +class ReportsController < ApplicationController + before_action :set_report, only: %i[show edit update destroy work] + + # GET /reports + def index + @reports = Report.all + end + + # GET /reports/1 + def show + end + + # GET /reports/new + def new + @report = Report.new + end + + # GET /reports/1/edit + def edit + end + + # POST /reports + def create + @report = Report.new(report_params) + + if @report.save + redirect_to @report, notice: 'Report was successfully created.' + else + render :new, status: :unprocessable_entity + end + end + + # PATCH/PUT /reports/1 + def update + if @report.update(report_params) + redirect_to @report, notice: 'Report was successfully updated.', status: :see_other + else + render :edit, status: :unprocessable_entity + end + end + + # DELETE /reports/1 + def destroy + @report.destroy! + redirect_to reports_url, notice: 'Report was successfully destroyed.', status: :see_other + end + + def work + @report + end + + private + + # Use callbacks to share common setup or constraints between actions. + def set_report + @report = Report.find(params[:id]) + end + + # Only allow a list of trusted parameters through. + def report_params + params.require(:report).permit(:name, :comment) + end +end diff --git a/app/controllers/success_criteria_controller.rb b/app/controllers/success_criteria_controller.rb new file mode 100644 index 0000000..9251457 --- /dev/null +++ b/app/controllers/success_criteria_controller.rb @@ -0,0 +1,58 @@ +class SuccessCriteriaController < ApplicationController + before_action :set_success_criterion, only: %i[ show edit update destroy ] + + # GET /success_criteria + def index + @success_criteria = SuccessCriterion.all + end + + # GET /success_criteria/1 + def show + end + + # GET /success_criteria/new + def new + @success_criterion = SuccessCriterion.new + end + + # GET /success_criteria/1/edit + def edit + end + + # POST /success_criteria + def create + @success_criterion = SuccessCriterion.new(success_criterion_params) + + if @success_criterion.save + redirect_to @success_criterion, notice: "Success criterion was successfully created." + else + render :new, status: :unprocessable_entity + end + end + + # PATCH/PUT /success_criteria/1 + def update + if @success_criterion.update(success_criterion_params) + redirect_to @success_criterion, notice: "Success criterion was successfully updated.", status: :see_other + else + render :edit, status: :unprocessable_entity + end + end + + # DELETE /success_criteria/1 + def destroy + @success_criterion.destroy! + redirect_to success_criteria_url, notice: "Success criterion was successfully destroyed.", status: :see_other + end + + private + # Use callbacks to share common setup or constraints between actions. + def set_success_criterion + @success_criterion = SuccessCriterion.find(params[:id]) + end + + # Only allow a list of trusted parameters through. + def success_criterion_params + params.require(:success_criterion).permit(:element_id, :title, :description, :level, :result, :comment) + end +end diff --git a/app/helpers/checklists_helper.rb b/app/helpers/checklists_helper.rb new file mode 100644 index 0000000..4652a79 --- /dev/null +++ b/app/helpers/checklists_helper.rb @@ -0,0 +1,2 @@ +module ChecklistsHelper +end diff --git a/app/helpers/checks_helper.rb b/app/helpers/checks_helper.rb new file mode 100644 index 0000000..ec8edd7 --- /dev/null +++ b/app/helpers/checks_helper.rb @@ -0,0 +1,2 @@ +module ChecksHelper +end diff --git a/app/helpers/elements_helper.rb b/app/helpers/elements_helper.rb new file mode 100644 index 0000000..fed28ea --- /dev/null +++ b/app/helpers/elements_helper.rb @@ -0,0 +1,2 @@ +module ElementsHelper +end diff --git a/app/helpers/reports_helper.rb b/app/helpers/reports_helper.rb new file mode 100644 index 0000000..cae2f09 --- /dev/null +++ b/app/helpers/reports_helper.rb @@ -0,0 +1,2 @@ +module ReportsHelper +end diff --git a/app/helpers/success_criteria_helper.rb b/app/helpers/success_criteria_helper.rb new file mode 100644 index 0000000..2f26b2f --- /dev/null +++ b/app/helpers/success_criteria_helper.rb @@ -0,0 +1,2 @@ +module SuccessCriteriaHelper +end diff --git a/app/javascript/controllers/index.js b/app/javascript/controllers/index.js index d0c72e0..47aa271 100644 --- a/app/javascript/controllers/index.js +++ b/app/javascript/controllers/index.js @@ -9,3 +9,6 @@ application.register("hello", HelloController) import SetThemeController from "./set_theme_controller" application.register("set-theme", SetThemeController) + +import ThemeSwitcherController from "./theme_switcher_controller" +application.register("theme-switcher", ThemeSwitcherController) diff --git a/app/javascript/controllers/theme_switcher_controller.js b/app/javascript/controllers/theme_switcher_controller.js new file mode 100644 index 0000000..1ea384d --- /dev/null +++ b/app/javascript/controllers/theme_switcher_controller.js @@ -0,0 +1,28 @@ +import { Controller } from "@hotwired/stimulus" +import Cookie from "../lib/cookies" + +// Connects to data-controller="theme-switcher" +export default class extends Controller { + COOKIE_NAME = "modeTheme" + + connect() { + console.log("connect switcher") + } + + switch() { + const cookieValue = Cookie.get(this.COOKIE_NAME); + const newThemeValue = cookieValue == "dark" ? "light" : "dark"; + + Cookie.set("modeTheme", newThemeValue); + window.document.getElementsByTagName("html")[0].setAttribute("data-bs-theme", newThemeValue); + + const icon = this.element.getElementsByTagName("i")[0]; + if(newThemeValue == "dark") { + icon.classList.remove("bi-sun-fill") + icon.classList.add("bi-moon-stars-fill") + } else { + icon.classList.add("bi-sun-fill") + icon.classList.remove("bi-moon-stars-fill") + } + } +} diff --git a/app/models/check.rb b/app/models/check.rb new file mode 100644 index 0000000..a67436e --- /dev/null +++ b/app/models/check.rb @@ -0,0 +1,5 @@ +class Check < ApplicationRecord + enum :level, %i[A AA AAA] + validates :position, :name, :success_criterion, :level, presence: true + validates :position, numericality: { less_than: 200 } +end diff --git a/app/models/checklist.rb b/app/models/checklist.rb new file mode 100644 index 0000000..3bb1335 --- /dev/null +++ b/app/models/checklist.rb @@ -0,0 +1,6 @@ +class Checklist < ApplicationRecord + has_many :checklist_entries, -> { order(position: :asc) }, dependent: :destroy, inverse_of: :checklist + has_many :checks, through: :checklist_entries + + accepts_nested_attributes_for :checklist_entries +end diff --git a/app/models/checklist_entry.rb b/app/models/checklist_entry.rb new file mode 100644 index 0000000..f030b00 --- /dev/null +++ b/app/models/checklist_entry.rb @@ -0,0 +1,4 @@ +class ChecklistEntry < ApplicationRecord + belongs_to :checklist + belongs_to :check +end diff --git a/app/models/element.rb b/app/models/element.rb new file mode 100644 index 0000000..eabfad8 --- /dev/null +++ b/app/models/element.rb @@ -0,0 +1,6 @@ +class Element < ApplicationRecord + attr_accessor :checklist_id + + belongs_to :report + has_many :success_criteria, dependent: :destroy +end diff --git a/app/models/report.rb b/app/models/report.rb new file mode 100644 index 0000000..3c752ea --- /dev/null +++ b/app/models/report.rb @@ -0,0 +1,3 @@ +class Report < ApplicationRecord + has_many :elements, dependent: :destroy +end diff --git a/app/models/success_criterion.rb b/app/models/success_criterion.rb new file mode 100644 index 0000000..34c3b8a --- /dev/null +++ b/app/models/success_criterion.rb @@ -0,0 +1,4 @@ +class SuccessCriterion < ApplicationRecord + enum :result, %i[passed failed not_applicable] + belongs_to :element +end diff --git a/app/views/checklists/_checklist.html.erb b/app/views/checklists/_checklist.html.erb new file mode 100644 index 0000000..527b498 --- /dev/null +++ b/app/views/checklists/_checklist.html.erb @@ -0,0 +1,28 @@ +
+ Code: + <%= checklist.code %> +
+ ++ Name: + <%= checklist.name %> +
+ ++ Description: + <%= checklist.description %> +
+ ++ Checks +
| <%= Checklist.human_attribute_name(:id) %> | + +<%= Checklist.human_attribute_name(:code) %> | + +<%= Checklist.human_attribute_name(:name) %> | + +<%= Checklist.human_attribute_name(:description) %> | + +
|---|---|---|---|
| <%= link_to(checklist.id, url_for(checklist)) %> | + +<%= link_to(checklist.code, url_for(checklist)) %> | + +<%= link_to(checklist.name, url_for(checklist)) %> | + +<%= link_to(checklist.description, url_for(checklist)) %> | + +
+ <%= Check.human_attribute_name(:position) %>: + <%= check.position %> +
+ ++ <%= Check.human_attribute_name(:name) %>: + <%= check.name %> +
+ ++ <%= Check.human_attribute_name(:success_criterion) %>: + <%= check.success_criterion %> +
+ ++ <%= Check.human_attribute_name(:level) %>: + <%= check.level %> +
+ +| <%= Check.human_attribute_name(:id) %> | +<%= Check.human_attribute_name(:level) %> | +<%= Check.human_attribute_name(:name) %> | +<%= Check.human_attribute_name(:success_criterion) %> | +
|---|---|---|---|
| <%= check.id %> | +<%= check.level %> | +<%= link_to(check.name, url_for(check)) %> | +<%= link_to(truncate(check.success_criterion), url_for(check)) %> | +
+ Path: + <%= element.path %> +
+ + <% element.success_criteria.each do |sc| %> + <%= render sc %> + <% end %> +| <%= Element.human_attribute_name(:id) %> | + +<%= Element.human_attribute_name(:report_id) %> | + +<%= Element.human_attribute_name(:path) %> | + +<%= Element.human_attribute_name(:title) %> | + +<%= Element.human_attribute_name(:description) %> | + +
|---|---|---|---|---|
| <%= link_to(element.id, url_for(element)) %> | + +<%= link_to(element.report_id, url_for(element)) %> | + +<%= link_to(element.path, url_for(element)) %> | + +<%= link_to(element.title, url_for(element)) %> | + +<%= link_to(element.description, url_for(element)) %> | + +
Find me in app/views/home/show.html.erb
- \ No newline at end of file ++ +<%= Report.count %> +<%= link_to Report.model_name.human(count: Report.count), :reports %> +
++ +<%= Checklist.count %> +<%= link_to Checklist.model_name.human(count: Checklist.count), :checklists %> +
++ +<%= Check.count %> +<%= link_to Check.model_name.human(count: Check.count), :checks %> +
\ No newline at end of file diff --git a/app/views/layouts/_flash.html.erb b/app/views/layouts/_flash.html.erb new file mode 100644 index 0000000..486a703 --- /dev/null +++ b/app/views/layouts/_flash.html.erb @@ -0,0 +1,16 @@ +<% if flash[:alert] || flash[:notice] %> +