diff --git a/.gitignore b/.gitignore index 50d55f6..6ae1fe5 100644 --- a/.gitignore +++ b/.gitignore @@ -39,3 +39,4 @@ /node_modules /.irbrc_history +.~lock* diff --git a/Dockerfile b/Dockerfile index 2968489..d3c7c08 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,14 +1,19 @@ -FROM ruby:3.3 - -LABEL maintainer='david@hohl.cloud' - ARG NAME=app ARG UID=1000 ARG GID=1000 ARG APP_PORT=3000 - ARG INSTALL_DIR=/${NAME} +FROM ruby:3.3 AS development + +ARG NAME +ARG UID +ARG GID +ARG APP_PORT +ARG INSTALL_DIR + +LABEL maintainer='david@hohl.cloud' + WORKDIR ${INSTALL_DIR} ENV GEM_HOME=${INSTALL_DIR}/.bundle @@ -48,15 +53,75 @@ RUN \ truncate -s 0 /var/log/*log && \ gem update --system && \ bundle config set app_config ${GEM_HOME} - -USER ${NAME} -EXPOSE ${APP_PORT} +FROM development AS builder + +COPY Gemfile Gemfile.lock package.json yarn.lock ./ + +RUN bundle install && yarn install + +FROM builder AS assets + +COPY . . + +COPY --from=builder /app/.bundle /app/.bundle +COPY --from=builder /app/node_modules /app/node_modules + +RUN RAILS_ENV=production SECRET_KEY_BASE_DUMMY=1 rails assets:precompile + +FROM ruby:3.3.0-slim AS production + +ARG NAME +ARG UID +ARG GID +ARG APP_PORT +ARG INSTALL_DIR + +WORKDIR ${INSTALL_DIR} + +ENV \ + LANG=C.UTF-8 \ + INSTALL_DIR=${INSTALL_DIR} \ + RAILS_ENV=production \ + TZ=Europe/Zurich \ + PATH=${INSTALL_DIR}/bin:$GEM_HOME/bin:$GEM_HOME/gems/bin:$PATH + +ENV GEM_HOME=${INSTALL_DIR}/.bundle + +RUN \ + ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && \ + echo $TZ > /etc/timezone && \ + addgroup --gid ${GID} ${NAME} && \ + adduser \ + --gecos GECOS \ + --home /home/${NAME} \ + --uid ${UID} \ + --gid ${GID} \ + --disabled-password \ + --disabled-login \ + --shell /bin/bash \ + ${NAME} && \ + apt-get update -yqq && \ + apt-get install -yqq --no-install-recommends \ + sqlite3 libvips && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* && \ + truncate -s 0 /var/log/*log && \ + gem update --system && \ + bundle config set app_config ${GEM_HOME} + +EXPOSE 3000 ENTRYPOINT [ "bin/entrypoint" ] -ENV SERVER_PORT=$APP_PORT +COPY . . +COPY --from=builder /app/.bundle /app/.bundle +COPY --from=assets /app/public/assets /app/public/assets + +RUN chown -R app:app /app/tmp /app/log /app/storage + +USER app # Using variables in command list is not possible: # https://stackoverflow.com/questions/40454470/how-can-i-use-a-variable-inside-a-dockerfile-cmd -CMD rails server --binding 0.0.0.0 --no-daemon --port $SERVER_PORT +CMD [ "rails", "server", "--binding", "0.0.0.0", "--no-daemon", "--port" , "3000" ] \ No newline at end of file diff --git a/Gemfile b/Gemfile index 9fcf1cb..f4dd1ed 100644 --- a/Gemfile +++ b/Gemfile @@ -48,8 +48,11 @@ gem 'bootsnap', require: false # Use Active Storage variants [https://guides.rubyonrails.org/active_storage_overview.html#transforming-images] gem 'bootstrap_form' +gem 'caxlsx' +gem 'caxlsx_rails' gem 'image_processing', '~> 1.2' gem 'prawn-rails' +gem 'sablon' 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 98d77fb..9e24a71 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -96,6 +96,14 @@ GEM rack-test (>= 0.6.3) regexp_parser (>= 1.5, < 3.0) xpath (~> 3.2) + caxlsx (4.1.0) + htmlentities (~> 4.3, >= 4.3.4) + marcel (~> 1.0) + nokogiri (~> 1.10, >= 1.10.4) + rubyzip (>= 1.3.0, < 3) + caxlsx_rails (0.6.4) + actionpack (>= 3.1) + caxlsx (>= 3.0) concurrent-ruby (1.3.3) connection_pool (2.4.1) crass (1.0.6) @@ -115,6 +123,7 @@ GEM ffi (1.17.0-x86_64-linux-gnu) globalid (1.2.1) activesupport (>= 6.1) + htmlentities (4.3.4) i18n (1.14.5) concurrent-ruby (~> 1.0) image_processing (1.12.2) @@ -270,6 +279,9 @@ GEM ruby-vips (2.2.1) ffi (~> 1.12) rubyzip (2.3.2) + sablon (0.4.1) + nokogiri (>= 1.8.5) + rubyzip (>= 1.3.0) selenium-webdriver (4.22.0) base64 (~> 0.2) logger (~> 1.4) @@ -331,6 +343,8 @@ DEPENDENCIES bootsnap bootstrap_form capybara + caxlsx + caxlsx_rails cssbundling-rails debug image_processing (~> 1.2) @@ -344,6 +358,7 @@ DEPENDENCIES rubocop-rails ruby-lsp ruby-lsp-rails + sablon selenium-webdriver sprockets-rails sqlite3 (~> 1.4) diff --git a/app/assets/stylesheets/actiontext.css b/app/assets/stylesheets/actiontext.css deleted file mode 100644 index 7786117..0000000 --- a/app/assets/stylesheets/actiontext.css +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Provides a drop-in pointer for the default Trix stylesheet that will format the toolbar and - * the trix-editor content (whether displayed or under editing). Feel free to incorporate this - * inclusion directly in any other asset bundle and remove this file. - * - *= require trix -*/ - -/* - * We need to override trix.css’s image gallery styles to accommodate the - * element we wrap around attachments. Otherwise, - * images in galleries will be squished by the max-width: 33%; rule. -*/ -.trix-content .attachment-gallery > action-text-attachment, -.trix-content .attachment-gallery > .attachment { - flex: 1 0 33%; - padding: 0 0.5em; - max-width: 33%; -} - -.trix-content .attachment-gallery.attachment-gallery--2 > action-text-attachment, -.trix-content .attachment-gallery.attachment-gallery--2 > .attachment, .trix-content .attachment-gallery.attachment-gallery--4 > action-text-attachment, -.trix-content .attachment-gallery.attachment-gallery--4 > .attachment { - flex-basis: 50%; - max-width: 50%; -} - -.trix-content action-text-attachment .attachment { - padding: 0 !important; - max-width: 100% !important; -} - - -/* Fix trix dark mode */ -.trix-button-row { - .trix-button-group { - border: var(--bs-border-width) solid var(--bs-border-color); - - .trix-button { - border: 0; - padding: var(--bs-padding) - } - } -} - -[data-bs-theme=dark] { - .trix-button-row { - .trix-button-group { - .trix-button { - background-color: transparent; - filter: invert(100%); - } - } - } -} -/* end fix trix dark mode */ - -.trix-content { - pre { - background-color: var(--bs-secondary-bg) !important; - color: var(--bs-secondary-color) !important; - border: var(--bs-border-width) solid var(--bs-border-color) !important; - border-radius: var(--bs-border-radius) !important; - } -} diff --git a/app/assets/stylesheets/application.bootstrap.scss b/app/assets/stylesheets/application.bootstrap.scss index 32022f7..2983d77 100644 --- a/app/assets/stylesheets/application.bootstrap.scss +++ b/app/assets/stylesheets/application.bootstrap.scss @@ -24,11 +24,97 @@ $font-family-sans-serif: // Emoji fonts "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji" !default; +$enable-rounded: false; + @import 'bootstrap/scss/bootstrap'; @import 'bootstrap-icons/font/bootstrap-icons'; -@import "rails_bootstrap_forms.css"; -@import './actiontext.css'; -@import 'trix.css'; +.rails-bootstrap-forms-date-select select, +.rails-bootstrap-forms-time-select select, +.rails-bootstrap-forms-datetime-select select { + display: inline-block; + width: auto; +} -@import "./layout.scss"; \ No newline at end of file +.rails-bootstrap-forms-error-summary { + margin-top: 10px; +} + + +@import "trix/dist/trix"; + +/* + * Provides a drop-in pointer for the default Trix stylesheet that will format the toolbar and + * the trix-editor content (whether displayed or under editing). Feel free to incorporate this + * inclusion directly in any other asset bundle and remove this file. + * + *= require trix +*/ + +/* + * We need to override trix.css’s image gallery styles to accommodate the + * element we wrap around attachments. Otherwise, + * images in galleries will be squished by the max-width: 33%; rule. +*/ +.trix-content .attachment-gallery > action-text-attachment, +.trix-content .attachment-gallery > .attachment { + flex: 1 0 33%; + padding: 0 0.5em; + max-width: 33%; +} + +.trix-content .attachment-gallery.attachment-gallery--2 > action-text-attachment, +.trix-content .attachment-gallery.attachment-gallery--2 > .attachment, .trix-content .attachment-gallery.attachment-gallery--4 > action-text-attachment, +.trix-content .attachment-gallery.attachment-gallery--4 > .attachment { + flex-basis: 50%; + max-width: 50%; +} + +.trix-content action-text-attachment .attachment { + padding: 0 !important; + max-width: 100% !important; +} + + +/* Fix trix dark mode */ +.trix-button-row { + .trix-button-group { + border: var(--bs-border-width) solid var(--bs-border-color); + + .trix-button { + border: 0; + padding: var(--bs-padding) + } + } +} + +[data-bs-theme=dark] { + .trix-button-row { + .trix-button-group { + .trix-button { + background-color: transparent !important; + filter: invert(100%) !important; + } + } + } +} +/* end fix trix dark mode */ + +.trix-content { + pre { + background-color: var(--bs-secondary-bg) !important; + color: var(--bs-secondary-color) !important; + border: var(--bs-border-width) solid var(--bs-border-color) !important; + border-radius: 0 !important; + } + +} + +/* trix-editor.trix-content { + min-height: 350px; + overflow-y: auto; +} */ + + + +@import "./layout"; \ No newline at end of file diff --git a/app/assets/stylesheets/layout.scss b/app/assets/stylesheets/layout.scss index 927375b..67b1497 100644 --- a/app/assets/stylesheets/layout.scss +++ b/app/assets/stylesheets/layout.scss @@ -41,4 +41,16 @@ // border: var(--bs-border-width) solid var(--bs-border-color); // border-radius: var(--bs-border-radius); // padding: var(--bs-padding); -// } \ No newline at end of file +// } + +.hover-row:hover { + background-color: var(--bs-tertiary-bg); +} + +.comment { + @extend .alert; + @extend .alert-warning; + + border: 0; + border-left: 4px solid var(--bs-warning); +} \ No newline at end of file diff --git a/app/controllers/checklist_entries_controller.rb b/app/controllers/checklist_entries_controller.rb index f4d3ce4..c0f7de4 100644 --- a/app/controllers/checklist_entries_controller.rb +++ b/app/controllers/checklist_entries_controller.rb @@ -24,7 +24,7 @@ class ChecklistEntriesController < ApplicationController @checklist_entry = ChecklistEntry.new(checklist_entry_params) if @checklist_entry.save - redirect_to @checklist_entry, notice: 'Checklist entry was successfully created.' + redirect_to @checklist_entry.checklist, notice: 'Checklist entry was successfully created.' else render :new, status: :unprocessable_entity end @@ -33,7 +33,8 @@ class ChecklistEntriesController < ApplicationController # PATCH/PUT /checklist_entries/1 def update if @checklist_entry.update(checklist_entry_params) - redirect_to @checklist_entry, notice: 'Checklist entry was successfully updated.', status: :see_other + redirect_to @checklist_entry.checklist, notice: 'Checklist entry was successfully updated.', + status: :see_other else render :edit, status: :unprocessable_entity end @@ -42,7 +43,12 @@ class ChecklistEntriesController < ApplicationController # DELETE /checklist_entries/1 def destroy @checklist_entry.destroy! - redirect_to checklist_entries_url, notice: 'Checklist entry was successfully destroyed.', status: :see_other + respond_to do |format| + format.html do + redirect_to checklist_entries_url, notice: 'Checklist entry was successfully destroyed.', status: :see_other + end + format.turbo_stream + end end private diff --git a/app/controllers/checklists_controller.rb b/app/controllers/checklists_controller.rb index 02a20b8..7d09926 100644 --- a/app/controllers/checklists_controller.rb +++ b/app/controllers/checklists_controller.rb @@ -24,7 +24,7 @@ class ChecklistsController < ApplicationController @checklist = Checklist.new(checklist_params) if @checklist.save - redirect_to @checklist, notice: 'Checklist was successfully created.' + redirect_to [:edit, @checklist], notice: 'Checklist was successfully created.' else render :new, status: :unprocessable_entity end diff --git a/app/controllers/reports_controller.rb b/app/controllers/reports_controller.rb index 206a387..341f183 100644 --- a/app/controllers/reports_controller.rb +++ b/app/controllers/reports_controller.rb @@ -8,6 +8,29 @@ class ReportsController < ApplicationController # GET /reports/1 def show + respond_to do |format| + format.html + format.pdf + format.xlsx do + response.headers['Content-Disposition'] = %(attachment; filename="#{filename(@report, extension: 'xlsx')}") + render + end + format.docx do + template = Sablon.template(Rails.root.join('lib/templates/docx/report.docx')) + context = { + person: OpenStruct.new(first_name: @report.name), + skills: [], + education: [], + career: [], + referees: [] + } + + template.render_to_file(Rails.root.join('tmp/output.docx'), context) + send_file Rails.root.join('tmp/output.docx'), + filename: filename(@report, extension: 'docx'), + type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' + end + end end # GET /reports/new @@ -60,4 +83,8 @@ class ReportsController < ApplicationController def report_params params.require(:report).permit(:name, :comment_html) end + + def filename(report, extension: 'html') + "#{report.name}-#{Time.current.strftime('%Y%m%d%H%M')}.#{extension}" + end end diff --git a/app/helpers/success_criteria_helper.rb b/app/helpers/success_criteria_helper.rb index 2f26b2f..2754b45 100644 --- a/app/helpers/success_criteria_helper.rb +++ b/app/helpers/success_criteria_helper.rb @@ -1,2 +1,13 @@ module SuccessCriteriaHelper + def success_criterion_result_icon_classes(sc) + if sc.passed? + 'bi bi-check text-success' + elsif sc.failed? + 'bi bi-exclamation-lg text-danger' + elsif sc.not_applicable? + 'bi bi-dash text-muted' + else + 'bi bi-question text-warning' + end + end end diff --git a/app/javascript/controllers/autosubmit_controller.js b/app/javascript/controllers/autosubmit_controller.js new file mode 100644 index 0000000..2e8e5b5 --- /dev/null +++ b/app/javascript/controllers/autosubmit_controller.js @@ -0,0 +1,8 @@ +import { Controller } from "@hotwired/stimulus" + +// Connects to data-controller="autosubmit" +export default class extends Controller { + connect() { + this.element.addEventListener('change', event => event.target.form.requestSubmit()); + } +} diff --git a/app/javascript/controllers/collapse_chevron_toggler_controller.js b/app/javascript/controllers/collapse_chevron_toggler_controller.js new file mode 100644 index 0000000..d64d54d --- /dev/null +++ b/app/javascript/controllers/collapse_chevron_toggler_controller.js @@ -0,0 +1,32 @@ +import { Controller } from "@hotwired/stimulus" + +// Connects to data-controller="collapse-chevron-toggler" +export default class extends Controller { + static targets = [ "icon" ]; + collapsible = null; + + connect() { + this.collapsible = window.document.getElementById(this.element.getAttribute('href').substring(1)); + this.setIcon(); + + this.collapsible.addEventListener('hide.bs.collapse', e => this.toggle()) + this.collapsible.addEventListener('show.bs.collapse', e => this.toggle()) + } + + setIcon(reverted = false) { + console.log('setIcon', this.collapsible) + if(this.collapsible.classList.contains('show')) { + this.iconTarget.classList.remove('bi-chevron-down') + this.iconTarget.classList.add('bi-chevron-up') + } else { + this.iconTarget.classList.remove('bi-chevron-up') + this.iconTarget.classList.add('bi-chevron-down') + } + } + + toggle() { + console.log('toggle', this.collapsible) + this.iconTarget.classList.toggle('bi-chevron-down'); + this.iconTarget.classList.toggle('bi-chevron-up'); + } +} diff --git a/app/javascript/controllers/index.js b/app/javascript/controllers/index.js index 47aa271..a8cca77 100644 --- a/app/javascript/controllers/index.js +++ b/app/javascript/controllers/index.js @@ -4,6 +4,12 @@ import { application } from "./application" +import AutosubmitController from "./autosubmit_controller" +application.register("autosubmit", AutosubmitController) + +import CollapseChevronTogglerController from "./collapse_chevron_toggler_controller" +application.register("collapse-chevron-toggler", CollapseChevronTogglerController) + import HelloController from "./hello_controller" application.register("hello", HelloController) diff --git a/app/models/check.rb b/app/models/check.rb index f4079d2..2b14c9f 100644 --- a/app/models/check.rb +++ b/app/models/check.rb @@ -1,4 +1,6 @@ class Check < ApplicationRecord + include RichTextTargetBlank + enum :level, %i[A AA AAA] has_rich_text :success_criterion_html diff --git a/app/models/checklist.rb b/app/models/checklist.rb index b5b2a02..084ded2 100644 --- a/app/models/checklist.rb +++ b/app/models/checklist.rb @@ -5,4 +5,6 @@ class Checklist < ApplicationRecord has_rich_text :description_html accepts_nested_attributes_for :checklist_entries, reject_if: :all_blank, allow_destroy: true + + delegate :empty?, to: :checklist_entries end diff --git a/app/models/checklist_entry.rb b/app/models/checklist_entry.rb index f030b00..0bde766 100644 --- a/app/models/checklist_entry.rb +++ b/app/models/checklist_entry.rb @@ -1,4 +1,18 @@ class ChecklistEntry < ApplicationRecord belongs_to :checklist belongs_to :check + + before_validation :set_position + after_validation :normalize_positions + + def set_position + self.position ||= checklist.checklist_entries.maximum(:position).to_i + 1 + end + + def normalize_positions + checklist.checklist_entries.where.not(id:).find_by(position:)&.update_attribute(:position, position_was) + # checklist.checklist_entries.order(:position).each_with_index do |entry, index| + # entry.update_column(:position, index + 1) if entry.position != index + 1 + # end + end end diff --git a/app/models/concerns/rich_text_target_blank.rb b/app/models/concerns/rich_text_target_blank.rb new file mode 100644 index 0000000..0405983 --- /dev/null +++ b/app/models/concerns/rich_text_target_blank.rb @@ -0,0 +1,20 @@ +module RichTextTargetBlank + extend ActiveSupport::Concern + + class_methods do + # Override has_rich_text to include target="_blank" functionality + def has_rich_text(name) + super # Call the original has_rich_text to set up the rich text association + + # Define the before_save callback to modify the links + before_save do + rich_text_attribute = send(name) + if rich_text_attribute.present? + doc = Nokogiri::HTML::DocumentFragment.parse(rich_text_attribute.body.to_html) + doc.css('a').each { |a| a['target'] ||= '_blank' } + rich_text_attribute.body = doc.to_html + end + end + end + end +end diff --git a/app/models/element.rb b/app/models/element.rb index afa8796..dfa3a5e 100644 --- a/app/models/element.rb +++ b/app/models/element.rb @@ -3,6 +3,8 @@ class Element < ApplicationRecord has_rich_text :description_html - belongs_to :report + belongs_to :report, touch: true has_many :success_criteria, dependent: :destroy + + validates :path, :title, presence: true end diff --git a/app/models/report.rb b/app/models/report.rb index d2a3e60..b1a87fb 100644 --- a/app/models/report.rb +++ b/app/models/report.rb @@ -1,5 +1,7 @@ class Report < ApplicationRecord + has_rich_text :comment_html + has_many :elements, dependent: :destroy - has_rich_text :comment_html + validates :name, presence: true end diff --git a/app/models/success_criterion.rb b/app/models/success_criterion.rb index 524baa3..de63a93 100644 --- a/app/models/success_criterion.rb +++ b/app/models/success_criterion.rb @@ -1,8 +1,9 @@ class SuccessCriterion < ApplicationRecord enum :result, %i[passed failed not_applicable] + enum :level, %i[A AA AAA] has_rich_text :comment_html has_rich_text :description_html - belongs_to :element + belongs_to :element, touch: true end diff --git a/app/views/checklist_entries/_checklist_entry.html.erb b/app/views/checklist_entries/_checklist_entry.html.erb index ab9404e..79e526d 100644 --- a/app/views/checklist_entries/_checklist_entry.html.erb +++ b/app/views/checklist_entries/_checklist_entry.html.erb @@ -1,8 +1,10 @@ -
-

+

+
+ <%= button_to tag.i(class: "bi bi-arrow-down"), checklist_entry_path(checklist_entry), method: :patch, class: "btn btn-link p-0 float-start", data: { turbo_frame: "checklist_entries" }, params: { checklist_entry: { position: checklist_entry.position + 1 }} %> + <%= button_to tag.i(class: "bi bi-arrow-up"), checklist_entry_path(checklist_entry), method: :patch, class: "btn btn-link p-0 pe-3 float-start", data: { turbo_frame: "checklist_entries" }, params: { checklist_entry: { position: checklist_entry.position - 1 }} %> <%= button_to tag.i(class: "bi bi-trash"), checklist_entry_path(checklist_entry), method: :delete, class: "btn btn-link p-0 ps-3 float-end" %> - <%= link_to "edit", edit_checklist_entry_path(checklist_entry), class: "float-end" %> - <%= checklist_entry.position %> + <%= link_to tag.i(class: "bi bi-pencil"), edit_checklist_entry_path(checklist_entry), class: "float-end" %> + <%# checklist_entry.position %> <%= link_to(checklist_entry.check.name, checklist_entry.check, data: { turbo_frame: "_top" }) %> -

+
diff --git a/app/views/checklist_entries/_form.html.erb b/app/views/checklist_entries/_form.html.erb index 3f5a7e7..51f68a4 100644 --- a/app/views/checklist_entries/_form.html.erb +++ b/app/views/checklist_entries/_form.html.erb @@ -1,6 +1,7 @@ <%= bootstrap_form_with(model: checklist_entry, layout: :horizontal) do |form| %> + <%= link_to "Abbrechen", checklist_entry.persisted? ? checklist_entry : checklist_entry.checklist, class: "btn btn-outline-secondary float-end", data: { turbo_frame: "checklist_entries" } %> + <%= form.submit class: "btn btn-secondary float-end me-2" %> <%= form.hidden_field :checklist_id %> <%= form.collection_select :check_id, Check.all.order(:name), :id, :name %> - <%= form.number_field :position %> - <%= form.submit %> + <%# form.number_field :position %> <% end %> \ No newline at end of file diff --git a/app/views/checklist_entries/destroy.turbo_stream.erb b/app/views/checklist_entries/destroy.turbo_stream.erb new file mode 100644 index 0000000..6e7c01a --- /dev/null +++ b/app/views/checklist_entries/destroy.turbo_stream.erb @@ -0,0 +1 @@ +<%= turbo_stream.remove dom_id(@checklist_entry) %> \ No newline at end of file diff --git a/app/views/checklist_entries/edit.html.erb b/app/views/checklist_entries/edit.html.erb index 25e960f..515099d 100644 --- a/app/views/checklist_entries/edit.html.erb +++ b/app/views/checklist_entries/edit.html.erb @@ -2,7 +2,7 @@ <%= turbo_frame_tag dom_id(@checklist_entry, :frame) do %> <%= render "form", checklist_entry: @checklist_entry %> - <%= link_to "cancel", @checklist_entry %> + <% end %>
diff --git a/app/views/checklist_entries/index.html.erb b/app/views/checklist_entries/index.html.erb index d2cffb6..41c2d13 100644 --- a/app/views/checklist_entries/index.html.erb +++ b/app/views/checklist_entries/index.html.erb @@ -1,32 +1,12 @@

<%= t("scaffold.pagetitle_index", model: ChecklistEntry.model_name.human(count: 2)) %>

- - - - - - - - - - - - - - <% @checklist_entries.each do |checklist_entry| %> - - - - - - - - - - +<%= turbo_frame_tag "checklist_entries" do %> + <% @checklist_entries.each do |entry| %> + <%= turbo_frame_tag dom_id(entry, :frame) do %> + <%= render entry %> <% end %> - -
<%= ChecklistEntry.human_attribute_name(:id) %><%= ChecklistEntry.human_attribute_name(:checklist_id) %><%= ChecklistEntry.human_attribute_name(:check_id) %><%= ChecklistEntry.human_attribute_name(:position) %>
<%= link_to(checklist_entry.id, url_for(checklist_entry)) %><%= link_to(checklist_entry.checklist_id, url_for(checklist_entry)) %><%= link_to(checklist_entry.check_id, url_for(checklist_entry)) %><%= link_to(checklist_entry.position, url_for(checklist_entry)) %>
+ <% end %> +<% end %>
<%= link_to t("scaffold.link_new", model: ChecklistEntry.model_name.human), new_checklist_entry_path %> diff --git a/app/views/checklist_entries/new.html.erb b/app/views/checklist_entries/new.html.erb index 7fedce1..e65e082 100644 --- a/app/views/checklist_entries/new.html.erb +++ b/app/views/checklist_entries/new.html.erb @@ -1,7 +1,8 @@

<%= t("scaffold.pagetitle_new", model: ChecklistEntry.model_name.human) %>

-<%= turbo_frame_tag "new_checklist_entry" do %> +<%= turbo_frame_tag "checklist_entries" do %> <%= render "form", checklist_entry: @checklist_entry %> + <%= render @checklist_entry.checklist.checklist_entries.reject { _1 == @checklist_entry } %> <% end %>
diff --git a/app/views/checklists/_checklist.html.erb b/app/views/checklists/_checklist.html.erb index 70e1a96..643ea9d 100644 --- a/app/views/checklists/_checklist.html.erb +++ b/app/views/checklists/_checklist.html.erb @@ -1,28 +1,3 @@
-

- Code: - <%= checklist.code %> -

- -

- Name: - <%= checklist.name %> -

- -

- Description (formatted): - <%= checklist.description_html %> -

- -

- Checks -

    - <% checklist.checklist_entries.each do |entry| %> -
  • - <%= entry.position %> <%= entry.check.name %> -
  • - <% end %> -
-

- + <%= checklist.description_html %>
diff --git a/app/views/checklists/_form.html.erb b/app/views/checklists/_form.html.erb index 55696ca..c891179 100644 --- a/app/views/checklists/_form.html.erb +++ b/app/views/checklists/_form.html.erb @@ -1,6 +1,6 @@ <%= bootstrap_form_with(model: checklist) do |form| %> - <%= form.text_field :code %> + <%# form.text_field :code %> <%= form.text_field :name %> - <%= form.rich_text_area :description_html %> + <%= form.rich_text_area :description_html, rows: 12 %> <%= form.submit %> <% end %> \ No newline at end of file diff --git a/app/views/checklists/edit.html.erb b/app/views/checklists/edit.html.erb index 7ffb0eb..eded8e8 100644 --- a/app/views/checklists/edit.html.erb +++ b/app/views/checklists/edit.html.erb @@ -1,24 +1,7 @@

<%= t("scaffold.pagetitle_edit", model: Checklist.model_name.human) %>

-
-
- <%= render "form", checklist: @checklist %> -
-
-

Checks

-
- <%= turbo_frame_tag "new_checklist_entry" do %> - <%= link_to tag.i(class: "bi bi-plus"), new_checklist_entry_path(checklist_id: @checklist.id), class: "btn btn-primary", data: { turbo_frame: "new_checklist_entry"} %> - <% end %> -
- <% @checklist.checklist_entries.each do |entry| %> - <%= turbo_frame_tag dom_id(entry, :frame) do %> - <%= render entry %> - <% end %> - <% end %> -
-
+<%= render "form", checklist: @checklist %>
<%= link_to t("scaffold.link_show", model: Checklist.model_name.human), @checklist %> diff --git a/app/views/checklists/index.html.erb b/app/views/checklists/index.html.erb index 89d5781..f0ed6bd 100644 --- a/app/views/checklists/index.html.erb +++ b/app/views/checklists/index.html.erb @@ -5,8 +5,6 @@ <%= Checklist.human_attribute_name(:id) %> - <%= Checklist.human_attribute_name(:code) %> - <%= Checklist.human_attribute_name(:name) %> <%= Checklist.human_attribute_name(:description_html) %> @@ -17,8 +15,6 @@ <%= link_to(checklist.id, url_for(checklist)) %> - <%= link_to(checklist.code, url_for(checklist)) %> - <%= link_to(checklist.name, url_for(checklist)) %> <%= link_to(truncate(strip_tags(checklist.description_html.to_s)), url_for(checklist)) %> diff --git a/app/views/checklists/new.html.erb b/app/views/checklists/new.html.erb index 3894c80..510f845 100644 --- a/app/views/checklists/new.html.erb +++ b/app/views/checklists/new.html.erb @@ -2,6 +2,12 @@ <%= render "form", checklist: @checklist %> + <% @checklist.checklist_entries.each do |entry| %> + <%= turbo_frame_tag dom_id(entry, :frame) do %> + <%= render entry %> + <% end %> + <% end %> +
<%= link_to t("scaffold.link_index", model: Checklist.model_name.human(count: 2)), checklists_path %>
diff --git a/app/views/checklists/show.html.erb b/app/views/checklists/show.html.erb index 165fd7d..74eccd2 100644 --- a/app/views/checklists/show.html.erb +++ b/app/views/checklists/show.html.erb @@ -1,9 +1,29 @@ -

<%= t("scaffold.pagetitle_show", model: @checklist.class.model_name.human) %>

+

<%= "#{@checklist.name}" %>

+ +
+
+ <%= render @checklist %> +
+
+
+ <%= link_to tag.i(class: "bi bi-plus-lg"), new_checklist_entry_path(checklist_id: @checklist.id), class: "btn btn-primary float-end", data: { turbo_frame: "checklist_entries" } %> +

Checks

+
+
+ <%= turbo_frame_tag "new_checklist_entry" do %> + <% end %> +
+ <%= turbo_frame_tag "checklist_entries" do %> + <% @checklist.checklist_entries.each do |entry| %> + <%= turbo_frame_tag dom_id(entry, :frame) do %> + <%= render entry %> + <% end %> + <% end %> + <%= tag.i "Es sind (noch) keine Checks definiert." if @checklist.empty? %> + <% end %> +
+
-<%= render @checklist %> -
Dashboard
-  is
-  sidebar
<%= link_to t("scaffold.link_edit", model: @checklist.model_name.human), edit_checklist_path(@checklist) %> <%= link_to t("scaffold.link_index", model: @checklist.model_name.human(count: 2)), checklists_path %> diff --git a/app/views/elements/_element.html.erb b/app/views/elements/_element.html.erb index 579fdb2..a667966 100644 --- a/app/views/elements/_element.html.erb +++ b/app/views/elements/_element.html.erb @@ -1,16 +1,32 @@ -
-

- <%= element.title %>

-

- Path: - <%= element.path %> -

+
+ <%= turbo_frame_tag dom_id(element, :frame) do %> +
+

+ + + <%= element.title %> +
+ <%= element.path %> +
+

+ <%= link_to [:edit, element], class: "btn btn-link text-secondary" do %> + + + <% end %> +
+
+ + <%= element.description_html %> +
- <%= element.description_html %> + <% end %> <% element.success_criteria.each do |sc| %> <%= turbo_frame_tag(dom_id(sc, :frame)) do %> <%= render sc %> <% end %> <% end %> + <% if element.success_criteria.none? %> +

Es sind (noch) keine Erfolgskriterien definiert.

+ <% end %>
diff --git a/app/views/elements/_form.html.erb b/app/views/elements/_form.html.erb index f3fa56e..e73d914 100644 --- a/app/views/elements/_form.html.erb +++ b/app/views/elements/_form.html.erb @@ -1,8 +1,15 @@ -<%= bootstrap_form_with(model: element, data: { turbo_frame: "_top"}) do |form| %> +<%= bootstrap_form_with(model: element) do |form| %> <%= form.hidden_field :report_id %> - <%= form.collection_select(:checklist_id, Checklist.all, :id, :name) %> - <%= form.text_field :path %> +
+
+ <%= form.text_field :path %> +
+
+ <%= form.collection_select(:checklist_id, Checklist.all, :id, :name) %> +
+
<%= form.text_field :title %> <%= form.rich_text_area :description_html %> - <%= form.submit %> + <%= form.submit class: "btn btn-warning" %> + <%= link_to("Abbrechen", element.report, class: "btn btn-outline-secondary") %> <% end %> diff --git a/app/views/elements/edit.html.erb b/app/views/elements/edit.html.erb index 2252e24..dbdcb3a 100644 --- a/app/views/elements/edit.html.erb +++ b/app/views/elements/edit.html.erb @@ -1,6 +1,18 @@

<%= t("scaffold.pagetitle_edit", model: Element.model_name.human) %>

-<%= render "form", element: @element %> +<%= turbo_frame_tag dom_id(@element, :frame) do %> +
+
+

+ + + <%= @element.title %> +

+ <%= link_to(tag.i(class: "bi bi-pencil"), @element, class: "btn btn-link text-warning") %> +
+ <%= render "form", element: @element %> +
+<% end %>
<%= link_to t("scaffold.link_show", model: Element.model_name.human), @element %> diff --git a/app/views/elements/new.html.erb b/app/views/elements/new.html.erb index 32cb059..350f93b 100644 --- a/app/views/elements/new.html.erb +++ b/app/views/elements/new.html.erb @@ -1,8 +1,10 @@

<%= t("scaffold.pagetitle_new", model: Element.model_name.human) %>

<%= turbo_frame_tag "new_element_frame" do %> -

Element hinzufügen

- <%= render "form", element: @element %> +
+

Neues Element

+ <%= render "form", element: @element %> +
<% end %>
diff --git a/app/views/layouts/_navigation.html.erb b/app/views/layouts/_navigation.html.erb index ceff512..36067c1 100644 --- a/app/views/layouts/_navigation.html.erb +++ b/app/views/layouts/_navigation.html.erb @@ -1,5 +1,5 @@