Cosmetics
Some checks failed
/ Run tests (push) Successful in 1m52s
/ Run system tests (push) Failing after 2m3s
/ Build, push and deploy image (push) Successful in 1m45s

This commit is contained in:
david 2024-11-11 05:00:51 +01:00
parent ee5dbcf33e
commit e569bcb246
21 changed files with 54 additions and 65 deletions

View file

@ -130,7 +130,7 @@ class ReportsController < ApplicationController
# Only allow a list of trusted parameters through. # Only allow a list of trusted parameters through.
def report_params def report_params
params.require(:report).permit(:name, :comment) params.require(:report).permit(:name, :comment, :url)
end end
def filename(report, extension: "html") def filename(report, extension: "html")

View file

@ -4,7 +4,6 @@ import * as bootstrap from 'bootstrap'
// Connects to data-controller="bs-scrollspy" // Connects to data-controller="bs-scrollspy"
export default class extends Controller { export default class extends Controller {
connect() { connect() {
// console.log(this.element)
const target = this.element.getAttribute("data-bs-scrollspy-target") const target = this.element.getAttribute("data-bs-scrollspy-target")
const scrollSpy = new bootstrap.ScrollSpy(this.element, { const scrollSpy = new bootstrap.ScrollSpy(this.element, {
target: target target: target

View file

@ -5,13 +5,10 @@ export default class extends Controller {
static targets = ["input", "button"] static targets = ["input", "button"]
connect() { connect() {
console.log("connect", this.inputTarget, this.buttonTarget)
this.inputTarget.addEventListener("input", e => this.onUrlInputChange(e)) this.inputTarget.addEventListener("input", e => this.onUrlInputChange(e))
} }
onUrlInputChange(event) { onUrlInputChange(event) {
console.log("connect", this.inputTarget, this.buttonTarget)
console.log(event, this.buttonTarget)
this.buttonTarget.href = this.inputTarget.value; this.buttonTarget.href = this.inputTarget.value;
this.buttonTarget.innerHTML = this.inputTarget.value; this.buttonTarget.innerHTML = this.inputTarget.value;
return true; return true;

View file

@ -2,20 +2,19 @@ import { Controller } from "@hotwired/stimulus"
// Connects to data-controller="collapse-chevron-toggler" // Connects to data-controller="collapse-chevron-toggler"
export default class extends Controller { export default class extends Controller {
static targets = [ "icon" ]; static targets = ["icon"];
collapsible = null; collapsible = null;
connect() { connect() {
this.collapsible = window.document.getElementById(this.element.getAttribute('href').substring(1)); this.collapsible = window.document.getElementById(this.element.getAttribute('href').substring(1));
this.setIcon(); this.setIcon();
this.collapsible.addEventListener('hide.bs.collapse', e => this.toggle()) this.collapsible.addEventListener('hide.bs.collapse', e => this.toggle())
this.collapsible.addEventListener('show.bs.collapse', e => this.toggle()) this.collapsible.addEventListener('show.bs.collapse', e => this.toggle())
} }
setIcon(reverted = false) { setIcon(reverted = false) {
console.log('setIcon', this.collapsible) if (this.collapsible.classList.contains('show')) {
if(this.collapsible.classList.contains('show')) {
this.iconTarget.classList.remove('bi-chevron-down') this.iconTarget.classList.remove('bi-chevron-down')
this.iconTarget.classList.add('bi-chevron-up') this.iconTarget.classList.add('bi-chevron-up')
} else { } else {
@ -25,7 +24,6 @@ export default class extends Controller {
} }
toggle() { toggle() {
console.log('toggle', this.collapsible)
this.iconTarget.classList.toggle('bi-chevron-down'); this.iconTarget.classList.toggle('bi-chevron-down');
this.iconTarget.classList.toggle('bi-chevron-up'); this.iconTarget.classList.toggle('bi-chevron-up');
} }

View file

@ -6,17 +6,20 @@ export default class extends Controller {
} }
openAll(e) { openAll(e) {
console.log(e) console.log("open all")
e.preventDefault(); e.preventDefault();
this.element.querySelectorAll("details").forEach(el => { const id = this.element.dataset["targetId"]
const el = document.getElementById(id)
el.querySelectorAll("details").forEach(el => {
el.setAttribute("open", "") el.setAttribute("open", "")
}) })
} }
closeAll(e) { closeAll(e) {
console.log(e)
e.preventDefault(); e.preventDefault();
this.element.querySelectorAll("details").forEach(el => { const id = this.element.dataset["targetId"]
const el = document.getElementById(id)
el.querySelectorAll("details").forEach(el => {
el.removeAttribute("open") el.removeAttribute("open")
}) })
} }

View file

@ -5,17 +5,16 @@ import { install } from '@github/hotkey'
export default class extends Controller { export default class extends Controller {
connect() { connect() {
// Install all the hotkeys on the page // Install all the hotkeys on the page
console.log("hotkey connect", this.element)
this.element.addEventListener("turbo:load", this.handleTurboLoad) this.element.addEventListener("turbo:load", this.handleTurboLoad)
for (const el of this.element.parentNode.querySelectorAll('[data-hotkey]')) { for (const el of this.element.parentNode.querySelectorAll('[data-hotkey]')) {
console.log(el) console.log(el.dataset)
install(el) install(el)
} }
} }
handleTurboLoad(event) { handleTurboLoad(event) {
for (const el of event.getTarget().querySelectorAll('[data-hotkey]')) { for (const el of event.getTarget().querySelectorAll('[data-hotkey]')) {
console.log(el) console.log(el.dataset)
install(el) install(el)
} }
} }

View file

@ -7,8 +7,7 @@ export default class extends Controller {
connect() { connect() {
const cookieValue = Cookie.get(this.COOKIE_NAME); const cookieValue = Cookie.get(this.COOKIE_NAME);
console.log("cookieValue", cookieValue); if (cookieValue) {
if(cookieValue) {
return true; return true;
} }
const darkMode = window.matchMedia("(prefers-color-scheme:dark)").matches ? "dark" : "light"; const darkMode = window.matchMedia("(prefers-color-scheme:dark)").matches ? "dark" : "light";

View file

@ -8,10 +8,8 @@ export default class extends Controller {
connect() { connect() {
this.element.style.cursor = "grab" this.element.style.cursor = "grab"
console.log("dataset", this.element.dataset)
if (this.element.dataset["linkedElementId"]) { if (this.element.dataset["linkedElementId"]) {
this.linkedElement = document.getElementById(this.element.dataset["linkedElementId"]) this.linkedElement = document.getElementById(this.element.dataset["linkedElementId"])
console.log("Has a linked element", this.linkedElement)
} }
new Sortable(this.element, { new Sortable(this.element, {
@ -29,7 +27,6 @@ export default class extends Controller {
let body = {} let body = {}
body[formName] = {} body[formName] = {}
body[formName][positionAttribute] = position body[formName][positionAttribute] = position
console.log("event", event, "url", url)
// Expect backend to update list items via turbo if necessary // Expect backend to update list items via turbo if necessary
put(url, { put(url, {
body: JSON.stringify(body), body: JSON.stringify(body),
@ -38,16 +35,13 @@ export default class extends Controller {
"Accept": "text/vnd.turbo-stream.html, text/html, application/xhtml+xml" "Accept": "text/vnd.turbo-stream.html, text/html, application/xhtml+xml"
} }
}) })
console.log(linkedElement)
if (linkedElement) { if (linkedElement) {
console.log("move linked", linkedElement)
let children = linkedElement.children let children = linkedElement.children
let child = children[event.oldIndex] let child = children[event.oldIndex]
let newAfter = children[event.newIndex] let newAfter = children[event.newIndex]
if (event.oldIndex < event.newIndex) { if (event.oldIndex < event.newIndex) {
newAfter = children[event.newIndex + 1] newAfter = children[event.newIndex + 1]
} }
console.log("move ", child, "before", newAfter)
child.parentNode.insertBefore(child, newAfter) child.parentNode.insertBefore(child, newAfter)
} }
} }

View file

@ -6,7 +6,6 @@ export default class extends Controller {
COOKIE_NAME = "modeTheme" COOKIE_NAME = "modeTheme"
connect() { connect() {
console.log("connect switcher", this.init())
} }
init() { init() {

View file

@ -10,18 +10,11 @@ export default class extends Controller {
isSubmitted = false isSubmitted = false
connect() { connect() {
console.log("connect unsaved-changes")
this.initialState = this.formState() this.initialState = this.formState()
console.log("usaved-changes connect ", this.cancelTargets)
window.addEventListener("beforeunload", (event) => this.leavingPage(event)) window.addEventListener("beforeunload", (event) => this.leavingPage(event))
document.addEventListener('turbo:before-visit', (e) => this.leavingPage(e)) document.addEventListener('turbo:before-visit', (e) => this.leavingPage(e))
this.element.addEventListener("submit", (_) => this.isSubmitted = true) this.element.addEventListener("submit", (_) => this.isSubmitted = true)
// this.cancelTargets.forEach(element => {
// console.log(element)
// element.addEventListener("onclick", (_) => this.reset())
// });
} }
formState() { formState() {
@ -31,17 +24,14 @@ export default class extends Controller {
} }
reset() { reset() {
console.log("reset")
this.initialState = this.formState() this.initialState = this.formState()
} }
hasChanged() { hasChanged() {
console.log("hasChanged result", this.initialState != this.formState())
return this.formState() != this.initialState return this.formState() != this.initialState
} }
leavingPage(event) { leavingPage(event) {
console.log(event.type)
if (this.isSubmitted || !this.hasChanged()) { if (this.isSubmitted || !this.hasChanged()) {
return return
} }

View file

@ -4,7 +4,7 @@ class Element < ApplicationRecord
has_rich_text :description has_rich_text :description
belongs_to :page, touch: true belongs_to :page, touch: true
has_many :success_criteria, dependent: :destroy has_many :success_criteria, -> { order(:position) }, dependent: :destroy
delegate :report, to: :page delegate :report, to: :page

View file

@ -7,6 +7,11 @@ class Page < ApplicationRecord
before_validation :set_position before_validation :set_position
before_update :update_positions, if: :position_changed? before_update :update_positions, if: :position_changed?
def full_url
return nil if report.url.blank? && url.blank?
[ "https:/", report.url&.sub(/.*:\/\//, ""), url&.sub(/^\//, "") ].compact_blank.join("/")
end
private private
def set_position def set_position

View file

@ -13,6 +13,9 @@
<i class="bi bi-pencil"> <i class="bi bi-pencil">
</i> </i>
<% end %> <% end %>
<%= button_to(element_path(element), method: :delete, class: "btn btn-link text-danger", data: { turbo_confirm: "Bist du sicher?"}) do %>
<i class="bi bi-trash"></i>
<% end %>
</div> </div>
<% if element.description %> <% if element.description %>
<div class="mb-3"> <div class="mb-3">
@ -20,9 +23,7 @@
</div> </div>
<% end %> <% end %>
<p class="actions"> <p class="actions">
<%= button_to(element_path(element), method: :delete, class: "btn btn-outline-danger", data: { turbo_confirm: "Bist du sicher?"}) do %>
<i class="bi bi-trash"></i>
<% end %>
</p> </p>
<% end %> <% end %>

View file

@ -1,11 +1,11 @@
li id=dom_id(element, :page_nav_row) data={ "sortable-url": element_path(element), "form-name": "element", "position-attribute": "position" } li id=dom_id(element, :page_nav_row) data={ "sortable-url": element_path(element), "form-name": "element", "position-attribute": "position" }
- if current_page - if current_page
=< link_to("##{dom_id(element)}", data: { "turbo": false }) do =< link_to("##{dom_id(element)}", data: { "turbo": false }) do
i.bi.bi-boxes.me-1 i.bi.bi-boxes.me-2
span id=dom_id(element, :page_nav_title) span id=dom_id(element, :page_nav_title)
= "#{element.number} #{element.title}" = "#{element.number} #{element.title}"
- else - else
=< link_to(report_path(element.report, page_id: element.page.id, anchor: dom_id(element)), data: { "turbo": false }) do =< link_to(report_path(element.report, page_id: element.page.id, anchor: dom_id(element)), data: { "turbo": false }) do
i.bi.bi-boxes.me-1 i.bi.bi-boxes.me-2
span id=dom_id(element, :page_nav_title) span id=dom_id(element, :page_nav_title)
=< "#{element.number} #{element.title}" =< "#{element.number} #{element.title}"

View file

@ -19,7 +19,7 @@ dl
dd Springe zum Anfang des Contents (Skip-Link, kann auf allen Seiten verwendet werden) dd Springe zum Anfang des Contents (Skip-Link, kann auf allen Seiten verwendet werden)
dt a dt a
dd Alle auf dd Alle auf
dt z dt s
dd Alle zu dd Alle zu
dt b dt b
dd Baum dd Baum

View file

@ -1,9 +1,5 @@
<div id="<%= dom_id page %>" class="mb-3" data-bs-scrollspy-target="#<%= dom_id(page.report, :page_nav_spy) %>" data-controller="bs-scrollspy"> <div id="<%= dom_id page %>" class="mb-3" data-bs-scrollspy-target="#<%= dom_id(page.report, :page_nav_spy) %>" data-controller="bs-scrollspy">
<div class="text-end"> <div id="element_list">
<a href="#" data-action="click->details-list#closeAll" data-controller="hotkey" data-hotkey="z">Alle zu [z]</a>
<a href="#" data-action="click->details-list#openAll" data-controller="hotkey" data-hotkey="a">Alle auf [a]</a>
</div>
<div id="element_list" data-controller="details-list">
<% page.elements.each do |element| %> <% page.elements.each do |element| %>
<%= render element %> <%= render element %>
<% end %> <% end %>

View file

@ -1,5 +1,6 @@
<%= bootstrap_form_with(model: report) do |form| %> <%= bootstrap_form_with(model: report) do |form| %>
<%= form.text_field :name %> <%= form.text_field :name %>
<%= form.text_field :url %>
<%= form.rich_text_area :comment %> <%= form.rich_text_area :comment %>
<%= form.submit %> <%= form.submit %>
<% end %> <% end %>

View file

@ -17,9 +17,13 @@ h1
=< @current_page.path =< @current_page.path
p p
'URL: 'URL:
= @current_page.url = safe_display(@current_page.full_url) { link_to(_1, _1, target: :_blank) }
p.actions p.actions
= button_to("Pfad \"#{@current_page.path}\" löschen", page_path(@current_page), method: :delete, class: "btn btn-outline-danger", form: {data: { turbo_confirm: "Bist du sicher?" }}) .d-flex.justify-content-end data-controller="details-list" data-target-id="element_list"
.btn-group.me-3
= link_to("Alle zu [s]", "#", data: { action: "click->details-list#closeAll", controller: :hotkey, hotkey: "s" }, class: "btn btn-outline-secondary")
= link_to("Alle auf [a]", "#", data: { action: "click->details-list#openAll", controller: :hotkey, hotkey: "a" }, class: "btn btn-outline-secondary")
= button_to(tag.i(class: "bi bi-trash"), page_path(@current_page), method: :delete, class: "btn btn-outline-danger", form: {data: { turbo_confirm: "Bist du sicher?" }})
.row .row
.col-lg-3.col-md-4.col-sm-12 .col-lg-3.col-md-4.col-sm-12
.page_nav.sticky-top .page_nav.sticky-top

View file

@ -2,20 +2,18 @@
= turbo_frame_tag(dom_id(success_criterion, :frame)) do = turbo_frame_tag(dom_id(success_criterion, :frame)) do
.row .row
.col .col
.position-relative .my-3.btn-group[role="group" aria-label="Resultat"]
.position-absolute.top-0.end-0.fw-bold = bootstrap_form_with(model: success_criterion, data: { controller: "autosubmit" }) do |form|
= button_to(tag.i(class: "bi bi-trash"), success_criterion, method: :delete, class: "btn btn-outline-danger", data: { turbo_confirm: "Bist du sicher?"}) = form.radio_button_without_bootstrap :result, :passed, class: "btn-check", autocomplete: "off", id: dom_id(success_criterion, :result_passed)
= success_criterion_edit_button(success_criterion, false) label.btn.btn-outline-success for=dom_id(success_criterion, :result_passed) Bestanden
.my-3.btn-group[role="group" aria-label="Resultat"] = form.radio_button_without_bootstrap :result, :failed, class: "btn-check", autocomplete: "off", id: dom_id(success_criterion, :result_failed)
= bootstrap_form_with(model: success_criterion, data: { controller: "autosubmit" }) do |form| label.btn.btn-outline-danger for=dom_id(success_criterion, :result_failed) Durchgefallen
= form.radio_button_without_bootstrap :result, :passed, class: "btn-check", autocomplete: "off", id: dom_id(success_criterion, :result_passed) = form.radio_button_without_bootstrap :result, :not_applicable, class: "btn-check", autocomplete: "off", id: dom_id(success_criterion, :result_not_applicable)
label.btn.btn-outline-success for=dom_id(success_criterion, :result_passed) Bestanden label.btn.btn-outline-secondary for=dom_id(success_criterion, :result_not_applicable) Nicht anwendbar
= form.radio_button_without_bootstrap :result, :failed, class: "btn-check", autocomplete: "off", id: dom_id(success_criterion, :result_failed) /= form.radio_button_without_bootstrap :result, nil, class: "btn-check", autocomplete: "off", id: dom_id(success_criterion, :result_not_applicable)
label.btn.btn-outline-danger for=dom_id(success_criterion, :result_failed) Durchgefallen /label.btn.btn-outline-secondary for=dom_id(success_criterion, :nil) Reset
= form.radio_button_without_bootstrap :result, :not_applicable, class: "btn-check", autocomplete: "off", id: dom_id(success_criterion, :result_not_applicable) = button_to(tag.i(class: "bi bi-trash"), success_criterion, method: :delete, class: "btn btn-link text-danger", data: { turbo_confirm: "Bist du sicher?"})
label.btn.btn-outline-secondary for=dom_id(success_criterion, :result_not_applicable) Nicht anwendbar = success_criterion_edit_button(success_criterion, false)
/= form.radio_button_without_bootstrap :result, nil, class: "btn-check", autocomplete: "off", id: dom_id(success_criterion, :result_not_applicable)
/label.btn.btn-outline-secondary for=dom_id(success_criterion, :nil) Reset
.row .row
.col .col
- if success_criterion.test_comment? - if success_criterion.test_comment?

View file

@ -0,0 +1,5 @@
class AddUrlToReports < ActiveRecord::Migration[8.0]
def change
add_column :reports, :url, :string
end
end

3
db/schema.rb generated
View file

@ -10,7 +10,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[8.0].define(version: 2024_11_11_011637) do ActiveRecord::Schema[8.0].define(version: 2024_11_11_034826) do
create_table "action_text_rich_texts", force: :cascade do |t| create_table "action_text_rich_texts", force: :cascade do |t|
t.string "name", null: false t.string "name", null: false
t.text "body" t.text "body"
@ -158,6 +158,7 @@ ActiveRecord::Schema[8.0].define(version: 2024_11_11_011637) do
t.string "name" t.string "name"
t.datetime "created_at", null: false t.datetime "created_at", null: false
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
t.string "url"
end end
create_table "sessions", force: :cascade do |t| create_table "sessions", force: :cascade do |t|