Finish remaining question types
This commit is contained in:
parent
0d54f756d8
commit
5bd1e821f7
20 changed files with 431 additions and 8 deletions
|
@ -3,3 +3,38 @@
|
|||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.acrostic-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.acrostic-offset,.acrostic-number {
|
||||
display: inline-block;
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
border: 2px solid transparent;
|
||||
}
|
||||
|
||||
.acrostic-input {
|
||||
padding: 0;
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
text-transform: uppercase;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.acrostic-column {
|
||||
background-color: lightgrey;
|
||||
}
|
||||
|
||||
.connections-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 25% 25% 25% 25%;
|
||||
}
|
||||
|
||||
.connections-element {
|
||||
border: 1px solid black;
|
||||
margin: 0.5em;
|
||||
padding: 1em;
|
||||
}
|
||||
|
|
|
@ -24,4 +24,16 @@ class QuestionsController < ApplicationController
|
|||
def handle_politicians_answer
|
||||
@answer.update!(data: params[:order])
|
||||
end
|
||||
|
||||
def handle_acrostic_answer
|
||||
@answer.update!(data: params[:data])
|
||||
end
|
||||
|
||||
def handle_connections_answer
|
||||
@answer.update!(data: params[:order])
|
||||
end
|
||||
|
||||
def handle_lyrics_answer
|
||||
@answer.update!(data: params[:data])
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,6 +4,7 @@ class SectionsController < ApplicationController
|
|||
end
|
||||
|
||||
def show
|
||||
@sections = Section.all
|
||||
@section = Section.find(params[:id])
|
||||
@questions = @section.questions.includes(:answer)
|
||||
end
|
||||
|
|
39
app/javascript/acrostic_answer.js
Normal file
39
app/javascript/acrostic_answer.js
Normal file
|
@ -0,0 +1,39 @@
|
|||
import { submitValueDebounced } from './submit_value.js'
|
||||
|
||||
export default function initAcrosticQuestions() {
|
||||
document.querySelectorAll('[data-behaviour="question_acrostic"]').forEach((acrostic) => {
|
||||
const submitUrl = acrostic.dataset.submitUrl
|
||||
const _submit = submitValueDebounced()
|
||||
|
||||
const allInputs = Array.from(acrostic.querySelectorAll(".acrostic-input"))
|
||||
|
||||
function submit() {
|
||||
const data = allInputs.map((input) => input.value)
|
||||
_submit(submitUrl, {data})
|
||||
}
|
||||
|
||||
allInputs.forEach((input) => {
|
||||
const index = Number.parseInt(input.dataset.index)
|
||||
const previous = acrostic.querySelector(`.acrostic-input[data-index="${index - 1}"]`)
|
||||
const next = acrostic.querySelector(`.acrostic-input[data-index="${index + 1}"]`)
|
||||
input.addEventListener('input', (event) => {
|
||||
if (event.data) {
|
||||
input.value = event.data[0]
|
||||
}
|
||||
submit()
|
||||
if (event.data) {
|
||||
if (next) {
|
||||
next.focus()
|
||||
}
|
||||
} else {
|
||||
if (previous) {
|
||||
previous.focus()
|
||||
}
|
||||
}
|
||||
})
|
||||
input.addEventListener('focus', () => {
|
||||
input.select()
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
|
@ -2,9 +2,19 @@
|
|||
import initSimpleQuestions from './simple_input.js'
|
||||
import initImageQuestions from './image_input.js'
|
||||
import initPoliticianQuestions from './politicians_answer.js'
|
||||
import initAcrosticQuestions from './acrostic_answer.js'
|
||||
import initConnectionsQuestions from './connections_answer.js'
|
||||
import initLyricsQuestions from './lyrics_answer.js'
|
||||
|
||||
import { Sortable, Swap } from 'sortablejs'
|
||||
|
||||
Sortable.mount(new Swap())
|
||||
|
||||
addEventListener("DOMContentLoaded", () => {
|
||||
initSimpleQuestions()
|
||||
initImageQuestions()
|
||||
initPoliticianQuestions()
|
||||
initAcrosticQuestions()
|
||||
initConnectionsQuestions()
|
||||
initLyricsQuestions()
|
||||
})
|
||||
|
|
19
app/javascript/connections_answer.js
Normal file
19
app/javascript/connections_answer.js
Normal file
|
@ -0,0 +1,19 @@
|
|||
import { Sortable } from 'sortablejs'
|
||||
|
||||
import { submitValue } from './submit_value.js'
|
||||
|
||||
export default function initConnectionsQuestions() {
|
||||
|
||||
|
||||
document.querySelectorAll('[data-behaviour="connections_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 })
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
21
app/javascript/lyrics_answer.js
Normal file
21
app/javascript/lyrics_answer.js
Normal file
|
@ -0,0 +1,21 @@
|
|||
import { submitValueDebounced } from './submit_value.js'
|
||||
|
||||
export default function initLyricsQuestions() {
|
||||
document.querySelectorAll('[data-behaviour="lyrics_answer"]').forEach((lyrics) => {
|
||||
const submitUrl = lyrics.dataset.submitUrl
|
||||
const _submit = submitValueDebounced()
|
||||
|
||||
const allInputs = Array.from(lyrics.querySelectorAll(".lyrics-input"))
|
||||
|
||||
function submit() {
|
||||
const data = allInputs.map((input) => input.value)
|
||||
_submit(submitUrl, {data})
|
||||
}
|
||||
|
||||
allInputs.forEach((input) => {
|
||||
const index = Number.parseInt(input.dataset.index)
|
||||
input.addEventListener('input', () => submit())
|
||||
input.addEventListener('change', () => submit())
|
||||
})
|
||||
})
|
||||
}
|
|
@ -1,11 +1,8 @@
|
|||
import { Sortable, Swap } from 'sortablejs'
|
||||
import { Sortable } 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
|
||||
|
||||
|
|
|
@ -21,8 +21,8 @@
|
|||
# section_id (section_id => sections.id)
|
||||
#
|
||||
class Question < ApplicationRecord
|
||||
enum :answer_kind, { simple: 0, image: 1, politicians: 2 }, prefix: true
|
||||
enum :question_kind, { simple: 0, video: 1 }, prefix: true
|
||||
enum :answer_kind, { simple: 0, image: 1, politicians: 2, acrostic: 3, connections: 4, lyrics: 5 }, prefix: true
|
||||
enum :question_kind, { simple: 0, video: 1, acrostic: 3 }, prefix: true
|
||||
|
||||
belongs_to :section
|
||||
has_one :answer
|
||||
|
|
22
app/views/questions/_acrostic_form.html.erb
Normal file
22
app/views/questions/_acrostic_form.html.erb
Normal file
|
@ -0,0 +1,22 @@
|
|||
<% max_position = question.data.map { |c| c["position"] }.max %>
|
||||
<% index = -1 %>
|
||||
<div class="acrostic-puzzle"
|
||||
data-behaviour="question_acrostic"
|
||||
data-submit-url="<%= answer_question_url(question.id) %>"
|
||||
>
|
||||
<% question.data.each.with_index do |constraints, i| %>
|
||||
<div class="acrostic-row">
|
||||
<span class="acrostic-number"><%= i + 1 %></span>
|
||||
<% (max_position - constraints["position"]).times do %>
|
||||
<span class="acrostic-offset"></span>
|
||||
<% end %>
|
||||
<% (constraints["position"] - 1).times do %>
|
||||
<%= render partial: "questions/acrostic_input", locals: {on_column: false, index: (index += 1), answer_data: question.answer&.data} %>
|
||||
<% end %>
|
||||
<%= render partial: "questions/acrostic_input", locals: {on_column: true, index: (index += 1), answer_data: question.answer&.data} %>
|
||||
<% (constraints["length"] - constraints["position"]).times do %>
|
||||
<%= render partial: "questions/acrostic_input", locals: {on_column: false, index: (index += 1), answer_data: question.answer&.data} %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
6
app/views/questions/_acrostic_input.html.erb
Normal file
6
app/views/questions/_acrostic_input.html.erb
Normal file
|
@ -0,0 +1,6 @@
|
|||
<%= tag.input class: {"acrostic-input": true, "acrostic-column": on_column},
|
||||
data: {index: index},
|
||||
value: answer_data&.then { |it| it[index] },
|
||||
type: "text",
|
||||
autocomplete: "off"
|
||||
%>
|
3
app/views/questions/_acrostic_show.html.erb
Normal file
3
app/views/questions/_acrostic_show.html.erb
Normal file
|
@ -0,0 +1,3 @@
|
|||
<% question.text.lines.each.with_index do |q, i| %>
|
||||
<p><strong><%= i + 1 %>.</strong> <%= q %></p>
|
||||
<% end %>
|
11
app/views/questions/_connections_form.html.erb
Normal file
11
app/views/questions/_connections_form.html.erb
Normal file
|
@ -0,0 +1,11 @@
|
|||
<div
|
||||
class="connections-grid"
|
||||
data-behaviour="connections_answer"
|
||||
data-submit-url="<%= answer_question_url(question.id) %>"
|
||||
>
|
||||
<% answers = question.data.each.with_index.to_a %>
|
||||
<% answers = reorder_with_indices(answers, question.answer.data) if question.answer.present? %>
|
||||
<% answers.each do |a, i| %>
|
||||
<span class="connections-element" data-id="<%= i %>"><%= a %></span>
|
||||
<% end %>
|
||||
</div>
|
15
app/views/questions/_lyrics_form.html.erb
Normal file
15
app/views/questions/_lyrics_form.html.erb
Normal file
|
@ -0,0 +1,15 @@
|
|||
<% index = -1 %>
|
||||
<div data-behaviour="lyrics_answer"
|
||||
data-submit-url="<%= answer_question_url(question.id) %>"
|
||||
>
|
||||
<% question.data.lines.each do |l| %>
|
||||
<% parts = l.split "{}", -1 %>
|
||||
<p>
|
||||
<%= render partial: "questions/lyrics_given_part", locals: {text: parts[0]} %>
|
||||
<% parts[1..].each do |text| %>
|
||||
<%= render partial: "questions/lyrics_input", locals: {index: (index += 1), answer_data: question.answer&.data} %>
|
||||
<%= render partial: "questions/lyrics_given_part", locals: {text: text} %>
|
||||
<% end %>
|
||||
</p>
|
||||
<% end %>
|
||||
</div>
|
3
app/views/questions/_lyrics_given_part.html.erb
Normal file
3
app/views/questions/_lyrics_given_part.html.erb
Normal file
|
@ -0,0 +1,3 @@
|
|||
<% if text.present? %>
|
||||
<span><%= text %></span>
|
||||
<% end %>
|
6
app/views/questions/_lyrics_input.html.erb
Normal file
6
app/views/questions/_lyrics_input.html.erb
Normal file
|
@ -0,0 +1,6 @@
|
|||
<%= tag.input class: "lyrics-input",
|
||||
data: {index: index},
|
||||
value: answer_data&.then { |it| it[index] },
|
||||
type: "text",
|
||||
autocomplete: "off"
|
||||
%>
|
|
@ -5,8 +5,8 @@
|
|||
<% end %>
|
||||
</div>
|
||||
<div data-behaviour="politicians_answer"
|
||||
data-submit-url="<%= answer_question_url(question.id) %>"
|
||||
>
|
||||
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| %>
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
<%= link_to sections_url do %>Home<% end %>
|
||||
<% @sections.each do |section| %>
|
||||
<%= link_to section.title, section_url(section) %>
|
||||
<% end %>
|
||||
|
||||
<h4><%= @section.title %></h4>
|
||||
|
||||
<p><%= @section.description %></p>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue