Add politicians question type

This commit is contained in:
Charlotte Van Petegem 2025-05-17 11:58:07 +02:00
parent 4fe218166f
commit 2893f2bc53
Signed by: chvp
SSH key fingerprint: SHA256:s9rb8jBVfdahqWHuBAcHCBP1wmj4eYQXZfqgz4H3E9E
16 changed files with 101 additions and 33 deletions

View file

@ -1 +1,5 @@
/* Entry point for your PostCSS build */
.politicians-listing {
display: flex;
flex-direction: row;
}

View file

@ -20,4 +20,8 @@ class QuestionsController < ApplicationController
)
@answer.save!
end
def handle_politicians_answer
@answer.update!(data: params[:order])
end
end

View file

@ -1,2 +1,5 @@
module QuestionsHelper
def reorder_with_indices(array, indices)
array.sort {|a1, a2| indices.index(a1[1]) <=> indices.index(a2[1])}
end
end

View file

@ -1,8 +1,10 @@
// Entry point for the build script in your package.json
import initSimpleQuestions from './simple_input.js'
import initImageQuestions from './image_input.js'
import initPoliticianQuestions from './politicians_answer.js'
addEventListener("DOMContentLoaded", () => {
initSimpleQuestions()
initImageQuestions()
initPoliticianQuestions()
})

View file

@ -1,4 +1,4 @@
const csrfToken = document.querySelector("[name='csrf-token']").content
import { submitValue } from './submit_value.js'
export default function initImageQuestions() {
document.querySelectorAll('[data-behaviour="question_image_input"]').forEach((input) => {
@ -8,17 +8,10 @@ export default function initImageQuestions() {
const file = input.files[0];
const fileReader = new FileReader();
fileReader.onload = (ev) => {
fetch(submitUrl, {
method: 'PUT',
headers: {
"x-csrf-token": csrfToken,
"content-type": "application/json",
},
body: JSON.stringify({
filename: file.name,
mimetype: file.type,
data: ev.target.result.replace(/^data:[a-zA-Z0-9!#$%^&\\*_\-+{}|'.`~]+\/[a-zA-Z0-9!#$%^&\\*_\-+{}|'.`~]+;base64,/, ""),
})
submitValue(submitUrl, {
filename: file.name,
mimetype: file.type,
data: ev.target.result.replace(/^data:[a-zA-Z0-9!#$%^&\\*_\-+{}|'.`~]+\/[a-zA-Z0-9!#$%^&\\*_\-+{}|'.`~]+;base64,/, ""),
})
}
fileReader.readAsDataURL(file);

View file

@ -0,0 +1,20 @@
import { Sortable, Swap } from 'sortablejs'
import { submitValue } from './submit_value.js'
export default function initPoliticianQuestions() {
Sortable.mount(new Swap())
document.querySelectorAll('[data-behaviour="politicians_answer').forEach((list) => {
const submitUrl = list.dataset.submitUrl
Sortable.create(list, {
swap: true,
onUpdate: (event) => {
const newOrder = Array.from(event.to.children).map((el) => Number.parseInt(el.dataset.id))
submitValue(submitUrl, { order: newOrder })
}
})
})
}

View file

@ -1,23 +1,11 @@
import debounce from 'debounce'
const csrfToken = document.querySelector("[name='csrf-token']").content
import { submitValueDebounced } from './submit_value.js'
export default function initSimpleQuestions() {
document.querySelectorAll('[data-behaviour="question_simple_input"]').forEach((input) => {
const submitUrl = input.dataset.submitUrl
const submit = submitValueDebounced()
const handleInput = debounce(() => {
fetch(submitUrl, {
method: 'PUT',
headers: {
"x-csrf-token": csrfToken,
"content-type": "application/json",
},
body: JSON.stringify({ value: input.value }),
})
}, 300)
input.addEventListener('change', handleInput)
input.addEventListener('input', handleInput)
input.addEventListener('change', () => submit(submitUrl, {value: input.value}))
input.addEventListener('input', () => submit(submitUrl, {value: input.value}))
})
}

View file

@ -0,0 +1,18 @@
import debounce from 'debounce'
const csrfToken = document.querySelector("[name='csrf-token']").content
export function submitValue(url, value) {
fetch(url, {
method: 'PUT',
headers: {
"x-csrf-token": csrfToken,
"content-type": "application/json",
},
body: JSON.stringify(value),
})
}
export function submitValueDebounced() {
return debounce(submitValue, 300)
}

View file

@ -4,6 +4,7 @@
#
# id :integer not null, primary key
# answer_kind :integer not null
# data :text
# public_asset_path :string
# question_kind :integer default("simple"), not null
# text :text not null
@ -25,4 +26,6 @@ class Question < ApplicationRecord
belongs_to :section
has_one :answer
serialize :data, coder: JSON
end

View file

@ -1,3 +1,16 @@
<div>
This one's going to be hard...
<div class="politicians-listing">
<div>
<% question.data["left"].each do |l| %>
<p><%= l %></p>
<% end %>
</div>
<div data-behaviour="politicians_answer"
data-submit-url="<%= answer_question_url(question.id) %>"
>
<% answers = question.data["right"].each.with_index.to_a %>
<% answers = reorder_with_indices(answers, question.answer.data) if question.answer.present? %>
<% answers.each do |a, i| %>
<p data-id="<%= i %>"><%= a %></p>
<% end %>
</div>
</div>