Add politicians question type
This commit is contained in:
parent
4fe218166f
commit
2893f2bc53
16 changed files with 101 additions and 33 deletions
|
@ -1 +1,5 @@
|
|||
/* Entry point for your PostCSS build */
|
||||
.politicians-listing {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
|
|
@ -20,4 +20,8 @@ class QuestionsController < ApplicationController
|
|||
)
|
||||
@answer.save!
|
||||
end
|
||||
|
||||
def handle_politicians_answer
|
||||
@answer.update!(data: params[:order])
|
||||
end
|
||||
end
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
})
|
||||
|
|
|
@ -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);
|
||||
|
|
20
app/javascript/politicians_answer.js
Normal file
20
app/javascript/politicians_answer.js
Normal 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 })
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
|
@ -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}))
|
||||
})
|
||||
}
|
||||
|
|
18
app/javascript/submit_value.js
Normal file
18
app/javascript/submit_value.js
Normal 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)
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue