diff --git a/app/assets/stylesheets/application.postcss.css b/app/assets/stylesheets/application.postcss.css index c155eda..b1470bd 100644 --- a/app/assets/stylesheets/application.postcss.css +++ b/app/assets/stylesheets/application.postcss.css @@ -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; +} diff --git a/app/controllers/questions_controller.rb b/app/controllers/questions_controller.rb index 4b56b49..0db46d4 100644 --- a/app/controllers/questions_controller.rb +++ b/app/controllers/questions_controller.rb @@ -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 diff --git a/app/controllers/sections_controller.rb b/app/controllers/sections_controller.rb index 7ad9a61..16edb04 100644 --- a/app/controllers/sections_controller.rb +++ b/app/controllers/sections_controller.rb @@ -4,6 +4,7 @@ class SectionsController < ApplicationController end def show + @sections = Section.all @section = Section.find(params[:id]) @questions = @section.questions.includes(:answer) end diff --git a/app/javascript/acrostic_answer.js b/app/javascript/acrostic_answer.js new file mode 100644 index 0000000..bee696f --- /dev/null +++ b/app/javascript/acrostic_answer.js @@ -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() + }) + }) + }) +} diff --git a/app/javascript/application.js b/app/javascript/application.js index fe5d93e..391047e 100644 --- a/app/javascript/application.js +++ b/app/javascript/application.js @@ -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() }) diff --git a/app/javascript/connections_answer.js b/app/javascript/connections_answer.js new file mode 100644 index 0000000..928692c --- /dev/null +++ b/app/javascript/connections_answer.js @@ -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 }) + } + }) + }) +} diff --git a/app/javascript/lyrics_answer.js b/app/javascript/lyrics_answer.js new file mode 100644 index 0000000..00a0e08 --- /dev/null +++ b/app/javascript/lyrics_answer.js @@ -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()) + }) + }) +} diff --git a/app/javascript/politicians_answer.js b/app/javascript/politicians_answer.js index f29e457..b9f0a6f 100644 --- a/app/javascript/politicians_answer.js +++ b/app/javascript/politicians_answer.js @@ -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 diff --git a/app/models/question.rb b/app/models/question.rb index 265a6c5..437e387 100644 --- a/app/models/question.rb +++ b/app/models/question.rb @@ -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 diff --git a/app/views/questions/_acrostic_form.html.erb b/app/views/questions/_acrostic_form.html.erb new file mode 100644 index 0000000..421bdfc --- /dev/null +++ b/app/views/questions/_acrostic_form.html.erb @@ -0,0 +1,22 @@ +<% max_position = question.data.map { |c| c["position"] }.max %> +<% index = -1 %> +
<%= i + 1 %>. <%= q %>
+<% end %> diff --git a/app/views/questions/_connections_form.html.erb b/app/views/questions/_connections_form.html.erb new file mode 100644 index 0000000..1de2f2c --- /dev/null +++ b/app/views/questions/_connections_form.html.erb @@ -0,0 +1,11 @@ ++ <%= 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 %> +
+ <% end %> +<%= @section.description %>
diff --git a/test/fixtures/questions.yml b/test/fixtures/questions.yml index 632ae52..de7fde0 100644 --- a/test/fixtures/questions.yml +++ b/test/fixtures/questions.yml @@ -421,3 +421,205 @@ photos_sint_kruis_winkel: text: De grens met Zelzate. answer_kind: <%= Question.answer_kinds[:image] %> question_kind: <%= Question.question_kinds[:simple] %> + +acrostic_acrostic: + section: acrostic + text: | + Wat is het oudste publiek toegankelijke museum van België? + Waar is Chokri Ben Chika tegen? + Waar kan je met je oldtimer binnen met een dagpas? + Wat is de bijnaam van de Gentenaar? + Wie kan je bewonderen in Poppentheater Pedrolino? + Welke dag gaan jullie het slechtst slapen? + Welke mini Gentse Feesten gaan door rond 15 augustus? + data: '<%= JSON.dump([ + { position: 3, length: 3 }, + { position: 5, length: 8 }, + { position: 3, length: 3 }, + { position: 7, length: 14 }, + { position: 4, length: 14 }, + { position: 3, length: 9 }, + { position: 11, length: 16 }, + ]) %>' + answer_kind: <%= Question.answer_kinds[:acrostic] %> + question_kind: <%= Question.question_kinds[:acrostic] %> + +connections_buildings: + section: connections + text: Gebouwen + data: '<%= + JSON.dump( + ["Huwelijk", "Burcht", "Middeleeuwen", "Nieuw slot", "UGent", "Wetenschap", "Museum", "Plantentuin", "Hotel", "Matexi", "Provincie", "Defensie"].shuffle + ) + %>' + answer_kind: <%= Question.answer_kinds[:connections] %> + question_kind: <%= Question.question_kinds[:simple] %> + +connections_food: + section: connections + text: Eten + data: '<%= + JSON.dump( + ["Bouillon", "Kip", "Kervel", "Brood", "Neus", "Kegel", "Framboos", "Kraam", "Kaneel", "Bruine suiker", "Hondsdolheid", "Sint-Hubertus"].shuffle + ) + %>' + answer_kind: <%= Question.answer_kinds[:connections] %> + question_kind: <%= Question.question_kinds[:simple] %> + +connections_sport: + section: connections + text: Sport + data: '<%= + JSON.dump( + ["Marathon", "Tokyo", "Somalië", "1989", "5K", "Roeien", "Nachez", "Blaarmeersen", "Voetbal", "Baro", "2013", "Arteveldestadion"].shuffle + ) + %>' + answer_kind: <%= Question.answer_kinds[:connections] %> + question_kind: <%= Question.question_kinds[:simple] %> + +translations_lousbirge: + section: translations + text: "we goan eu in Lousbirge steeke" + answer_kind: <%= Question.answer_kinds[:simple] %> + question_kind: <%= Question.question_kinds[:simple] %> + +translations_alvekoate: + section: translations + text: "da weete mijn kluuten uuk en 't zijn gîen alvekoate" + answer_kind: <%= Question.answer_kinds[:simple] %> + question_kind: <%= Question.question_kinds[:simple] %> + +translations_deursteeke: + section: translations + text: "de koarte deursteeke" + answer_kind: <%= Question.answer_kinds[:simple] %> + question_kind: <%= Question.question_kinds[:simple] %> + +translations_dampuurte: + section: translations + text: "'k goa eu mee eu muile teege de Dampuurte plakke, dadde viertien doage bruine ziepe schijt" + answer_kind: <%= Question.answer_kinds[:simple] %> + question_kind: <%= Question.question_kinds[:simple] %> + +translations_wielekes: + section: translations + text: "o mijn tante wielekes g'hat, 't was een kerre" + answer_kind: <%= Question.answer_kinds[:simple] %> + question_kind: <%= Question.question_kinds[:simple] %> + +translations_soepe: + section: translations + text: "veur em schept God den dag en moed'r schept de soepe" + answer_kind: <%= Question.answer_kinds[:simple] %> + question_kind: <%= Question.question_kinds[:simple] %> + +music_one: + section: music + text: "" + data: '<%= JSON.dump <