From 6ac639782792f2e469e86b7be43f08c4cdd8c3af Mon Sep 17 00:00:00 2001 From: KKrenz Date: Sun, 16 Nov 2014 16:57:01 +0100 Subject: [PATCH 01/22] implement dragdrop in models, services and views (only in new and show) --- .DS_Store | Bin 0 -> 12292 bytes app/.DS_Store | Bin 0 -> 12292 bytes app/assets/.DS_Store | Bin 0 -> 6148 bytes app/controllers/questions_controller.rb | 14 ++++- app/models/answer_pair.rb | 10 ++++ app/models/question.rb | 13 +++- app/models/survey.rb | 5 ++ app/parsers/gift_importer.rb | 2 + app/services/.DS_Store | Bin 0 -> 6148 bytes app/services/choice_question.rb | 4 ++ app/services/dragdrop_question.rb | 27 +++++++++ app/services/dragdrop_survey.rb | 31 ++++++++++ app/services/number_question.rb | 4 ++ app/services/text_question.rb | 4 ++ app/views/.DS_Store | Bin 0 -> 6148 bytes app/views/questions/.DS_Store | Bin 0 -> 6148 bytes app/views/questions/_answer_pair.html.erb | 5 ++ app/views/questions/_dragdrop_form.html.erb | 56 ++++++++++++++++++ ...gdrop_question_answer_pair_fields.html.erb | 7 +++ app/views/questions/index.html.erb | 4 +- app/views/questions/new.html.erb | 4 ++ app/views/questions/show.html.erb | 11 +++- config/.DS_Store | Bin 0 -> 12292 bytes config/initializers/secret_token.rb | 2 +- config/locales/defaults/de.yml | 1 + config/locales/defaults/en.yml | 1 + config/locales/views/questions.de.yml | 3 +- config/locales/views/questions.en.yml | 3 +- config/locales/views/surveys.de.yml | 5 ++ config/locales/views/surveys.en.yml | 6 +- features/.DS_Store | Bin 0 -> 6148 bytes lib/.DS_Store | Bin 0 -> 6148 bytes public/.DS_Store | Bin 0 -> 6148 bytes spec/.DS_Store | Bin 0 -> 6148 bytes spec/models/answer_pair_spec.rb | 5 ++ vendor/.DS_Store | Bin 0 -> 6148 bytes 36 files changed, 218 insertions(+), 9 deletions(-) create mode 100644 .DS_Store create mode 100644 app/.DS_Store create mode 100644 app/assets/.DS_Store create mode 100644 app/models/answer_pair.rb create mode 100644 app/services/.DS_Store create mode 100644 app/services/dragdrop_question.rb create mode 100644 app/services/dragdrop_survey.rb create mode 100644 app/views/.DS_Store create mode 100644 app/views/questions/.DS_Store create mode 100644 app/views/questions/_answer_pair.html.erb create mode 100644 app/views/questions/_dragdrop_form.html.erb create mode 100644 app/views/questions/_dragdrop_question_answer_pair_fields.html.erb create mode 100644 config/.DS_Store create mode 100644 features/.DS_Store create mode 100644 lib/.DS_Store create mode 100644 public/.DS_Store create mode 100644 spec/.DS_Store create mode 100644 spec/models/answer_pair_spec.rb create mode 100644 vendor/.DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..7b290f85bf013bd3921736668072c3be2d989499 GIT binary patch literal 12292 zcmeHMy^9k;6n~qRg$EH&@Z`+q8}&wQsEnIy0LuVi zVrI6G$3l}B&T=B9WXlFx1O1`jS*tbNftTn>4Ws}mKnjooqyQ=Krzn7DHcRFa=e|Ix zBn3!;|55?AKUkQVElV2+%eM|J_!R(c2Ag@pdVy8YTGE!K4TMDmlObHu3Rgp3F%033 z?Uw9UmNpPpxPu`tABJQ$^Q!~yMs{{mP%596i6z-?(P}53?1l!uiW2P^Fb6F zxYcTN>^A^D+V7`)pwMsNHjl)-ZseUn(PEBisDlTd!gk`r+XbTGl0F(Hi6}g00>+bt z2Dsor8)NI(laXilT^rlK*j~Rk@{7gKMk<{-mOXCfa`{~T8#>wI+LorR%Qa*LzND$enx57IxX)={ZezQgO#lbF^C%jXS-j z-{phK2Gh)$xxK>jbh=(Ftyt?@rP+!#-P|m$SXWA0vsvLy&OCdebnT|?K79P->9gkt zFJH01aC?*6AevXW4%{c{4 zu$4JM>fO9uGZ)@pGY8(TaEpT@jpMt}P#NG8GDt+j5h96IED;TliL0uG>)3}e46!y+ z86W*b#zY?tx28{G7KuK}e2i_R!szCA;w_ysMK$BQFvCrF`q2#V^j|Rl@66v#LyTX;aq%g5r56fRmNBN z#rRY%6iAEeGQ0oZIQsqn!hvd}04ea#DPUx(wQ2>!nm<&=BV@;bh4}$ymRP?)Snh%a z>%!XkbsTN@hauK2iIt@dghd3?Z+{UW?k>vnfpSjJ`9J>$m(G8_La87HNC8rS6d(mi Y0aAbzAO%PPQh*d71xNu>;O|u67u&WNUH||9 literal 0 HcmV?d00001 diff --git a/app/.DS_Store b/app/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..392367d31a6d72b7099cc4c9bb5559661af5dc67 GIT binary patch literal 12292 zcmeI1zfK!L5XNVL_>5>MDK8RDA|Zjq1DuG{N8$wnwiOUIXYnsmqDWWd0rChb@&IYl zr%aK8N8+2^Rpi~Bb43xvx7O{PZf15q|JL$(&LZNDZYKvKJ0dc~p>}%0;OcAcpSPpY9nS^MTOU%}4sn&K>blJL9kk2Ey(tZAt0iA;1lEiRRuLD@_e zmcEyJWrU$CTf@+kMI<`pd(bh*j-A__*1vciNrb5*izs%jk|ZM4v9CG?h-hWvnPj_l z_$l`r8j^g2MB-2Df7ALEcH%@oDb{|R|1Bd74cQuoiYy}4@l$mSqk=o^$rxHP7O#I< zF@~069YakKlj^xwJugI+Oyy&yWbMbR)N5#1$~CGld6T-;w$`msvBiE|So^X0ri?J^ zXKNT5vWP?nel&O`y#MQdaFD<%0_(xKqy7Ke{^$RzmY|OWNZ^SRa2uoJ(GlK6?5&Hp zqrG;G<2?=?8rKEuQ!x2<9M-qvu>bxr#CeTS&1s_Tg2fdKJ_zs_IFSGekN^pg011!) W36KB@kN^pg011!)36Q{}5_kYbb|TRL literal 0 HcmV?d00001 diff --git a/app/assets/.DS_Store b/app/assets/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..11a75f53b0891dcac715b22e96d8195e4c7ca845 GIT binary patch literal 6148 zcmeHK%}N6?5Kd~=G$tgIF;yp9}r zsh{?fs^2@u-ie=f0%M;_*`3&aa2B-&O=ta3#;G60t)5Db!WM)y>QNlZK~?tSFll(& zS&zcBqb4;D%d#!I>1+&#zgKJ yo!K1LS^;_qih^;O#z_hosuV*kmf{UiCEyom0J;V true + + embeds_many :answer_pairs + accepts_nested_attributes_for :answer_pairs, :allow_destroy => true field :name, type: String field :description, type: String @@ -55,6 +58,8 @@ def service NumberSurvey.new(self) when "exit_q" ExitSurvey.new(self) + when "dragdrop" + DragDropSurvey.new(self) else self end diff --git a/app/parsers/gift_importer.rb b/app/parsers/gift_importer.rb index 4ec9ad5..61095fd 100755 --- a/app/parsers/gift_importer.rb +++ b/app/parsers/gift_importer.rb @@ -27,6 +27,8 @@ def import (gift_file, user, tags) q = Question.new(type:"text").service elsif question.is_a? Gift::NumericQuestion q = Question.new(type:"number") + elsif question.is_a? Gift::DragDropQuestion + q = Question.new(type:"dragdrop") elsif question.is_a?(Gift::DescriptionQuestion) || question.is_a?(Gift::MatchQuestion) || question.is_a?(Gift::FillInQuestion) # Abfrage nicht unterstützter Typen errors << {"type" => "unsupported_type", "text" => question.text} diff --git a/app/services/.DS_Store b/app/services/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5008ddfcf53c02e82d7eee2e57c38e5672ef89f6 GIT binary patch literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0)nqoLN57a^ht6-`L7fs)lGwTD{B(dX|d`ilhr zj5E7iQCe>zQf6TGo1Mol`z7oH07ShTZvZ#|V4)J0Y-}b7#YxAcWITjIjgdnF5>m*b z-dHv}{v!kQ?QFP)E;J#7FW)b_irO;5=zDb4PO{wd-b87pJUcgU*>=UQEG$;ef|l$B zd6;*zde}Lk-a(kRB4Zy)+5WV{=qPFS&Yk65ndV`VHan^~iJO>mdYq)O?A2vAjkD80 zJCBn%Z>d3z!?JA4K6h67{SB|`ZhEyr)$P}6Xm4$MgMl-&t+n;do&8AO-rYYuK0Oa# zG~)t)P9;kQNAQZqgvH+kowO~}ON@>xM-`0B05iZ0Oa%jGbF(T_u^L_kGr$b|CIhrT zxTu7_!9t_jIOijp#w)i-4km8)o278TbG+dRv14 literal 0 HcmV?d00001 diff --git a/app/views/questions/.DS_Store b/app/views/questions/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..e0f58f23e91b8c63b1222b3657b89e592fd9ea2e GIT binary patch literal 6148 zcmeHK&r1SP5dNNdFuHilrb?Ofkj;w`mDJ{NdpuJn!Y zM5~QUoS}zPT;PVi103^Rnb6;Nd}myN56yYw7zM48zA;CVaelJep0BpGv`^cyy{Q{_ zx{U`GYYGN}fneYl7+}p7Y3vzB8w>;k!N7t6`95S+!Q8Pj)K3Q+y#f&HbgR&oyM*Lq zj=5uH$R0|vRHCIOzhWdyr$6(!+_5sWbR?abUOv#udQpFlUkcm@2DaYR~ar+XlN;Btd!ywRfYac W3}WtB8PY?E9|5Hynqc5h8TbNed_;!; literal 0 HcmV?d00001 diff --git a/app/views/questions/_answer_pair.html.erb b/app/views/questions/_answer_pair.html.erb new file mode 100644 index 0000000..b6c3803 --- /dev/null +++ b/app/views/questions/_answer_pair.html.erb @@ -0,0 +1,5 @@ +
  • + <%= answer_pair.answer1 %> + <%= answer_pair.answer2 %> + <%= icon_tag("ok") %> +
  • diff --git a/app/views/questions/_dragdrop_form.html.erb b/app/views/questions/_dragdrop_form.html.erb new file mode 100644 index 0000000..c6e7a48 --- /dev/null +++ b/app/views/questions/_dragdrop_form.html.erb @@ -0,0 +1,56 @@ +<%= semantic_form_for question, namespace: "dragdrop", html: { class: "form-inline ", id: "new_dragdrop_question" } do |form| %> +<%= error_msg_for question %> +
    +
    + <%= form.input :name, input_html: {class: "input-xxlarge"} %> +
    + <%= form.hidden_field :type, value: "dragdrop" %> + <%= hidden_field_tag :redirect_to_session, params[:redirect_to_session] %> +
    + <%= form.input :tags, input_html: { class: "input-xxlarge" , placeholder: "Tags" }, required: false %> + <% if current_user.question_tags && !current_user.question_tags.blank? %> + <%= select_tag "tags", options_for_select([[t("questions.add_from_your_tags"), '']] + current_user.question_tags.sort.map{ |t| [t, t]}), id: "dragdrop_select_tag" %> +
      + <% end %> +
    +
    + +
    +
    + +

    <%= t("surveys.edit.answer_pairs_for_dragdrop_survey") %>

    +
    +
    + <%= form.semantic_fields_for :answer_pairs, class: "form-inline" do |pair| %> + <%= render "dragdrop_question_answer_pair_fields", f: pair %> + <% end %> + +
    +
    +
    +
    +<%= form.hidden_field :collaborators_form, class:"collaborators-form" %> +<%= form.submit class: "btn btn-primary", id: "single_question_submit" %> +<% if params[:redirect_to_session] %> +
    +
    +<% end %>(<%= link_to t("questions.chart_notice"), "#chartNoticeModal", data: {toggle: "modal"} %>) +<% end %> +<% content_for :javascript do %> + +<% end %> diff --git a/app/views/questions/_dragdrop_question_answer_pair_fields.html.erb b/app/views/questions/_dragdrop_question_answer_pair_fields.html.erb new file mode 100644 index 0000000..6105b59 --- /dev/null +++ b/app/views/questions/_dragdrop_question_answer_pair_fields.html.erb @@ -0,0 +1,7 @@ +
    +
    + <%= link_to_remove_association icon_tag("minus-sign"), f %> + <%= f.text_field :answer1, placeholder: t("surveys.dragdrop_input_field_1") %> + <%= f.text_field :answer2, placeholder: t("surveys.dragdrop_input_field_2") %> +
    +
    diff --git a/app/views/questions/index.html.erb b/app/views/questions/index.html.erb index 2511848..07f1789 100644 --- a/app/views/questions/index.html.erb +++ b/app/views/questions/index.html.erb @@ -57,7 +57,9 @@
  • "> <%= link_to icon_tag("th") + t("type.text"), questions_path(tag: params[:tag], q_type: "text", public: params[:public], shared: params[:shared]) %>
  • "> -<%= link_to icon_tag("th") + t("type.number"), questions_path(tag: params[:tag], q_type: "number", public: params[:public], shared: params[:shared]) %>
  • + <%= link_to icon_tag("th") + t("type.number"), questions_path(tag: params[:tag], q_type: "number", public: params[:public], shared: params[:shared]) %> +
  • "> + <%= link_to icon_tag("move") + t("type.dragdrop"), questions_path(tag: params[:tag], q_type: "dragdrop", public: params[:public], shared: params[:shared]) %>
  • diff --git a/app/views/questions/new.html.erb b/app/views/questions/new.html.erb index dcca525..f750e45 100644 --- a/app/views/questions/new.html.erb +++ b/app/views/questions/new.html.erb @@ -9,6 +9,7 @@
  • <%= t "type.multi" %>
  • <%= t "type.text" %>
  • <%= t "type.number" %> BETA
  • +
  • <%= t "type.dragdrop" %>
  • @@ -26,6 +27,9 @@
    <%= render partial: @question_number.form_partial, locals: {question: @question_number} %>
    +
    + <%= render partial: @question_dragdrop.form_partial, locals: {question: @question_dragdrop} %> +
    diff --git a/app/views/questions/show.html.erb b/app/views/questions/show.html.erb index bbf94a4..1f2570c 100644 --- a/app/views/questions/show.html.erb +++ b/app/views/questions/show.html.erb @@ -13,7 +13,9 @@ <% elsif @question.type == "text" %> Text <% elsif @question.type == "number" %> - <%= t("type_number") %> + <%= t("questions.show.type_number") %> +<% elsif @question.type == "dragdrop" %> + Drag and Drop <% end %>

    Tags: <%= @question.tags_array.join(", ") %>

    @@ -26,7 +28,12 @@ <% end %> - +<% if @question.has_answer_pairs? %> + <%= t("surveys.show.answer_pairs") %> +
      + <%= render partial: "answer_pair", collection: @question.answer_pairs %> +
    +<% end %> <% if @question.can_be_accessed_by?(current_user) %> <%= link_to t("edit"), edit_question_path(@question), class: "btn btn-small" %> diff --git a/config/.DS_Store b/config/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..abed5158dc13d06d46567219ab069ae26297ac6f GIT binary patch literal 12292 zcmeI1!EVz)5Qb+=-hl%L zjywggQ2v=+p{%{GazGIh|3I_tTo~Df z48_^#&}HT>F87u#36MaafadPU$k`Y8)KUIEms43v@uF_aqHYWL>DGFV`uNTYjzkWm zK(5~+=TCWm?|6^#eqd#_fo_KWPvxUDQpcmXi;nJ4rtsDXTlgnNaz8tYWBAYIJ!Z6o zW{xrRdpb&;)0d4ojR&;v;wVLDx0SBGIlC;|W&wYcC%@1Pj?uJ}$#ivFiu@?PeKx^8 zzSFIJ7jHLX$hG4~nCH^?EW-+T4Mut|D|v%@|NV()UO`!z^4iwXCsTKb*s$Rn7dM92etzB9aoL{b!Mk~!;Lo9QO7%)le_rZ?=LZvP9II% zi@)O$MZNb*qdvmw*FA89w!%(I?m1n}QS@UdX7T~+V`g`>OzRx>YNR`~6}7@z0HLA1 zx}oq7a6bR_PO*@{?g%{aL!D^;|7`gE|Ly|fNF+c4J15}wCzq3R3>$LmUI3bFXQ)@G zTGVgttx3?Ri=MZqIqaW53~`)=Yk9D1Z*c{MF9Hk$8xkM^5+DH*AOR8}0TLhq5+DH* OAOR8}0TTGD1bzdJ!YtkZ literal 0 HcmV?d00001 diff --git a/config/initializers/secret_token.rb b/config/initializers/secret_token.rb index 728a26d..ee73c01 100755 --- a/config/initializers/secret_token.rb +++ b/config/initializers/secret_token.rb @@ -4,4 +4,4 @@ # If you change this key, all old signed cookies will become invalid! # Make sure the secret is at least 30 characters and all random, # no regular words or you'll be exposed to dictionary attacks. -Eclickr::Application.config.secret_token = '' +Eclickr::Application.config.secret_token = '29449u94bu4b9u804bu0evf8ubvdufjdfjdf44521s5142s125ddadada15215' diff --git a/config/locales/defaults/de.yml b/config/locales/defaults/de.yml index e10353e..6e44603 100644 --- a/config/locales/defaults/de.yml +++ b/config/locales/defaults/de.yml @@ -80,6 +80,7 @@ de: choice: "Auswahlfrage" single: "Single Choice" multi: "Multiple Choice" + dragdrop: "Drag and Drop" truefalse: "Wahr/Falsch-Frage" yesno: "Ja/Nein-Frage" agree: "Zustimmen/Nicht zustimmen-Frage" diff --git a/config/locales/defaults/en.yml b/config/locales/defaults/en.yml index 84b2655..56b4106 100644 --- a/config/locales/defaults/en.yml +++ b/config/locales/defaults/en.yml @@ -79,6 +79,7 @@ en: choice: "Choice Question" single: "Single Choice" multi: "Multiple Choice" + dragdrop: "Drag and Drop" truefalse: "True/False Question" yesno: "Yes/No Question" agree: "Agree/Disagree Question" diff --git a/config/locales/views/questions.de.yml b/config/locales/views/questions.de.yml index 0071b85..9ff52fb 100644 --- a/config/locales/views/questions.de.yml +++ b/config/locales/views/questions.de.yml @@ -28,8 +28,9 @@ de: show: add_to_own: Zu eigenen Fragen hinzufügen shared_question: "Für Sie von %{by} freigegebene Frage" + type_number: Numerisch new: - please_choose_question_type_to_continue: "Bitte wählen Sie links einen Fragetyp (Single/Multiple-Choice, Text oder Numerisch) aus." + please_choose_question_type_to_continue: "Bitte wählen Sie links einen Fragetyp (Single/Multiple-Choice, Text, Numerisch oder Drag-and-Drop) aus." comments: placeholder: Geben Sie hier Ihren Kommentar ein. show_session: dazugehörige Session/Umfrage anzeigen diff --git a/config/locales/views/questions.en.yml b/config/locales/views/questions.en.yml index 213fb29..c0dd969 100644 --- a/config/locales/views/questions.en.yml +++ b/config/locales/views/questions.en.yml @@ -24,10 +24,11 @@ en: edit_question: Edit question transform: "Transform into %{kind}-Choice question" new: - please_choose_question_type_to_continue: "Please choose a question type (single/multiple choice, text, numerical) on the left hand side." + please_choose_question_type_to_continue: "Please choose a question type (single/multiple choice, text, numerical, drag and drop) on the left hand side." show: add_to_own: Add to own questions shared_question: "shared question from %{by}" + type_number: Numerical comments: placeholder: Enter your comment here. show_session: show related survey diff --git a/config/locales/views/surveys.de.yml b/config/locales/views/surveys.de.yml index e412e6a..e41362c 100755 --- a/config/locales/views/surveys.de.yml +++ b/config/locales/views/surveys.de.yml @@ -8,7 +8,9 @@ de: correct_answer: Korrekte Antwort edit_survey: Umfrage bearbeiten add_option: Antwortmöglichkeit hinzufügen + add_answer_pair: Antwortpaar hinzufügen options_for_survey: Antwortmöglichkeiten für diese Umfrage + answer_pairs_for_dragdrop_survey: Antwortpaare für diese Umfrage changed: header: Vergleich des Antwortverhaltens wait: "Einen Moment bitte, Daten werden berechnet" @@ -40,6 +42,7 @@ de: end: Ende der Abstimmzeit time_left: "Zeit übrig" options: Antwortmöglichkeiten + answer_pairs: Antwortpaare stop1: Stoppen start1: Jetzt starten continue1: Fortsetzen @@ -63,4 +66,6 @@ de: add_field_notice: "Bei dieser Umfrage können Sie beliebig viele Antworten eingeben." number_input_field: notice: "Zahl bitte ohne 1.000er-Trennzeichen eingeben, z. B. 42,7" + dragdrop_input_field_1: "Das gehört..." + dragdrop_input_field_2: "...zu dem." diff --git a/config/locales/views/surveys.en.yml b/config/locales/views/surveys.en.yml index 49e65f7..22d4fd2 100755 --- a/config/locales/views/surveys.en.yml +++ b/config/locales/views/surveys.en.yml @@ -1,4 +1,3 @@ -# nothing en: surveys: exit_question: Exit question @@ -9,7 +8,9 @@ en: correct_answer: Correct answer edit_survey: Edit survey add_option: Add option + add_answer_pair: Add answer pair options_for_survey: Answer options for this survey + answer_pairs_for_dragdrop_survey: Answer pairs for this survey changed: header: Comparison of voting behaviour wait: "One moment please, gathering data" @@ -41,6 +42,7 @@ en: end: end of survey time_left: time left options: options + answer_pairs: answer pairs stop1: stop start1: start now continue1: continue @@ -64,4 +66,6 @@ en: add_field_notice: "In this survey, you can enter as many answers as you wish." number_input_field: notice: "Please enter the number without a thousands delimiter, e.g. 42.7" + dragdrop_input_field_1: "This belongs..." + dragdrop_input_field_2: "...to that." diff --git a/features/.DS_Store b/features/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..aa8cd9056b65df0d13140bef0446a18d62db93bb GIT binary patch literal 6148 zcmeHK!A`?440Xm3L*vj362~0)ft|QUQ@JDU13;`WDp6Xk?E!Jg=W*ndc#fl~U5f@6 zgpe&cuXXI$d6DXdh|IFh7DNdV&7h2vQw$@*^Q;4zM9Ue_gf(s{qX&AVoL&arYWRx` z@Yy9)Q-gD>sC#}nY&n%U$@+P-Sgp&Vk_}wFekZ0V(==CNg?50BXTWb2%pI;6=Mrz$#W2CY@kA5AF>o`UgHF(|bGdOSivm^OCu_L)V zv;Dj`oL5B|PzIENLkys2v&`m#Iw}LofHJUSfWHqG%IG3`!SLz85Uv2gDa=9e%y$Wn zu@PNFFNhh4kx-z7ns~)95)QkKelDUHlyEZf@?m0T6K^OcWXJk8xRY^$Iw}LoK%apl zc}=+gUw?i7?+59dGN26nD+bIoU8PHGDfZUE=D62d=pB@W{k-5V1P`GV!9^ literal 0 HcmV?d00001 diff --git a/lib/.DS_Store b/lib/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..c856bc7a89dbc7c6c3b810ddfe608a0745a00c6b GIT binary patch literal 6148 zcmeHKO-_O_5S>vp7&k0k_6ppfA)hDU0xF-8L-~4DOU*nP(ogwXO z`#PQWCA8lV5zqGhlxRXkV-!J_M#E&dNuBv*Az9bh(e~wOI$x|;o5n)FaY*)lN%yqH z?~&U3ulUuv>-zm}LG(vMo{!bLdc*n$Y$JBX4k910b=;&I zk17-h1ww&P;9n|$H(P9cZ5VYZ5DJ6>-wMe6kWd7(V=>gL1C^!#z!8Sk(3V_6e3D~! zEQVlUY_33aWlu5K+%cYfUUn>o=1%O%2YckN7d9|9^!RH48L6!-+g!9AD9Y(C8S^V% zCDu=Q?f@>1P)UZ;-9azv(pq2(Z zVgxP6d}4X2VWp_$6zuR3?8(7SC_$c%{)wbhNEJQ00NG>Y&(_#Z^ip?G2Bad089-lMa;nbLqKHk J;0pYy0v{5+mVE#K literal 0 HcmV?d00001 diff --git a/spec/.DS_Store b/spec/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..866ac8252667933ea8dd2903d129795a9feeb187 GIT binary patch literal 6148 zcmeHLOHRWu5FNJ_RCH6phGmXGZxB`C1ib)|pi-$JRX=RlqUY%yPT~#%QeNFWK@b)VF6MeQ_^G)XF>FekP zcY01O-P20fmq?$C8Zk1u5=NpYVuU(mlr!k)sKF|?rkskPKBFP3PZR|8neoqMo(`C= z6=rQ2&XfAUGkIiWG(>%5<|Sfebc|^yEBy;})VPYg7%rhD;bgRAIEg0-C)C6H7oLwD z?s-Z~yJ)2`Z@o2d@U=ElAM+bO)D3BOS#onVV z9mwPe034xM0@tz@0}CzymWsVclpvgM3iM5#9xy-EZ+tcU&u#tT;2h4$g<$xPii)xNr(!DjgIo@jvq&p-I p=Jg(>2{PS|<$||j{$D`?bp>AlOU2$JN)Yx#Ky0wg9QaWOJ^+>$#gPC2 literal 0 HcmV?d00001 diff --git a/spec/models/answer_pair_spec.rb b/spec/models/answer_pair_spec.rb new file mode 100644 index 0000000..eaadc5a --- /dev/null +++ b/spec/models/answer_pair_spec.rb @@ -0,0 +1,5 @@ +require 'spec_helper' + +describe AnswerPair do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/vendor/.DS_Store b/vendor/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..f73be21a4e59edfdb1ddd624ed6fb6def21fe7cf GIT binary patch literal 6148 zcmeHKOHRWu5PdEc6tU@&rLWK%L{&IJF90;CAhk47n^iYC9!rkI8_%dxV#5wpp_yv@ zocSd7bCl@-2+OWn0CNB{s^H|7LqWtZn#sg0;tc5?M;x}B#cI9ZwOOSYjOsh0cYSh7+}p7ncXS+=nOam&cK-g`94IdU}e}VrcVcl)B+HvG$-L)dI`yi zhLvHjNDn1wDp6B|wHQIuX^$3H8TN{rj$qA4uqOxWP(pe-?;le*LZ#@VGvEvi8MxBR zxzzuM@B9B@l3zIk&cMH7AWZ93z2ugxwq~1?S{td4R1t~m70)T0q*BaSDaH5HB(z7F V5G%u8krs;o5lA%n;0*jJ17ESOM_vE` literal 0 HcmV?d00001 From d27c553256a9fef91eaf5d635b0caf9dbf107c58 Mon Sep 17 00:00:00 2001 From: KKrenz Date: Tue, 18 Nov 2014 22:12:17 +0100 Subject: [PATCH 02/22] Take care of naming conventions --- app/controllers/questions_controller.rb | 13 ++++------- app/models/answer_pair.rb | 2 +- app/models/question.rb | 4 ++-- app/models/survey.rb | 2 +- app/parsers/gift_importer.rb | 2 +- ...drop_question.rb => drag_drop_question.rb} | 8 +++---- ...dragdrop_survey.rb => drag_drop_survey.rb} | 8 +++---- app/views/questions/.DS_Store | Bin 6148 -> 6148 bytes app/views/questions/_answer_pair.html.erb | 4 ++-- ...form.html.erb => _drag_drop_form.html.erb} | 22 +++++++++--------- ..._drop_question_answer_pair_fields.html.erb | 7 ++++++ ...gdrop_question_answer_pair_fields.html.erb | 7 ------ app/views/questions/index.html.erb | 4 ++-- app/views/questions/new.html.erb | 6 ++--- app/views/questions/show.html.erb | 2 +- config/locales/defaults/de.yml | 2 +- config/locales/defaults/en.yml | 2 +- config/locales/views/surveys.de.yml | 6 ++--- config/locales/views/surveys.en.yml | 6 ++--- 19 files changed, 51 insertions(+), 56 deletions(-) rename app/services/{dragdrop_question.rb => drag_drop_question.rb} (67%) rename app/services/{dragdrop_survey.rb => drag_drop_survey.rb} (79%) rename app/views/questions/{_dragdrop_form.html.erb => _drag_drop_form.html.erb} (68%) create mode 100644 app/views/questions/_drag_drop_question_answer_pair_fields.html.erb delete mode 100644 app/views/questions/_dragdrop_question_answer_pair_fields.html.erb diff --git a/app/controllers/questions_controller.rb b/app/controllers/questions_controller.rb index 2be3828..f45c527 100644 --- a/app/controllers/questions_controller.rb +++ b/app/controllers/questions_controller.rb @@ -1,5 +1,4 @@ class QuestionsController < ApplicationController - require_dependency "app/services/dragdrop_question.rb" before_filter :authenticate_user! before_filter :check_access, except: [:index, :new, :create, :show, :add_to_own, :import, :export, :upload, :share] @@ -100,7 +99,7 @@ def new @question_multi = MultipleChoiceQuestion.new.tap { |q| q.question_options.build } @question_text = TextQuestion.new @question_number = NumberQuestion.new #refactor this maybe? - @question_dragdrop = DragDropQuestion.new.tap { |q| q.answer_pairs.build } + @question_drag_drop = DragDropQuestion.new.tap { |q| q.answer_pairs.build } end def edit @@ -151,10 +150,6 @@ def create @question.add_setting("answers", params[:options]) end - if params[:answer_pairs] && @question.has_settings? - @question.add_setting("answers", params[:answer_pairs]) - end - respond_to do |format| if @question.save @event = Event.find_by_id_or_token(params[:redirect_to_session]) if params[:redirect_to_session] @@ -278,8 +273,8 @@ def set_js_tags params[:question][:tags] = params["text_question"][:tags] elsif params["number_question"] && params["number_question"][:tags] params[:question][:tags] = params["number_question"][:tags] - elsif params["dragdrop_question"] && params["dragdrop_question"][:tags] - params[:question][:tags] = params["dragdrop_question"][:tags] + elsif params["drag_drop_question"] && params["drag_drop_question"][:tags] + params[:question][:tags] = params["drag_drop_question"][:tags] end end @@ -294,6 +289,6 @@ def check_access end def question_params - params.require(:question).permit(:name, :type, :description, :tags, :public, :collaborators_form, question_options_attributes: [:name, :correct, :id, :_destroy], answer_pair_attributes: [:answer1, :answer2, :id, :_destroy]) + params.require(:question).permit(:name, :type, :description, :tags, :public, :collaborators_form, question_options_attributes: [:name, :correct, :id, :_destroy], answer_pairs_attributes: [:answer1, :answer2, :id, :_destroy]) end end diff --git a/app/models/answer_pair.rb b/app/models/answer_pair.rb index 55bbcd2..0787b35 100644 --- a/app/models/answer_pair.rb +++ b/app/models/answer_pair.rb @@ -1,7 +1,7 @@ class AnswerPair include Mongoid::Document - embedded_in :question + embedded_in :question, :inverse_of => :answer_pairs field :answer1, type: String field :answer2, type: String diff --git a/app/models/question.rb b/app/models/question.rb index 757066f..c9b6d7b 100644 --- a/app/models/question.rb +++ b/app/models/question.rb @@ -12,7 +12,7 @@ class Question field :settings, type: Hash, default: {} def self.question_types - ["multi", "single", "text", "exit_q", "number", "dragdrop"] + ["multi", "single", "text", "exit_q", "number", "drag_drop"] end validates :type, inclusion: {in: Question.question_types} @@ -45,7 +45,7 @@ def service MultipleChoiceQuestion.new(self) when "number" NumberQuestion.new(self) - when "dragdrop" + when "drag_drop" DragDropQuestion.new(self) else self diff --git a/app/models/survey.rb b/app/models/survey.rb index 4e363c1..aad0899 100755 --- a/app/models/survey.rb +++ b/app/models/survey.rb @@ -58,7 +58,7 @@ def service NumberSurvey.new(self) when "exit_q" ExitSurvey.new(self) - when "dragdrop" + when "drag_drop" DragDropSurvey.new(self) else self diff --git a/app/parsers/gift_importer.rb b/app/parsers/gift_importer.rb index 61095fd..a79f5f4 100755 --- a/app/parsers/gift_importer.rb +++ b/app/parsers/gift_importer.rb @@ -28,7 +28,7 @@ def import (gift_file, user, tags) elsif question.is_a? Gift::NumericQuestion q = Question.new(type:"number") elsif question.is_a? Gift::DragDropQuestion - q = Question.new(type:"dragdrop") + q = Question.new(type:"drag_drop") elsif question.is_a?(Gift::DescriptionQuestion) || question.is_a?(Gift::MatchQuestion) || question.is_a?(Gift::FillInQuestion) # Abfrage nicht unterstützter Typen errors << {"type" => "unsupported_type", "text" => question.text} diff --git a/app/services/dragdrop_question.rb b/app/services/drag_drop_question.rb similarity index 67% rename from app/services/dragdrop_question.rb rename to app/services/drag_drop_question.rb index ae321ca..5d61e29 100644 --- a/app/services/dragdrop_question.rb +++ b/app/services/drag_drop_question.rb @@ -1,8 +1,8 @@ class DragDropQuestion < GenericQuestion - def initialize(question = Question.new(type: "dragdrop")) - raise "type of question not correct" if question.type != "dragdrop" + def initialize(question = Question.new(type: "drag_drop")) + raise "type of question not correct" if question.type != "drag_drop" super - self.question.type = "dragdrop" unless self.question.persisted? + self.question.type = "drag_drop" unless self.question.persisted? end def has_options? @@ -18,7 +18,7 @@ def has_settings? end def form_partial - "dragdrop_form" + "drag_drop_form" end def to_survey diff --git a/app/services/dragdrop_survey.rb b/app/services/drag_drop_survey.rb similarity index 79% rename from app/services/dragdrop_survey.rb rename to app/services/drag_drop_survey.rb index e83e16e..4c32283 100644 --- a/app/services/dragdrop_survey.rb +++ b/app/services/drag_drop_survey.rb @@ -1,15 +1,15 @@ class DragDropSurvey < GenericSurvey def initialize(survey) - raise "type of survey (#{survey.type}) not correct" if survey.type != "dragdrop" + raise "type of survey (#{survey.type}) not correct" if survey.type != "drag_drop" super end def prompt - I18n.t "surveys.participate.dragdrop" + I18n.t "surveys.participate.drag_drop" end def participate_partial - "dragdrop_option" + "drag_drop_option" end # VIEW OPTIONS @@ -22,7 +22,7 @@ def has_answer_pairs? end def has_settings? - false + true end def results_comparable? diff --git a/app/views/questions/.DS_Store b/app/views/questions/.DS_Store index e0f58f23e91b8c63b1222b3657b89e592fd9ea2e..5008ddfcf53c02e82d7eee2e57c38e5672ef89f6 100644 GIT binary patch delta 70 zcmZoMXfc=|#>AjHu~2NHo+1YW5HK<@2y8ZFzQ(fIf%z8GW_AvK4xj>{$am(+{342+ UKzW7)kiy9(Jj$D6L{=~Z03S{czyJUM delta 368 zcmbVIy$-=(6g{mM?OKBB=0;GT`#&EEPjbR|J$}v>37)n-rtC(=g!4hT6 z;IS@ZNFyThXuT`CCuFM_#4xO11z1 diff --git a/app/views/questions/_answer_pair.html.erb b/app/views/questions/_answer_pair.html.erb index b6c3803..43ac62b 100644 --- a/app/views/questions/_answer_pair.html.erb +++ b/app/views/questions/_answer_pair.html.erb @@ -1,5 +1,5 @@
  • - <%= answer_pair.answer1 %> + <%= answer_pair.answer1 %> + - <%= answer_pair.answer2 %> - <%= icon_tag("ok") %>
  • diff --git a/app/views/questions/_dragdrop_form.html.erb b/app/views/questions/_drag_drop_form.html.erb similarity index 68% rename from app/views/questions/_dragdrop_form.html.erb rename to app/views/questions/_drag_drop_form.html.erb index c6e7a48..aa431e9 100644 --- a/app/views/questions/_dragdrop_form.html.erb +++ b/app/views/questions/_drag_drop_form.html.erb @@ -1,15 +1,15 @@ -<%= semantic_form_for question, namespace: "dragdrop", html: { class: "form-inline ", id: "new_dragdrop_question" } do |form| %> +<%= semantic_form_for question, namespace: "drag_drop", html: { class: "form-inline ", id: "new_drag_drop_question" } do |form| %> <%= error_msg_for question %>
    <%= form.input :name, input_html: {class: "input-xxlarge"} %>
    - <%= form.hidden_field :type, value: "dragdrop" %> + <%= form.hidden_field :type, value: "drag_drop" %> <%= hidden_field_tag :redirect_to_session, params[:redirect_to_session] %>
    <%= form.input :tags, input_html: { class: "input-xxlarge" , placeholder: "Tags" }, required: false %> <% if current_user.question_tags && !current_user.question_tags.blank? %> - <%= select_tag "tags", options_for_select([[t("questions.add_from_your_tags"), '']] + current_user.question_tags.sort.map{ |t| [t, t]}), id: "dragdrop_select_tag" %> + <%= select_tag "tags", options_for_select([[t("questions.add_from_your_tags"), '']] + current_user.question_tags.sort.map{ |t| [t, t]}), id: "drag_drop_select_tag" %>
      <% end %>
    @@ -18,14 +18,14 @@
    -

    <%= t("surveys.edit.answer_pairs_for_dragdrop_survey") %>

    +

    <%= t("surveys.edit.answer_pairs_for_drag_drop_survey") %>

    <%= form.semantic_fields_for :answer_pairs, class: "form-inline" do |pair| %> - <%= render "dragdrop_question_answer_pair_fields", f: pair %> + <%= render "drag_drop_question_answer_pair_fields", f: pair %> <% end %>
    @@ -42,14 +42,14 @@ <% content_for :javascript do %> diff --git a/app/views/questions/_drag_drop_question_answer_pair_fields.html.erb b/app/views/questions/_drag_drop_question_answer_pair_fields.html.erb new file mode 100644 index 0000000..2b551a1 --- /dev/null +++ b/app/views/questions/_drag_drop_question_answer_pair_fields.html.erb @@ -0,0 +1,7 @@ +
    +
    + <%= link_to_remove_association icon_tag("minus-sign"), f %> + <%= f.text_field :answer1, placeholder: t("surveys.drag_drop_input_field_1") %> + <%= f.text_field :answer2, placeholder: t("surveys.drag_drop_input_field_2") %> +
    +
    diff --git a/app/views/questions/_dragdrop_question_answer_pair_fields.html.erb b/app/views/questions/_dragdrop_question_answer_pair_fields.html.erb deleted file mode 100644 index 6105b59..0000000 --- a/app/views/questions/_dragdrop_question_answer_pair_fields.html.erb +++ /dev/null @@ -1,7 +0,0 @@ -
    -
    - <%= link_to_remove_association icon_tag("minus-sign"), f %> - <%= f.text_field :answer1, placeholder: t("surveys.dragdrop_input_field_1") %> - <%= f.text_field :answer2, placeholder: t("surveys.dragdrop_input_field_2") %> -
    -
    diff --git a/app/views/questions/index.html.erb b/app/views/questions/index.html.erb index 07f1789..d819697 100644 --- a/app/views/questions/index.html.erb +++ b/app/views/questions/index.html.erb @@ -58,8 +58,8 @@ <%= link_to icon_tag("th") + t("type.text"), questions_path(tag: params[:tag], q_type: "text", public: params[:public], shared: params[:shared]) %>
  • "> <%= link_to icon_tag("th") + t("type.number"), questions_path(tag: params[:tag], q_type: "number", public: params[:public], shared: params[:shared]) %>
  • -
  • "> - <%= link_to icon_tag("move") + t("type.dragdrop"), questions_path(tag: params[:tag], q_type: "dragdrop", public: params[:public], shared: params[:shared]) %>
  • +
  • "> + <%= link_to icon_tag("move") + t("type.drag_drop"), questions_path(tag: params[:tag], q_type: "drag_drop", public: params[:public], shared: params[:shared]) %>
  • diff --git a/app/views/questions/new.html.erb b/app/views/questions/new.html.erb index f750e45..2b24bb7 100644 --- a/app/views/questions/new.html.erb +++ b/app/views/questions/new.html.erb @@ -9,7 +9,7 @@
  • <%= t "type.multi" %>
  • <%= t "type.text" %>
  • <%= t "type.number" %> BETA
  • -
  • <%= t "type.dragdrop" %>
  • +
  • <%= t "type.drag_drop" %>
  • @@ -27,8 +27,8 @@
    <%= render partial: @question_number.form_partial, locals: {question: @question_number} %>
    -
    - <%= render partial: @question_dragdrop.form_partial, locals: {question: @question_dragdrop} %> +
    + <%= render partial: @question_drag_drop.form_partial, locals: {question: @question_drag_drop} %>
    diff --git a/app/views/questions/show.html.erb b/app/views/questions/show.html.erb index 1f2570c..7f5aaa8 100644 --- a/app/views/questions/show.html.erb +++ b/app/views/questions/show.html.erb @@ -14,7 +14,7 @@ Text <% elsif @question.type == "number" %> <%= t("questions.show.type_number") %> -<% elsif @question.type == "dragdrop" %> +<% elsif @question.type == "drag_drop" %> Drag and Drop <% end %>
    diff --git a/config/locales/defaults/de.yml b/config/locales/defaults/de.yml index 6e44603..c377cd0 100644 --- a/config/locales/defaults/de.yml +++ b/config/locales/defaults/de.yml @@ -80,7 +80,7 @@ de: choice: "Auswahlfrage" single: "Single Choice" multi: "Multiple Choice" - dragdrop: "Drag and Drop" + drag_drop: "Drag and Drop" truefalse: "Wahr/Falsch-Frage" yesno: "Ja/Nein-Frage" agree: "Zustimmen/Nicht zustimmen-Frage" diff --git a/config/locales/defaults/en.yml b/config/locales/defaults/en.yml index 56b4106..904405b 100644 --- a/config/locales/defaults/en.yml +++ b/config/locales/defaults/en.yml @@ -79,7 +79,7 @@ en: choice: "Choice Question" single: "Single Choice" multi: "Multiple Choice" - dragdrop: "Drag and Drop" + drag_drop: "Drag and Drop" truefalse: "True/False Question" yesno: "Yes/No Question" agree: "Agree/Disagree Question" diff --git a/config/locales/views/surveys.de.yml b/config/locales/views/surveys.de.yml index e41362c..ca28af9 100755 --- a/config/locales/views/surveys.de.yml +++ b/config/locales/views/surveys.de.yml @@ -10,7 +10,7 @@ de: add_option: Antwortmöglichkeit hinzufügen add_answer_pair: Antwortpaar hinzufügen options_for_survey: Antwortmöglichkeiten für diese Umfrage - answer_pairs_for_dragdrop_survey: Antwortpaare für diese Umfrage + answer_pairs_for_drag_drop_survey: Antwortpaare für diese Umfrage changed: header: Vergleich des Antwortverhaltens wait: "Einen Moment bitte, Daten werden berechnet" @@ -66,6 +66,6 @@ de: add_field_notice: "Bei dieser Umfrage können Sie beliebig viele Antworten eingeben." number_input_field: notice: "Zahl bitte ohne 1.000er-Trennzeichen eingeben, z. B. 42,7" - dragdrop_input_field_1: "Das gehört..." - dragdrop_input_field_2: "...zu dem." + drag_drop_input_field_1: "Das gehört..." + drag_drop_input_field_2: "...zu dem." diff --git a/config/locales/views/surveys.en.yml b/config/locales/views/surveys.en.yml index 22d4fd2..0c1b6e7 100755 --- a/config/locales/views/surveys.en.yml +++ b/config/locales/views/surveys.en.yml @@ -10,7 +10,7 @@ en: add_option: Add option add_answer_pair: Add answer pair options_for_survey: Answer options for this survey - answer_pairs_for_dragdrop_survey: Answer pairs for this survey + answer_pairs_for_drag_drop_survey: Answer pairs for this survey changed: header: Comparison of voting behaviour wait: "One moment please, gathering data" @@ -66,6 +66,6 @@ en: add_field_notice: "In this survey, you can enter as many answers as you wish." number_input_field: notice: "Please enter the number without a thousands delimiter, e.g. 42.7" - dragdrop_input_field_1: "This belongs..." - dragdrop_input_field_2: "...to that." + drag_drop_input_field_1: "This belongs..." + drag_drop_input_field_2: "...to that." From 61183152c02b8955c1d54d01351005f448cb19ff Mon Sep 17 00:00:00 2001 From: KKrenz Date: Sun, 4 Jan 2015 23:52:57 +0100 Subject: [PATCH 03/22] match result table and first steps in participate --- app/assets/javascripts/table.js | 125 ++++++++++++++++++ app/assets/stylesheets/surveys.css.less | 18 ++- app/controllers/questions_controller.rb | 16 +-- app/controllers/surveys_controller.rb | 6 +- app/models/answer_pair.rb | 26 +++- app/models/option.rb | 2 +- app/models/question.rb | 39 +++++- app/models/survey.rb | 8 +- app/parsers/gift_importer.rb | 4 +- app/services/drag_drop_question.rb | 27 ---- app/services/drag_drop_survey.rb | 31 ----- app/services/generic_survey.rb | 4 + app/services/match_question.rb | 28 ++++ app/services/match_survey.rb | 43 ++++++ app/views/.DS_Store | Bin 6148 -> 6148 bytes ..._drop_question_answer_pair_fields.html.erb | 7 - ...rop_form.html.erb => _match_form.html.erb} | 24 ++-- ...match_question_answer_pair_fields.html.erb | 7 + app/views/questions/index.html.erb | 4 +- app/views/questions/new.html.erb | 6 +- app/views/questions/show.html.erb | 6 +- app/views/surveys/.DS_Store | Bin 0 -> 6148 bytes app/views/surveys/Ablage.html | 24 ++++ .../_answer_pair_result_table.html.erb | 19 +++ app/views/surveys/_match_lists.html.erb | 44 ++++++ app/views/surveys/_show.html.erb | 70 ++++++---- app/views/surveys/show.js.erb | 11 +- config/locales/defaults/de.yml | 2 +- config/locales/defaults/en.yml | 2 +- config/locales/views/questions.de.yml | 3 +- config/locales/views/questions.en.yml | 3 +- config/locales/views/surveys.de.yml | 12 +- config/locales/views/surveys.en.yml | 12 +- 33 files changed, 481 insertions(+), 152 deletions(-) create mode 100644 app/assets/javascripts/table.js delete mode 100644 app/services/drag_drop_question.rb delete mode 100644 app/services/drag_drop_survey.rb create mode 100644 app/services/match_question.rb create mode 100644 app/services/match_survey.rb delete mode 100644 app/views/questions/_drag_drop_question_answer_pair_fields.html.erb rename app/views/questions/{_drag_drop_form.html.erb => _match_form.html.erb} (68%) create mode 100644 app/views/questions/_match_question_answer_pair_fields.html.erb create mode 100644 app/views/surveys/.DS_Store create mode 100644 app/views/surveys/Ablage.html create mode 100644 app/views/surveys/_answer_pair_result_table.html.erb create mode 100644 app/views/surveys/_match_lists.html.erb diff --git a/app/assets/javascripts/table.js b/app/assets/javascripts/table.js new file mode 100644 index 0000000..294abea --- /dev/null +++ b/app/assets/javascripts/table.js @@ -0,0 +1,125 @@ +function tableDraw() + {this.span(); + + var props = ""; + var i = 0; + var dummyRows = this.content.length; + var dummyCols = this.content[0].length; + + var dummyCode = '= this.propsLengthPublic) {break;} + dummyCode = dummyCode+' '+prop+'="'+this[prop]+'"';i++; + } + dummyCode = dummyCode+'>\n'; + + for (var i=1;i<=dummyRows;i++) + {dummyCode = dummyCode+'\n'; + for (var k=1;k<=dummyCols;k++) + {if (this.content[(i-1)][(k-1)][2] == "false") + {dummyCode = dummyCode+' '+this.content[(i-1)][(k-1)][1]+'\n';} + } + dummyCode = dummyCode+'\n'; + } + + dummyCode = dummyCode+'\n'; + return dummyCode; + } + +function tableSpan() + {var dummyRows = this.content.length; + var dummyCols = this.content[0].length; + + for (var i=1;i<=dummyRows;i++) + {var rowspan = 0;var colspan = 0; + var fromHere = 0;var tillThere = 0; + var myString = ""; + for (var k=1;k<=dummyCols;k++) + {rowspan = 0;colspan = 0; + if (this.content[(i-1)][(k-1)][2] == "false") + {myString = (this.content[(i-1)][(k-1)][0]) + ""; + if (myString.indexOf("colspan") >= 0) + {fromHere = (myString.indexOf("colspan"))+9; + tillThere = (myString.indexOf('"',fromHere))-1; + if ((fromHere-tillThere) == 0) + {colspan = myString.charAt(fromHere);} + else + {colspan = myString.substring(fromHere,tillThere);} + colspan = parseInt(colspan); + } + if (myString.indexOf("rowspan") >= 0) + {fromHere = (myString.indexOf("rowspan"))+9; + tillThere = (myString.indexOf('"',fromHere))-1; + if ((fromHere-tillThere) == 0) + {rowspan = myString.charAt(fromHere);} + else + {rowspan = myString.substring(fromHere,tillThere);} + rowspan = parseInt(rowspan); + } + if ((colspan >= 2) && (rowspan <= 1)) + {for (var m=2;m<=colspan;m++) + {this.content[(i-1)][((k-1)+(m-1))][2] = "true";} + } + if ((rowspan >= 2) && (colspan <= 1)) + {for (var m=2;m<=rowspan;m++) + {this.content[((i-1)+(m-1))][(k-1)][2] = "true";} + } + if ((rowspan >= 2) && (colspan >= 2)) + {for (var m=1;m<=rowspan;m++) + {for (var p=1;p<=colspan;p++) + {this.content[((i-1)+(m-1))][((k-1)+(p-1))][2] = "true";} + } + this.content[(i-1)][(k-1)][2] = "false"; + } } } } } + +function tableContent(dummyCols,dummyRows) + {var dummyContent = "["; + for (var i=1;i<=dummyRows;i++) + {dummyContent = dummyContent+"[" + for (var k=1;k<=dummyCols;k++) + {dummyContent = dummyContent+"[['align="+'"left"'+" valign="+'"top"'+"'],[' '],['false']],";} + dummyContent = dummyContent.substring(0,((dummyContent.length)-1)); + dummyContent = dummyContent+"]," + } + dummyContent = dummyContent.substring(0,((dummyContent.length)-1)); + dummyContent = dummyContent+"]"; + return eval(dummyContent); + } + +function tableContentArraysToArguments() + {var dummyRows = this.content.length; + var dummyCols = this.content[0].length; + for (var i=1;i<=dummyRows;i++) + {for (var k=1;k<=dummyCols;k++) + {this.content[(i-1)][(k-1)].props = this.content[(i-1)][(k-1)][0]; + this.content[(i-1)][(k-1)].value = this.content[(i-1)][(k-1)][1]; + this.content[(i-1)][(k-1)].spans = this.content[(i-1)][(k-1)][2]; + } } } + +function tableContentArgumentsToArrays() + {var dummyRows = this.content.length; + var dummyCols = this.content[0].length; + for (var i=1;i<=dummyRows;i++) + {for (var k=1;k<=dummyCols;k++) + {this.content[(i-1)][(k-1)][0] = this.content[(i-1)][(k-1)].props; + this.content[(i-1)][(k-1)][1] = this.content[(i-1)][(k-1)].value; + this.content[(i-1)][(k-1)][2] = this.content[(i-1)][(k-1)].spans; + } } } + +function table() + {var propsDefaultLength = 2; + this.cols = 1; + this.rows = 1; + for (var i=1;i<=table.arguments.length;i++) + {if (table.arguments[(i-1)].indexOf("cols") >= 0) {propsDefaultLength--;} + if (table.arguments[(i-1)].indexOf("rows") >= 0) {propsDefaultLength--;} + eval("this."+table.arguments[(i-1)]); + } + this.propsLengthPublic = (table.arguments.length + propsDefaultLength); + this.propsLengthPrivat = 7; + this.content = tableContent(this.cols,this.rows); + this.span = tableSpan; + this.draw = tableDraw; + this.contentArraysToArguments = tableContentArraysToArguments; + this.contentArgumentsToArrays = tableContentArgumentsToArrays; + } \ No newline at end of file diff --git a/app/assets/stylesheets/surveys.css.less b/app/assets/stylesheets/surveys.css.less index 989a590..cdab719 100755 --- a/app/assets/stylesheets/surveys.css.less +++ b/app/assets/stylesheets/surveys.css.less @@ -2,6 +2,7 @@ font-style: italic; font-size: 80%; } + #survey-options-list li { margin-bottom:10px; } @@ -56,7 +57,18 @@ } } +#selectable { + list-style-type: none; + margin: 0; + padding: 0; +} +#selectable li { + border: 1px solid LightGray; + margin: 3px; + padding: 0.4em; + text-align: center; +} /* ======================================== @@ -96,7 +108,9 @@ display: inline; } - +.selected { + background: #FECA40; +} @@ -166,7 +180,7 @@ margin-top: 0.25em; } -.canvas_downloadable { +.canvas_downloadable .table_downloadable { position: relative; .canvas_download-button { diff --git a/app/controllers/questions_controller.rb b/app/controllers/questions_controller.rb index f45c527..e073606 100644 --- a/app/controllers/questions_controller.rb +++ b/app/controllers/questions_controller.rb @@ -99,11 +99,11 @@ def new @question_multi = MultipleChoiceQuestion.new.tap { |q| q.question_options.build } @question_text = TextQuestion.new @question_number = NumberQuestion.new #refactor this maybe? - @question_drag_drop = DragDropQuestion.new.tap { |q| q.answer_pairs.build } + @question_match = MatchQuestion.new.tap { |q| q.answer_pairs.build } end def edit - + @question.delete_all_false_answer_pairs end def update @@ -113,10 +113,6 @@ def update @question.add_setting("answers", params[:options]) end - if params[:answer_pairs] && @question.has_settings? - @question.add_setting("answers", params[:answer_pairs]) - end - respond_to do |format| if @question.update_attributes(question_params) current_user.contacts.concat (@question.collaborators - current_user.contacts) @@ -127,6 +123,7 @@ def update format.json { render json: @question.errors, status: :unprocessable_entity } end end + end def transform @@ -273,8 +270,8 @@ def set_js_tags params[:question][:tags] = params["text_question"][:tags] elsif params["number_question"] && params["number_question"][:tags] params[:question][:tags] = params["number_question"][:tags] - elsif params["drag_drop_question"] && params["drag_drop_question"][:tags] - params[:question][:tags] = params["drag_drop_question"][:tags] + elsif params["match_question"] && params["match_question"][:tags] + params[:question][:tags] = params["match_question"][:tags] end end @@ -289,6 +286,7 @@ def check_access end def question_params - params.require(:question).permit(:name, :type, :description, :tags, :public, :collaborators_form, question_options_attributes: [:name, :correct, :id, :_destroy], answer_pairs_attributes: [:answer1, :answer2, :id, :_destroy]) + params.require(:question).permit(:name, :type, :description, :tags, :public, :collaborators_form, question_options_attributes: [:name, :correct, :id, :_destroy], answer_pairs_attributes: [:answer1, :answer2, :correct, :id, :_destroy]) end + end diff --git a/app/controllers/surveys_controller.rb b/app/controllers/surveys_controller.rb index 864a7fe..90d4987 100644 --- a/app/controllers/surveys_controller.rb +++ b/app/controllers/surveys_controller.rb @@ -44,6 +44,7 @@ def show def new @survey = Survey.new @survey.options.build + @survey.answer_pairs.build respond_to do |format| format.html # new.html.erb @@ -201,6 +202,9 @@ def repeat original_survey.options.map do |option| @survey.options.new(name: option.name, correct: option.correct) end + original_survey.answer_pairs.map do |pair| + @survey.answer_pairs.new(answer1: pair.answer1, answer2: pair.answer2, correct: pair.correct) + end @survey.type = original_survey.type @survey.settings = original_survey.settings @survey.original_survey = original_survey @@ -492,7 +496,7 @@ def api protected def survey_params - params.require(:survey).permit(:name, :description, options_attributes: [:name, :correct, :id]) + params.require(:survey).permit(:name, :description, options_attributes: [:name, :correct, :id], answer_pairs_attributes: [:answer1, :answer2, :correct, :id]) end def check_access diff --git a/app/models/answer_pair.rb b/app/models/answer_pair.rb index 0787b35..fba0f1c 100644 --- a/app/models/answer_pair.rb +++ b/app/models/answer_pair.rb @@ -1,10 +1,34 @@ class AnswerPair include Mongoid::Document - embedded_in :question, :inverse_of => :answer_pairs + embedded_in :question + embedded_in :survey field :answer1, type: String field :answer2, type: String + field :votes, type: Integer, default: 0 + field :description, type: String + field :correct, type: Boolean, default: true validates_presence_of :answer1 validates_presence_of :answer2 + + def self.buildnew(answer1 = "answer1", answer2 = "answer2", correct = false) + ap = AnswerPair.new + ap.answer1 = answer1 + ap.answer2 = answer2 + ap.correct = correct + return ap + end + + def vote_up + self.inc(:votes, 1) + end + + def vote_down + self.inc(:votes, -1) + end + + def correct? + self.correct + end end diff --git a/app/models/option.rb b/app/models/option.rb index 3b6322f..7119cf4 100755 --- a/app/models/option.rb +++ b/app/models/option.rb @@ -5,7 +5,7 @@ class Option field :name, type: String field :description, type: String field :votes, type: Integer, default: 0 - field :correct, type: Boolean, defaut: nil + field :correct, type: Boolean, default: nil validates_presence_of :name diff --git a/app/models/question.rb b/app/models/question.rb index c9b6d7b..acdee43 100644 --- a/app/models/question.rb +++ b/app/models/question.rb @@ -12,7 +12,7 @@ class Question field :settings, type: Hash, default: {} def self.question_types - ["multi", "single", "text", "exit_q", "number", "drag_drop"] + ["multi", "single", "text", "exit_q", "number", "match"] end validates :type, inclusion: {in: Question.question_types} @@ -33,6 +33,7 @@ def self.question_types has_and_belongs_to_many :collaborators, class_name: "User", inverse_of: :shared_questions index :collaborator_ids, sparse: true + before_save :fill_up_answer_pairs # this is where we setup getting the service objects def service @@ -45,8 +46,8 @@ def service MultipleChoiceQuestion.new(self) when "number" NumberQuestion.new(self) - when "drag_drop" - DragDropQuestion.new(self) + when "match" + MatchQuestion.new(self) else self end @@ -83,7 +84,10 @@ def self.new_from_existing(original_question) question.question_options.build(name: option.name, correct: option.correct) end original_question.answer_pairs.each do |pair| - question.answer_pairs.build(answer1: pair.answer1, answer2: pair.answer2) + question.answer_pairs.build( + answer1: pair.answer1, + answer2: pair.answer2, + correct: pair.correct) end question.type = original_question.type question.original_question = original_question @@ -115,4 +119,29 @@ def collaborators_form=(v) end end -end + + def delete_all_false_answer_pairs + if(self.answer_pairs.any?) + self.answer_pairs.where(correct: false).each do |pair| + pair.delete + end + end + end + + # adds all possible combinations of false answer_pairs to the collection "answer_pairs" + private + def fill_up_answer_pairs + if(self.answer_pairs.any?) + self.answer_pairs.where(correct: true).each do |pair1| + self.answer_pairs.where(correct: true).each do |pair2| + if(pair1.answer1 != pair2.answer1) + if(pair1.answer2 != pair2.answer2) + self.add_to_set(:answer_pairs, AnswerPair.buildnew(pair1.answer1, pair2.answer2, false)) + end + end + end + end + end + end + +end \ No newline at end of file diff --git a/app/models/survey.rb b/app/models/survey.rb index aad0899..b768e0e 100755 --- a/app/models/survey.rb +++ b/app/models/survey.rb @@ -39,8 +39,8 @@ class Survey belongs_to :question scope :current, where(:starts.gte => DateTime.now).and(:ends.lt => DateTime.now) - scope :display_fields, only(:description, :ends, :name, :options, :starts, :event_id, :quick, :created_at, :multi, :type, :settings, :voters, :voters_hash, :original_survey_id, :exit_q, :question_id) - scope :participate_fields, only(:description, :ends, :name, :options, :starts, :event_id, :quick, :multi, :type, :exit_q, :settings) + scope :display_fields, only(:description, :ends, :name, :options, :answer_pairs, :starts, :event_id, :quick, :created_at, :multi, :type, :settings, :voters, :voters_hash, :original_survey_id, :exit_q, :question_id) + scope :participate_fields, only(:description, :ends, :name, :options, :answer_pairs, :starts, :event_id, :quick, :multi, :type, :exit_q, :settings) scope :worker_fields, only(:voters, :multi, :type, :starts, :ends) validates :event, presence: true @@ -58,8 +58,8 @@ def service NumberSurvey.new(self) when "exit_q" ExitSurvey.new(self) - when "drag_drop" - DragDropSurvey.new(self) + when "match" + MatchSurvey.new(self) else self end diff --git a/app/parsers/gift_importer.rb b/app/parsers/gift_importer.rb index a79f5f4..5818875 100755 --- a/app/parsers/gift_importer.rb +++ b/app/parsers/gift_importer.rb @@ -27,8 +27,8 @@ def import (gift_file, user, tags) q = Question.new(type:"text").service elsif question.is_a? Gift::NumericQuestion q = Question.new(type:"number") - elsif question.is_a? Gift::DragDropQuestion - q = Question.new(type:"drag_drop") + elsif question.is_a? Gift::MatchQuestion + q = Question.new(type:"match") elsif question.is_a?(Gift::DescriptionQuestion) || question.is_a?(Gift::MatchQuestion) || question.is_a?(Gift::FillInQuestion) # Abfrage nicht unterstützter Typen errors << {"type" => "unsupported_type", "text" => question.text} diff --git a/app/services/drag_drop_question.rb b/app/services/drag_drop_question.rb deleted file mode 100644 index 5d61e29..0000000 --- a/app/services/drag_drop_question.rb +++ /dev/null @@ -1,27 +0,0 @@ -class DragDropQuestion < GenericQuestion - def initialize(question = Question.new(type: "drag_drop")) - raise "type of question not correct" if question.type != "drag_drop" - super - self.question.type = "drag_drop" unless self.question.persisted? - end - - def has_options? - false - end - - def has_answer_pairs? - true - end - - def has_settings? - true - end - - def form_partial - "drag_drop_form" - end - - def to_survey - DragDropSurvey.new(self.question.to_survey) - end -end \ No newline at end of file diff --git a/app/services/drag_drop_survey.rb b/app/services/drag_drop_survey.rb deleted file mode 100644 index 4c32283..0000000 --- a/app/services/drag_drop_survey.rb +++ /dev/null @@ -1,31 +0,0 @@ -class DragDropSurvey < GenericSurvey - def initialize(survey) - raise "type of survey (#{survey.type}) not correct" if survey.type != "drag_drop" - super - end - - def prompt - I18n.t "surveys.participate.drag_drop" - end - - def participate_partial - "drag_drop_option" - end - - # VIEW OPTIONS - def has_options? - false - end - - def has_answer_pairs? - true - end - - def has_settings? - true - end - - def results_comparable? - true - end -end \ No newline at end of file diff --git a/app/services/generic_survey.rb b/app/services/generic_survey.rb index 172f762..e560a95 100755 --- a/app/services/generic_survey.rb +++ b/app/services/generic_survey.rb @@ -24,6 +24,10 @@ def has_settings? def has_options? false end + + def has_answer_pairs? + false + end def terms_numeric? # are individual answers numeric? false diff --git a/app/services/match_question.rb b/app/services/match_question.rb new file mode 100644 index 0000000..6e13a86 --- /dev/null +++ b/app/services/match_question.rb @@ -0,0 +1,28 @@ +class MatchQuestion < GenericQuestion + def initialize(question = Question.new(type: "match")) + raise "type of question not correct" if question.type != "match" + super + self.question.type = "match" unless self.question.persisted? + end + + def has_options? + false + end + + def has_answer_pairs? + true + end + + def has_settings? + false + end + + def form_partial + "match_form" + end + + def to_survey + MatchSurvey.new(self.question.to_survey) + end + +end \ No newline at end of file diff --git a/app/services/match_survey.rb b/app/services/match_survey.rb new file mode 100644 index 0000000..e37a772 --- /dev/null +++ b/app/services/match_survey.rb @@ -0,0 +1,43 @@ +class MatchSurvey < GenericSurvey + def initialize(survey) + raise "type of survey (#{survey.type}) not correct" if survey.type != "match" + super + end + + def prompt + I18n.t "surveys.participate.choose-match" + end + + def participate_partial + "match_lists" + end + + def has_answer_pairs? + true + end + + def results_comparable? + true + end + + def get_all_answer1 + if(self.survey.answer_pairs.any?) + answer1s = [] + self.survey.answer_pairs.where(correct: true).each do |pair| + answer1s += [pair.answer1] + end + return answer1s + end + end + + def get_all_answer2 + if(self.survey.answer_pairs.any?) + answer2s = [] + self.survey.answer_pairs.where(correct: true).each do |pair| + answer2s += [pair.answer2] + end + return answer2s + end + end + +end \ No newline at end of file diff --git a/app/views/.DS_Store b/app/views/.DS_Store index 6bd38abfa2df9ccffe8a3f6e41ec906bc4377695..0152900264d4d6d9805e56ef46aacba0e2d83133 100644 GIT binary patch delta 106 zcmZoMXfc=|#>B!ku~2NHo+2a5#(>?7iyfGm7+E&+Fex$evNIGjlrj`Clrf|-R8Cf4 x+QwKr`8ty+s`zGE=F5zm**W+*fF^A=Wd6=PnP0?_gOP!Oi2(>UM~JLp1^`K*7x@4H delta 70 zcmZoMXfc=|#>B)qu~2NHo+2aD#(>?7lMO^zHuJN{Gj4WeJH)uLL7aIrI|n}pP}OEZ Yj_=Hq`9&N#7=VD0fq`Xngvc6Z0C+4A9{>OV diff --git a/app/views/questions/_drag_drop_question_answer_pair_fields.html.erb b/app/views/questions/_drag_drop_question_answer_pair_fields.html.erb deleted file mode 100644 index 2b551a1..0000000 --- a/app/views/questions/_drag_drop_question_answer_pair_fields.html.erb +++ /dev/null @@ -1,7 +0,0 @@ -
    -
    - <%= link_to_remove_association icon_tag("minus-sign"), f %> - <%= f.text_field :answer1, placeholder: t("surveys.drag_drop_input_field_1") %> - <%= f.text_field :answer2, placeholder: t("surveys.drag_drop_input_field_2") %> -
    -
    diff --git a/app/views/questions/_drag_drop_form.html.erb b/app/views/questions/_match_form.html.erb similarity index 68% rename from app/views/questions/_drag_drop_form.html.erb rename to app/views/questions/_match_form.html.erb index aa431e9..1ced556 100644 --- a/app/views/questions/_drag_drop_form.html.erb +++ b/app/views/questions/_match_form.html.erb @@ -1,15 +1,15 @@ -<%= semantic_form_for question, namespace: "drag_drop", html: { class: "form-inline ", id: "new_drag_drop_question" } do |form| %> +<%= semantic_form_for question, namespace: "match", html: { class: "form-inline ", id: "new_match_question" } do |form| %> <%= error_msg_for question %>
    <%= form.input :name, input_html: {class: "input-xxlarge"} %>
    - <%= form.hidden_field :type, value: "drag_drop" %> + <%= form.hidden_field :type, value: "match" %> <%= hidden_field_tag :redirect_to_session, params[:redirect_to_session] %>
    <%= form.input :tags, input_html: { class: "input-xxlarge" , placeholder: "Tags" }, required: false %> <% if current_user.question_tags && !current_user.question_tags.blank? %> - <%= select_tag "tags", options_for_select([[t("questions.add_from_your_tags"), '']] + current_user.question_tags.sort.map{ |t| [t, t]}), id: "drag_drop_select_tag" %> + <%= select_tag "tags", options_for_select([[t("questions.add_from_your_tags"), '']] + current_user.question_tags.sort.map{ |t| [t, t]}), id: "match_select_tag" %>
      <% end %>
    @@ -18,14 +18,14 @@
    -

    <%= t("surveys.edit.answer_pairs_for_drag_drop_survey") %>

    +

    <%= t("surveys.edit.answer_pairs_for_match_survey") %>

    <%= form.semantic_fields_for :answer_pairs, class: "form-inline" do |pair| %> - <%= render "drag_drop_question_answer_pair_fields", f: pair %> + <%= render "match_question_answer_pair_fields", f: pair %> <% end %>
    @@ -42,15 +42,15 @@ <% content_for :javascript do %> -<% end %> +<% end %> \ No newline at end of file diff --git a/app/views/questions/_match_question_answer_pair_fields.html.erb b/app/views/questions/_match_question_answer_pair_fields.html.erb new file mode 100644 index 0000000..f9e19cf --- /dev/null +++ b/app/views/questions/_match_question_answer_pair_fields.html.erb @@ -0,0 +1,7 @@ +
    +
    + <%= link_to_remove_association icon_tag("minus-sign"), f %> + <%= f.text_field :answer1, placeholder: t("surveys.match_input_field_1") %> + <%= f.text_field :answer2, placeholder: t("surveys.match_input_field_2") %> +
    +
    diff --git a/app/views/questions/index.html.erb b/app/views/questions/index.html.erb index d819697..c055700 100644 --- a/app/views/questions/index.html.erb +++ b/app/views/questions/index.html.erb @@ -58,8 +58,8 @@ <%= link_to icon_tag("th") + t("type.text"), questions_path(tag: params[:tag], q_type: "text", public: params[:public], shared: params[:shared]) %>
  • "> <%= link_to icon_tag("th") + t("type.number"), questions_path(tag: params[:tag], q_type: "number", public: params[:public], shared: params[:shared]) %>
  • -
  • "> - <%= link_to icon_tag("move") + t("type.drag_drop"), questions_path(tag: params[:tag], q_type: "drag_drop", public: params[:public], shared: params[:shared]) %>
  • +
  • "> + <%= link_to icon_tag("move") + t("type.match"), questions_path(tag: params[:tag], q_type: "match", public: params[:public], shared: params[:shared]) %>
  • diff --git a/app/views/questions/new.html.erb b/app/views/questions/new.html.erb index 2b24bb7..b5e6e42 100644 --- a/app/views/questions/new.html.erb +++ b/app/views/questions/new.html.erb @@ -9,7 +9,7 @@
  • <%= t "type.multi" %>
  • <%= t "type.text" %>
  • <%= t "type.number" %> BETA
  • -
  • <%= t "type.drag_drop" %>
  • +
  • <%= t "type.match" %>
  • @@ -27,8 +27,8 @@
    <%= render partial: @question_number.form_partial, locals: {question: @question_number} %>
    -
    - <%= render partial: @question_drag_drop.form_partial, locals: {question: @question_drag_drop} %> +
    + <%= render partial: @question_match.form_partial, locals: {question: @question_match} %>
    diff --git a/app/views/questions/show.html.erb b/app/views/questions/show.html.erb index 7f5aaa8..d73c7e1 100644 --- a/app/views/questions/show.html.erb +++ b/app/views/questions/show.html.erb @@ -14,8 +14,8 @@ Text <% elsif @question.type == "number" %> <%= t("questions.show.type_number") %> -<% elsif @question.type == "drag_drop" %> - Drag and Drop +<% elsif @question.type == "match" %> + <%= t("questions.show.type_match") %> <% end %>

    Tags: <%= @question.tags_array.join(", ") %>

    @@ -31,7 +31,7 @@ <% if @question.has_answer_pairs? %> <%= t("surveys.show.answer_pairs") %>
      - <%= render partial: "answer_pair", collection: @question.answer_pairs %> + <%= render partial: "answer_pair", collection: @question.answer_pairs.where(correct: true) %>
    <% end %> diff --git a/app/views/surveys/.DS_Store b/app/views/surveys/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5008ddfcf53c02e82d7eee2e57c38e5672ef89f6 GIT binary patch literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0<%= t ".mark_corrects" %> --> + + - - +

    <%= percentage %>

    +
    + + <% else %> + +
    +
    +

    <%= percentage %>

    +
    + + <% end %> <% end %> - - - - <% survey.answer_pairs.where(correct: true).each do |pair1| %> - <%= pair1.answer1 %> - <% survey.answer_pairs.where(correct: true).each do |pair2| %> - <%= survey.answer_pairs.where(answer1: pair1.answer1, answer2: pair2.answer2).first.votes %> + <% end %> - - <% end %> - - \ No newline at end of file + + + \ No newline at end of file diff --git a/app/views/surveys/_match_lists.html.erb b/app/views/surveys/_match_lists.html.erb old mode 100644 new mode 100755 diff --git a/app/views/surveys/_show.html.erb b/app/views/surveys/_show.html.erb index 35d9ebc..b58bcb0 100755 --- a/app/views/surveys/_show.html.erb +++ b/app/views/surveys/_show.html.erb @@ -75,10 +75,10 @@
    - <%= icon_tag("download-alt") %> + <%= icon_tag("download-alt") %> <% if survey.options.any?(&:correct) %> - <%= t ".mark_corrects" %> + <%= t("surveys.show.mark_corrects") %> <% end %> <% if survey.original_survey %> @@ -95,14 +95,12 @@ <% elsif survey.has_answer_pairs? %>
    -

    <%= t("results") %> (%)

    - <% if !survey.running? %> -
    - <%= render partial: "answer_pair_result_table", locals: {survey: survey} %> -
    - <% else %> -

    <%= t "surveys.show.wait_to_end" %>

    - <% end %> +

    <%= t("results") %>

    +
    + <%= render partial: "answer_pair_result_table", locals: {survey: survey} %> + <%= icon_tag("download-alt") %> + <%= t("surveys.show.mark_corrects") %> +
    @@ -199,6 +197,9 @@ if(window.PINGO.isMSIE()){ $(".canvas_downloadable").removeClass("canvas_downloadable"); } + $("#showCorrectsBtn").click(function() { + $(".toCorrectSwitchable").toggleClass("isCorrect"); + }); }); <% end %> diff --git a/app/views/surveys/_text_tag_cloud_result.html.erb b/app/views/surveys/_text_tag_cloud_result.html.erb old mode 100644 new mode 100755 diff --git a/app/views/surveys/show_remote.html.erb b/app/views/surveys/show_remote.html.erb old mode 100644 new mode 100755 diff --git a/config.ru b/config.ru old mode 100644 new mode 100755 diff --git a/config/.DS_Store b/config/.DS_Store old mode 100644 new mode 100755 diff --git a/config/locales/defaults/de.yml b/config/locales/defaults/de.yml old mode 100644 new mode 100755 diff --git a/config/locales/defaults/en.yml b/config/locales/defaults/en.yml old mode 100644 new mode 100755 diff --git a/config/locales/views/events.de.yml b/config/locales/views/events.de.yml old mode 100644 new mode 100755 diff --git a/config/locales/views/events.en.yml b/config/locales/views/events.en.yml old mode 100644 new mode 100755 diff --git a/config/locales/views/questions.de.yml b/config/locales/views/questions.de.yml old mode 100644 new mode 100755 diff --git a/config/locales/views/questions.en.yml b/config/locales/views/questions.en.yml old mode 100644 new mode 100755 diff --git a/config/locales/views/surveys.de.yml b/config/locales/views/surveys.de.yml index 76aa892..4f470dc 100755 --- a/config/locales/views/surveys.de.yml +++ b/config/locales/views/surveys.de.yml @@ -63,7 +63,6 @@ de: histogram: "Histogramm" repeated: "Diese Umfrage ist eine wiederholte Umfrage." mark_corrects: Korrekte markieren - wait_to_end: Warten bis Zeit abgelaufen ist... text_table_results: term: "Antwort" occurrences: "Häufigkeit" diff --git a/config/locales/views/surveys.en.yml b/config/locales/views/surveys.en.yml index a81b7f5..ccdac05 100755 --- a/config/locales/views/surveys.en.yml +++ b/config/locales/views/surveys.en.yml @@ -63,7 +63,6 @@ en: histogram: "histogram" repeated: "This is a repeated survey." mark_corrects: mark correct answers - wait_to_end: Wait until time is up... text_table_results: term: "answer" occurrences: "occurrences" diff --git a/config/routes.rb b/config/routes.rb old mode 100644 new mode 100755 diff --git a/features/.DS_Store b/features/.DS_Store old mode 100644 new mode 100755 diff --git a/features/events.feature b/features/events.feature old mode 100644 new mode 100755 diff --git a/features/predefined_questions.feature b/features/predefined_questions.feature old mode 100644 new mode 100755 diff --git a/features/step_definitions/questions_steps.rb b/features/step_definitions/questions_steps.rb old mode 100644 new mode 100755 diff --git a/lib/.DS_Store b/lib/.DS_Store old mode 100644 new mode 100755 diff --git a/lib/statistics.rb b/lib/statistics.rb old mode 100644 new mode 100755 diff --git a/public/.DS_Store b/public/.DS_Store old mode 100644 new mode 100755 diff --git a/public/splash-screen-640x1096.png b/public/splash-screen-640x1096.png old mode 100644 new mode 100755 diff --git a/spec/.DS_Store b/spec/.DS_Store old mode 100644 new mode 100755 diff --git a/spec/controllers/.keep b/spec/controllers/.keep old mode 100644 new mode 100755 diff --git a/spec/controllers/events_controller_spec.rb b/spec/controllers/events_controller_spec.rb old mode 100644 new mode 100755 diff --git a/spec/controllers/questions_controller_spec.rb b/spec/controllers/questions_controller_spec.rb old mode 100644 new mode 100755 diff --git a/spec/factories.rb b/spec/factories.rb old mode 100644 new mode 100755 diff --git a/spec/mailers/.keep b/spec/mailers/.keep old mode 100644 new mode 100755 diff --git a/spec/models/.keep b/spec/models/.keep old mode 100644 new mode 100755 diff --git a/spec/models/answer_pair_spec.rb b/spec/models/answer_pair_spec.rb old mode 100644 new mode 100755 diff --git a/spec/routing/.keep b/spec/routing/.keep old mode 100644 new mode 100755 diff --git a/spec/services/multiple_choice_question_spec.rb b/spec/services/multiple_choice_question_spec.rb old mode 100644 new mode 100755 diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb old mode 100644 new mode 100755 diff --git a/spec/support/helpers.rb b/spec/support/helpers.rb old mode 100644 new mode 100755 diff --git a/vendor/.DS_Store b/vendor/.DS_Store old mode 100644 new mode 100755 From 69544464192c3970821e86b0ab71c3bdb6a9fe51 Mon Sep 17 00:00:00 2001 From: KKrenz Date: Tue, 24 Feb 2015 19:48:44 +0100 Subject: [PATCH 06/22] word-wrap; fix downloadButton --- app/assets/stylesheets/surveys.css.less | 53 +++++++++++++--- app/controllers/surveys_controller.rb | 2 +- app/services/match_survey.rb | 4 +- .../_answer_pair_result_table.html.erb | 23 +++---- app/views/surveys/_match_lists.html.erb | 62 ++++++++++++------- app/views/surveys/_show.html.erb | 25 ++++++-- 6 files changed, 118 insertions(+), 51 deletions(-) diff --git a/app/assets/stylesheets/surveys.css.less b/app/assets/stylesheets/surveys.css.less index bc1f137..d884a4a 100755 --- a/app/assets/stylesheets/surveys.css.less +++ b/app/assets/stylesheets/surveys.css.less @@ -34,6 +34,11 @@ padding-bottom: 0.5em; font-weight: bold; } + +#survey-table td { + width: 50%; +} + .pointer { cursor: pointer; } @@ -57,22 +62,31 @@ } } -#selectable { +.selectable { list-style-type: none; margin: 0; padding: 0; } -#selectable li { +.selectable li { border: 1px solid LightGray; - margin: 3px; padding: 0.4em; + margin-top: 6px; + margin-bottom: 6px; text-align: center; border-radius: 5px; + word-wrap: break-word; +} + +.leftOptions { + margin-right: 2px; +} + +.rightOptions { + margin-left: 2px; } .select-result { - width:100%; padding: 0em; margin: 0px; } @@ -86,7 +100,23 @@ border-radius: 5px; } -#remove-btn { +.selected_left { + width:45%; + word-break: break-all; + padding-top: 5px; + padding-bottom: 5px; + padding-left: 10px; +} + +.selected_right { + width:45%; + word-break: break-all; + padding-top: 5px; + padding-bottom: 5px; + padding-right: 5px; +} + +.remove-btn { -moz-box-shadow: inset 0 0 2px #000000; -webkit-box-shadow: inset 0 0 2px #000000; box-shadow: inset 0 0 2px #000000; @@ -223,17 +253,24 @@ } } + /* ======================================== RESULT TABLE ======================================== */ +#result-table { + table-layout:fixed; +} + #result-table th { text-align: center; vertical-align: middle; + word-wrap: break-word; } -#result-table td { +#result-table-td { text-align: center; + word-wrap: break-word; margin: 0px !important; padding: 0px !important; } @@ -243,6 +280,6 @@ padding: 0px !important; } -.isCorrect { - border: 2px solid green !important; +.greenBorder { + border: 3px solid green !important; } diff --git a/app/controllers/surveys_controller.rb b/app/controllers/surveys_controller.rb index 501fb33..99f4e69 100755 --- a/app/controllers/surveys_controller.rb +++ b/app/controllers/surveys_controller.rb @@ -251,7 +251,7 @@ def vote elsif @survey.has_answer_pairs? if @survey.type == "match" unless params[:option].nil? - voted_for = "
    "+params[:option].map { |o| o+"
    "}.join + voted_for = "
      "+params[:option].map { |o| "
    • "+o+"
    • "}.join + "
    " else voted_for = t("matrix_keys.no_answer") end diff --git a/app/services/match_survey.rb b/app/services/match_survey.rb index 564ea92..d894ad4 100755 --- a/app/services/match_survey.rb +++ b/app/services/match_survey.rb @@ -55,7 +55,7 @@ def vote(voter, word_pairs) self.survey.add_to_set(:voters, voter.to_s) if word_pairs.respond_to?(:each) word_pairs.each do |pair| - pairArray = pair.split(' - ') + pairArray = pair.split(' ~-~ ') if(pairArray.length == 2) self.survey.answer_pairs.where(answer1: pairArray[0], answer2: pairArray[1]).first.vote_up end @@ -63,7 +63,7 @@ def vote(voter, word_pairs) elsif word_pairs.nil? # MC and nothing selected else - pairArray = word_pairs.split(' - ') + pairArray = word_pairs.split(' ~-~ ') if(pairArray.length == 2) self.survey.answer_pairs.where(answer1: pairArray[0], answer2: pairArray[1]).first.vote_up end diff --git a/app/views/surveys/_answer_pair_result_table.html.erb b/app/views/surveys/_answer_pair_result_table.html.erb index e3919c7..fae4123 100755 --- a/app/views/surveys/_answer_pair_result_table.html.erb +++ b/app/views/surveys/_answer_pair_result_table.html.erb @@ -2,17 +2,18 @@ - <% answer2s = survey.get_all_answer2 %> + <% columnWidthPercentage = number_to_percentage(1.to_f / (1 + answer2s.length).to_f * 100.to_f, :precision => 0) %> + <% answer2s.shuffle! %> <% answer2s.each do |answer2| %> - + <% end %> <% survey.answer_pairs.where(correct: true).each do |pair1| %> - + <% answer2s.each do |answer2| %> <% percentage = "0%" %> <% current_answer_pair = survey.answer_pairs.where(answer1: pair1.answer1, answer2: answer2).first %> @@ -20,17 +21,17 @@ <% percentage = number_to_percentage(current_answer_pair.votes.to_f / survey.total_votes.to_f * 100.to_f, :precision => 0) %> <% end %> <% if current_answer_pair.correct? %> - <% else %> - <% end %> diff --git a/app/views/surveys/_match_lists.html.erb b/app/views/surveys/_match_lists.html.erb index fec2eff..d7a0d58 100755 --- a/app/views/surveys/_match_lists.html.erb +++ b/app/views/surveys/_match_lists.html.erb @@ -2,20 +2,20 @@ -
      <%= answer2 %><%= answer2 %>
    <%= pair1.answer1 %>
    <%= pair1.answer1 %> -
    -
    -

    <%= percentage %>

    +
    +
    +
    +

    <%= percentage %>

    -
    -
    -

    <%= percentage %>

    +
    +
    +
    +

    <%= percentage %>

    +
    <% answer1s = survey.get_all_answer1 %> <% answer2s = survey.get_all_answer2 %> <% answer2s.shuffle! %> - - ' + + return( '' + '' + @@ -62,7 +66,16 @@ } $(document).ready(function(){ - $(".leftOptions").delegate(".left","click",function(){ + + $(".selectable").width($(window).width()/2 - 23); + $(".select-result").width($(window).width() - 40); + + $(window).resize(function(){ + $(".selectable").width($(window).width()/2 - 23); + $(".select-result").width($(window).width() - 40); + }); + + $(".leftOptions").delegate(".left","click",function(){ var leftbox = $(this); removeClazz("selected", ".left"); @@ -74,8 +87,8 @@ removeClazz("selected", ".left"); removeClazz("selected", ".right"); - leftbox.hide(500); - $(element).hide(500); + leftbox.hide(100); + $(element).hide(100); $(".select-result").append( writeSelectResultRow(leftbox.text(), $(element).text()) @@ -96,8 +109,8 @@ removeClazz("selected", ".left"); removeClazz("selected", ".right"); - $(element).hide(500); - rightbox.hide(500); + $(element).hide(100); + rightbox.hide(100); $(".select-result").append( writeSelectResultRow($(element).text(), rightbox.text()) @@ -106,18 +119,19 @@ }); }); - $(".select-result").delegate("#remove-btn","click",function(){ - var tableRow = $(this).parent().parent(); - var answerpair = tableRow.find(":contains(' - ')").text().split(" - "); + $(".select-result").delegate(".remove-btn","click",function(){ + var div = $(this).parent().parent().parent().parent(); + var answer1 = div.find(".selected_left").first().text(); + var answer2 = div.find(".selected_right").first().text(); $(".leftOptions").append('
  • ' + - answerpair[0] + + answer1 + '
  • ' ); $(".rightOptions").append('
  • ' + - answerpair[1] + + answer2 + '
  • ' ); - tableRow.parent().parent().parent().parent().remove(); + div.parent().parent().remove(); }); }); diff --git a/app/views/surveys/_show.html.erb b/app/views/surveys/_show.html.erb index b58bcb0..6b028ae 100755 --- a/app/views/surveys/_show.html.erb +++ b/app/views/surveys/_show.html.erb @@ -75,7 +75,7 @@
    - <%= icon_tag("download-alt") %> + <%= icon_tag("download-alt") %> <% if survey.options.any?(&:correct) %> <%= t("surveys.show.mark_corrects") %> @@ -98,7 +98,7 @@

    <%= t("results") %>

    <%= render partial: "answer_pair_result_table", locals: {survey: survey} %> - <%= icon_tag("download-alt") %> + <%= icon_tag("download-alt") %> <%= t("surveys.show.mark_corrects") %>
    @@ -182,7 +182,11 @@ <%= select_tag "duration", options_for_select(duration_choices(false), 120), id: "repeatDuration" %> - + <% end %> From 96b6d5557793b851d9bc9781d95532dfa56392aa Mon Sep 17 00:00:00 2001 From: KKrenz Date: Sun, 1 Mar 2015 17:05:23 +0100 Subject: [PATCH 07/22] Commit-Nachricht --- app/models/answer_pair.rb | 8 --- app/models/question.rb | 18 ------ app/views/questions/_match_form.html.erb | 78 +++++++++++++++++++++--- 3 files changed, 70 insertions(+), 34 deletions(-) diff --git a/app/models/answer_pair.rb b/app/models/answer_pair.rb index fba0f1c..bd8d792 100755 --- a/app/models/answer_pair.rb +++ b/app/models/answer_pair.rb @@ -12,14 +12,6 @@ class AnswerPair validates_presence_of :answer1 validates_presence_of :answer2 - def self.buildnew(answer1 = "answer1", answer2 = "answer2", correct = false) - ap = AnswerPair.new - ap.answer1 = answer1 - ap.answer2 = answer2 - ap.correct = correct - return ap - end - def vote_up self.inc(:votes, 1) end diff --git a/app/models/question.rb b/app/models/question.rb index acdee43..9b59353 100755 --- a/app/models/question.rb +++ b/app/models/question.rb @@ -33,8 +33,6 @@ def self.question_types has_and_belongs_to_many :collaborators, class_name: "User", inverse_of: :shared_questions index :collaborator_ids, sparse: true - before_save :fill_up_answer_pairs - # this is where we setup getting the service objects def service case type @@ -128,20 +126,4 @@ def delete_all_false_answer_pairs end end - # adds all possible combinations of false answer_pairs to the collection "answer_pairs" - private - def fill_up_answer_pairs - if(self.answer_pairs.any?) - self.answer_pairs.where(correct: true).each do |pair1| - self.answer_pairs.where(correct: true).each do |pair2| - if(pair1.answer1 != pair2.answer1) - if(pair1.answer2 != pair2.answer2) - self.add_to_set(:answer_pairs, AnswerPair.buildnew(pair1.answer1, pair2.answer2, false)) - end - end - end - end - end - end - end \ No newline at end of file diff --git a/app/views/questions/_match_form.html.erb b/app/views/questions/_match_form.html.erb index 1ced556..3df4d6f 100755 --- a/app/views/questions/_match_form.html.erb +++ b/app/views/questions/_match_form.html.erb @@ -1,4 +1,4 @@ -<%= semantic_form_for question, namespace: "match", html: { class: "form-inline ", id: "new_match_question" } do |form| %> +<%= semantic_form_for question, namespace: "match", html: { class: "form-inline", id: "new_match_question", onsubmit: "fill_up_answer_pairs()" } do |form| %> <%= error_msg_for question %>
    @@ -20,10 +20,19 @@

    <%= t("surveys.edit.answer_pairs_for_match_survey") %>

    -
    - <%= form.semantic_fields_for :answer_pairs, class: "form-inline" do |pair| %> - <%= render "match_question_answer_pair_fields", f: pair %> +
    + <% if question.answer_pairs.any? %> + <% question.answer_pairs.each do |answerpair| %> + <% if answerpair.correct? %> + <%= form.fields_for :answer_pairs, answerpair do |pair| %> + <%= render "match_question_answer_pair_fields", f: pair %> + <% end %> + <% end %> + <% end %> <% end %> + @@ -41,16 +50,69 @@ <% end %> <% content_for :javascript do %> <% end %> \ No newline at end of file From a825f7c70821a9a74ae790ed4d9544092b9bf88f Mon Sep 17 00:00:00 2001 From: KKrenz Date: Thu, 5 Mar 2015 23:43:53 +0100 Subject: [PATCH 08/22] finally fix fill_up_answer_pairs --- app/assets/javascripts/answer_pair.js.coffee | 3 + app/assets/stylesheets/answer_pair.css.less | 3 + app/controllers/answer_pair_controller.rb | 7 ++ app/controllers/questions_controller.rb | 12 +++- app/helpers/answer_pair_helper.rb | 2 + app/models/question.rb | 16 +++-- app/views/questions/_match_form.html.erb | 68 +------------------ app/views/questions/index.html.erb | 6 +- config/locales/models/questions.en.yml | 9 ++- .../answer_pair_controller_spec.rb | 5 ++ 10 files changed, 56 insertions(+), 75 deletions(-) create mode 100644 app/assets/javascripts/answer_pair.js.coffee create mode 100644 app/assets/stylesheets/answer_pair.css.less create mode 100644 app/controllers/answer_pair_controller.rb create mode 100644 app/helpers/answer_pair_helper.rb create mode 100644 spec/controllers/answer_pair_controller_spec.rb diff --git a/app/assets/javascripts/answer_pair.js.coffee b/app/assets/javascripts/answer_pair.js.coffee new file mode 100644 index 0000000..7615679 --- /dev/null +++ b/app/assets/javascripts/answer_pair.js.coffee @@ -0,0 +1,3 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/ diff --git a/app/assets/stylesheets/answer_pair.css.less b/app/assets/stylesheets/answer_pair.css.less new file mode 100644 index 0000000..b3b91c2 --- /dev/null +++ b/app/assets/stylesheets/answer_pair.css.less @@ -0,0 +1,3 @@ +// Place all the styles related to the AnswerPair controller here. +// They will automatically be included in application.css. +// You can use Less here: http://lesscss.org/ diff --git a/app/controllers/answer_pair_controller.rb b/app/controllers/answer_pair_controller.rb new file mode 100644 index 0000000..2493599 --- /dev/null +++ b/app/controllers/answer_pair_controller.rb @@ -0,0 +1,7 @@ +class AnswerPairController < ApplicationController + def create + @question = Question.find(params[:question_id]) + @answer_pair = @question.answer_pairs.create!(params[:answer_pair]) + redirect_to @question, :notice => "Comentario criado!" + end +end diff --git a/app/controllers/questions_controller.rb b/app/controllers/questions_controller.rb index e073606..41c9270 100755 --- a/app/controllers/questions_controller.rb +++ b/app/controllers/questions_controller.rb @@ -103,7 +103,7 @@ def new end def edit - @question.delete_all_false_answer_pairs + delete_all_false_answer_pairs end def update @@ -283,10 +283,18 @@ def check_access redirect_to questions_path, status: :forbidden and return false end true - end + end def question_params params.require(:question).permit(:name, :type, :description, :tags, :public, :collaborators_form, question_options_attributes: [:name, :correct, :id, :_destroy], answer_pairs_attributes: [:answer1, :answer2, :correct, :id, :_destroy]) end + def delete_all_false_answer_pairs + if(@question.answer_pairs.any?) + @question.answer_pairs.where(correct: false).each do |pair| + pair.delete + end + end + end + end diff --git a/app/helpers/answer_pair_helper.rb b/app/helpers/answer_pair_helper.rb new file mode 100644 index 0000000..5d4a761 --- /dev/null +++ b/app/helpers/answer_pair_helper.rb @@ -0,0 +1,2 @@ +module AnswerPairHelper +end diff --git a/app/models/question.rb b/app/models/question.rb index 9b59353..1ecbf2f 100755 --- a/app/models/question.rb +++ b/app/models/question.rb @@ -33,6 +33,8 @@ def self.question_types has_and_belongs_to_many :collaborators, class_name: "User", inverse_of: :shared_questions index :collaborator_ids, sparse: true + after_save :fill_up_answer_pairs + # this is where we setup getting the service objects def service case type @@ -117,11 +119,17 @@ def collaborators_form=(v) end end - - def delete_all_false_answer_pairs + # adds all wrong answer pairs to the collection answer_pairs of the just saved match question + def fill_up_answer_pairs if(self.answer_pairs.any?) - self.answer_pairs.where(correct: false).each do |pair| - pair.delete + self.answer_pairs.where(correct: true).each do |pair1| + self.answer_pairs.where(correct: true).each do |pair2| + if(pair1.answer1 != pair2.answer1) + if(pair1.answer2 != pair2.answer2) + self.answer_pairs.create(:answer1 => pair1.answer1, :answer2 => pair2.answer2, :correct => false) + end + end + end end end end diff --git a/app/views/questions/_match_form.html.erb b/app/views/questions/_match_form.html.erb index 3df4d6f..d2b193c 100755 --- a/app/views/questions/_match_form.html.erb +++ b/app/views/questions/_match_form.html.erb @@ -21,18 +21,9 @@

    <%= t("surveys.edit.answer_pairs_for_match_survey") %>

    - <% if question.answer_pairs.any? %> - <% question.answer_pairs.each do |answerpair| %> - <% if answerpair.correct? %> - <%= form.fields_for :answer_pairs, answerpair do |pair| %> - <%= render "match_question_answer_pair_fields", f: pair %> - <% end %> - <% end %> - <% end %> - <% end %> - + <% end %> @@ -43,66 +34,13 @@ <%= form.hidden_field :collaborators_form, class:"collaborators-form" %> <%= form.submit class: "btn btn-primary", id: "single_question_submit" %> <% if params[:redirect_to_session] %> - <% end %>(<%= link_to t("questions.chart_notice"), "#chartNoticeModal", data: {toggle: "modal"} %>) <% end %> <% content_for :javascript do %> +<% end %> \ No newline at end of file diff --git a/app/views/questions/_order_option.html.erb b/app/views/questions/_order_option.html.erb new file mode 100644 index 0000000..d2a5db9 --- /dev/null +++ b/app/views/questions/_order_option.html.erb @@ -0,0 +1,5 @@ +
  • + <%= order_option.position %> + ) + <%= order_option.name %> +
  • diff --git a/app/views/questions/_order_question_order_option_fields.html.erb b/app/views/questions/_order_question_order_option_fields.html.erb new file mode 100644 index 0000000..dc10526 --- /dev/null +++ b/app/views/questions/_order_question_order_option_fields.html.erb @@ -0,0 +1,7 @@ +
    +
    + <%= link_to_remove_association icon_tag("minus-sign"), f %> + <%= f.text_field :name, placeholder: t("name") %> + <%= f.number_field :position, placeholder: t("position") %> +
    +
    diff --git a/app/views/questions/import.html.erb b/app/views/questions/import.html.erb index 19cebc3..28423d5 100755 --- a/app/views/questions/import.html.erb +++ b/app/views/questions/import.html.erb @@ -39,7 +39,7 @@

    <%= t(".csv_info") %>

    - <%= link_to(icon_tag(:file) + "Excelvorlage laden", "/templates/csv-import-template.xlsx", class: "btn") %> + <%= link_to(icon_tag(:file) + t(".csv_template_load"), "/templates/csv-import-template.csv", class: "btn") %>
    <%= t(".aiken_info") %> @@ -130,6 +130,10 @@
    + + + + @@ -153,7 +157,7 @@ - + @@ -189,11 +193,11 @@ - + - + diff --git a/app/views/questions/index.html.erb b/app/views/questions/index.html.erb index f9db7c1..ffa0a01 100755 --- a/app/views/questions/index.html.erb +++ b/app/views/questions/index.html.erb @@ -60,6 +60,8 @@ <%= link_to icon_tag("th") + t("type.number"), questions_path(tag: params[:tag], q_type: "number", public: params[:public], shared: params[:shared]) %>
  • "> <%= link_to icon_tag("random") + t("type.match"), questions_path(tag: params[:tag], q_type: "match", public: params[:public], shared: params[:shared]) %>
  • +
  • "> + <%= link_to icon_tag("list") + t("type.order"), questions_path(tag: params[:tag], q_type: "order", public: params[:public], shared: params[:shared]) %>
  • @@ -80,40 +82,41 @@ <% unless @questions.empty? %>
    -
      +
    +
      <% for j in 0..(answer1s.length - 1) %>
    1. <%= answer1s[j] %>
    2. <% end %>
    -
      +
    +
      <% for j in 0..(answer2s.length - 1) %>
    1. <%= answer2s[j] %>
    2. <% end %> @@ -37,24 +37,28 @@ } function writeSelectResultRow(anzwer1, anzwer2) { - return( '
    ' + - '
    ' + - '' + + '
    ' + + '
    ' + '' + '' + '' + '' + '
    ' + - '
    <%= icon_tag "remove" %>
    ' + + '
    <%= icon_tag "remove" %>
    ' + '
    ' + - anzwer1 + - ' - ' + - anzwer2 + + '' + + '' + + '' + + '' + + '' + + '' + + '
    ' + anzwer1 + ' - ' + anzwer2 + '
    ' + '
    ' + '' + '
    ' + '
      Erste Spalte enthält "number" Numerische Frage
      Erste Spalte enthält "match"Zuordnungsfrage
    Moodle XML
      matchNicht unterstütztZuordnungsfrage
      cloze
      MatchingNicht unterstütztZuordnungsfrage
      Missing WordNicht unterstütztFreitext-Frage
      Numerical
    - - - - - + + + + + + <% @questions.each do |question| %> - + <%= + if (question.public) + icon_tag("globe") + elsif (question.collaborators.size > 0) + icon_tag("share") + end + %> + + <% if params[:public] %> - <% if question.user == current_user %> - - - <% else %> - - - <% end %> + <% if question.user == current_user %> + + + + <% else %> + + + <% end %> <% else %> - - + + + <% end %> <% end %> @@ -123,7 +126,6 @@ <%= hidden_field_tag "share_user_id" %> <%= render :partial => 'export_button' %> <%= render :partial => 'share_button', locals: {no_modal: false} %> - <% else %>

    <%= t(".no_questions_yet") %>

    diff --git a/app/views/questions/new.html.erb b/app/views/questions/new.html.erb index b5e6e42..16aebd1 100755 --- a/app/views/questions/new.html.erb +++ b/app/views/questions/new.html.erb @@ -10,6 +10,7 @@
  • <%= t "type.text" %>
  • <%= t "type.number" %> BETA
  • <%= t "type.match" %>
  • +
  • <%= t "type.order" %>
  • @@ -30,6 +31,9 @@
    <%= render partial: @question_match.form_partial, locals: {question: @question_match} %>
    +
    + <%= render partial: @question_order.form_partial, locals: {question: @question_order} %> +
    diff --git a/app/views/questions/show.html.erb b/app/views/questions/show.html.erb index d73c7e1..76d854a 100755 --- a/app/views/questions/show.html.erb +++ b/app/views/questions/show.html.erb @@ -16,6 +16,8 @@ <%= t("questions.show.type_number") %> <% elsif @question.type == "match" %> <%= t("questions.show.type_match") %> +<% elsif @question.type == "order" %> + <%= t("questions.show.type_order") %> <% end %>

    Tags: <%= @question.tags_array.join(", ") %>

    @@ -35,6 +37,13 @@ <% end %> +<% if @question.has_order_options? %> + <%= t("surveys.show.order_options") %> +
      + <%= render partial: "order_option", collection: @question.order_options %> +
    +<% end %> + <% if @question.can_be_accessed_by?(current_user) %> <%= link_to t("edit"), edit_question_path(@question), class: "btn btn-small" %> <%= link_to t("delete"), @question, confirm: t("questions.index.delete_sure"), method: :delete, class: "btn btn-small" %> diff --git a/app/views/surveys/_order_list.html.erb b/app/views/surveys/_order_list.html.erb new file mode 100644 index 0000000..1f8b51d --- /dev/null +++ b/app/views/surveys/_order_list.html.erb @@ -0,0 +1,30 @@ + + + + + + +
      +
    • testWordA
    • +
    • testWordB
    • +
    • testWordC
    • +
    • testWordD
    • +
    +
    + + + \ No newline at end of file diff --git a/app/views/surveys/_order_option_result_table.html.erb b/app/views/surveys/_order_option_result_table.html.erb new file mode 100644 index 0000000..df925c2 --- /dev/null +++ b/app/views/surveys/_order_option_result_table.html.erb @@ -0,0 +1,46 @@ + +
      - <%= t "name" %> 
     <%= t "name" %> 
    <%= check_box_tag("question_ids[]", question.id, false, class: "questions-table__checkbox") %> - <%= - if (question.public) - icon_tag("globe") - elsif (question.collaborators.size > 0) - icon_tag("share") - end - %> - <%= link_to (question.name||""), question_path(question), class: "questionLink" %> <%= link_to (question.name||""), question_path(question), class: "questionLink" %> <%= link_to icon_tag("pencil"), edit_question_path(question), title: t("edit") %> <%= link_to icon_tag("minus-sign"), question, - title: t(".delete_question"), confirm: t(".delete_sure"), method: :delete %><%= link_to icon_tag("plus-sign"), add_to_own_question_path(question, format: :json), remote: true, method: :post, class: "add_to_own_link", title: t("questions.show.add_to_own") %>  <%= link_to icon_tag("pencil"), edit_question_path(question), title: t("edit") %> <%= link_to icon_tag("plus-sign"), {:action => 'clone', :id => question.id}, title: t("duplicate") %> <%= link_to icon_tag("minus-sign"), question, title: t(".delete_question"), confirm: t(".delete_sure"), method: :delete %><%= link_to icon_tag("plus-sign"), add_to_own_question_path(question, format: :json), remote: true, method: :post, class: "add_to_own_link", title: t("questions.show.add_to_own") %>  <%= link_to icon_tag("pencil"), edit_question_path(question), title: t("edit"), class: "question_edit_link" %> <%= link_to icon_tag("minus-sign"), question, - title: t(".delete_question"), confirm: t(".delete_sure"), method: :delete %><%= link_to icon_tag("pencil"), edit_question_path(question), title: t("edit"), class: "question_edit_link" %> <%= link_to icon_tag("plus-sign"), {:action => 'clone', :id => question.id}, title: t("duplicate") %> <%= link_to icon_tag("minus-sign"), question, + title: t(".delete_question"), confirm: t(".delete_sure"), method: :delete %>
    + + + <% numberOfOptions = survey.order_options.length %> + <% columnWidthPercentage = number_to_percentage(1.to_f / (1 + numberOfOptions).to_f * 100.to_f, :precision => 0) %> + + <% for index in 1..numberOfOptions %> + + <% end %> + + + + <% survey.order_options.shuffle! %> + <% survey.order_options.each do |option| %> + + <% currentPosition = 1 %> + <% option.votes.split(",").each do |votesForPosition| %> + <% votesForPositionInteger = Integer(votesForPosition) %> + <% percentage = "0%" %> + <% if survey.total_votes > 0 %> + <% percentage = number_to_percentage(votesForPositionInteger.to_f / total_votes.to_f * 100.to_f, :precision => 0) %> + <% end %> + <% rowHeightPercentage = number_to_percentage(1.to_f / (1 + survey.order_options.length).to_f * 100.to_f, :precision => 0) %> + <% if option.position == currentPosition %> + + <% else %> + + <% end %> + <% currentPosition += 1 %> + <% end %> + + <% end %> + +
    Position<%= index %>
    <%= option.name %> +
    +
    +

    <%= percentage %>

    +
    +
    +
    +
    +

    <%= percentage %>

    +
    +
    + \ No newline at end of file diff --git a/app/views/surveys/_show.html.erb b/app/views/surveys/_show.html.erb index dc40422..ee9a4f9 100755 --- a/app/views/surveys/_show.html.erb +++ b/app/views/surveys/_show.html.erb @@ -24,6 +24,9 @@ <% if survey.type == "match" %>

    <%= t ".is_match" %>

    <% end %> + <% if survey.type == "order" %> +

    <%= t ".is_order" %>

    + <% end %> <% if survey.running?(true) %>

    @@ -99,6 +102,18 @@

    +<% elsif survey.has_order_options? %> +
    +
    +

    <%= t("results") %>

    +
    + <%= render partial: "order_option_result_table", locals: {survey: survey} %> + <%= icon_tag("download-alt") %> + <%= t("surveys.show.mark_corrects") %> +
    +
    +
    + <% elsif survey.type == "text" %> <% if !survey.running? && survey.total_votes > 0 %>
    diff --git a/config/locales/defaults/de.yml b/config/locales/defaults/de.yml index 2f1237e..edf37c3 100755 --- a/config/locales/defaults/de.yml +++ b/config/locales/defaults/de.yml @@ -24,6 +24,7 @@ de: remove: "Entfernen" start: "Starten" name: "Name" + position: "Position (1,2,3, ...)" description: "Beschreibung" there_were_errors_saving: "Beim Speichern sind Fehler aufgetreten" forgot_password: "Passwort vergessen?" @@ -51,6 +52,7 @@ de: comments: Kommentare survey: Umfrage share: "Freigeben" + duplicate: "Duplizieren" matrix_keys: no_participation: n. Teiln. @@ -81,6 +83,7 @@ de: single: "Single Choice" multi: "Multiple Choice" match: "Zuordnen" + order: "Reihenfolge" truefalse: "Wahr/Falsch-Frage" yesno: "Ja/Nein-Frage" agree: "Zustimmen/Nicht zustimmen-Frage" @@ -113,6 +116,7 @@ de: question_successfully_created: "Frage erfolgreich erstellt." question_successfully_updated: "Frage erfolgreich geändert." question_successfully_added: "Frage(n) erfolgreich hinzugefügt" + question_successfully_duplicated: "Frage erfolgreich dupliziert." no_access_to_question: "Sie sind nicht dazu berechtigt, auf diese Frage zuzugreifen." no_access_to_survey: "Sie sind nicht dazu berechtigt, auf diese Session / Umfrage zuzugreifen." invite_success: "Einladung versendet. Danke für's Weiterempfehlen!" diff --git a/config/locales/defaults/en.yml b/config/locales/defaults/en.yml index 228fc70..f714fd6 100755 --- a/config/locales/defaults/en.yml +++ b/config/locales/defaults/en.yml @@ -25,6 +25,7 @@ en: start: "Start" there_were_errors_saving: "Errors occured during saving" name: "Name" + position: "Position (1,2,3, ...)" description: "Description" forgot_password: "Forgot your password?" remember_me: "Remember me" @@ -50,6 +51,7 @@ en: comments: comments survey: Survey share: Share + duplicate: "Duplicate" matrix_keys: no_participation: no part. @@ -80,6 +82,7 @@ en: single: "Single Choice" multi: "Multiple Choice" match: "Match" + order: "Order" truefalse: "True/False Question" yesno: "Yes/No Question" agree: "Agree/Disagree Question" @@ -112,6 +115,7 @@ en: question_successfully_created: "Question successfully created." question_successfully_updated: "Question successfully updated." question_successfully_added: "Question successfully added" + question_successfully_duplicated: "Question successfully duplicated." no_access_to_question: "You do not have access to this question." token_reset_success: "You've been signed off from all third-party apps that were connected to your PINGO account." select_questions_for_export: "Please select questions for export" diff --git a/config/locales/views/questions.de.yml b/config/locales/views/questions.de.yml index e19506d..e49dcbc 100755 --- a/config/locales/views/questions.de.yml +++ b/config/locales/views/questions.de.yml @@ -14,6 +14,7 @@ de: questions_header: Fragen-Schlagwörter all_tags: Alle zeigen delete_question: Frage löschen + delete_questions: Fragen löschen delete_sure: Diese Frage wirklich löschen? own_questions: Eigene Fragen shared_questions: Freigegebene Fragen @@ -30,6 +31,7 @@ de: shared_question: "Für Sie von %{by} freigegebene Frage" type_number: Numerisch type_match: Zuordnen + type_order: Reihenfolge new: please_choose_question_type_to_continue: "Bitte wählen Sie links einen Fragetyp (Single/Multiple-Choice, Text, Numerisch oder Zuordnen) aus." comments: @@ -42,10 +44,11 @@ de: select_type: Dateiformat auswählen tags: Tags upload: Hochladen und importieren - moodle_xml_info: "Zurzeit werden die Moodle XML-Formate truefalse, shortanswer, multichoice, numerical und essay unterstützt." - csv_info: "Zurzeit werden als Trennzeichen ausschließlich Kommata akzeptiert. Das Format sieht vor, dass eine Zeile pro Frage verwendet wird. Die erste Spalte stellt den Typ der Frage dar (single, multi, number oder text). Spalte zwei enthält den Text der Frage. Danach folgen genau 9 Spalten, die Antwortmöglichkeiten enthalten können. Die letzte Spalte ist optional und enthält bei Multiple-Choice-Fragen die Nummern der korrekten Antworten, bei mehreren getrennt durch ein Semikolon (zum Beispiel 1;3;5). Bei Freitextfragen enthält sie die Limitierung für die Anzahl der abzugebenden Antworten (1 für eine, 3 für bis zu drei)." + moodle_xml_info: "Zurzeit werden die Moodle XML-Formate truefalse, shortanswer, multichoice, numerical, match und essay unterstützt." + csv_info: "Zurzeit werden als Trennzeichen ausschließlich Kommata akzeptiert. Das Format sieht vor, dass eine Zeile pro Frage verwendet wird. Die erste Spalte stellt den Typ der Frage dar (single, multi, number, match oder text). Spalte zwei enthält den Text der Frage. Spalte drei enthält Zahlen, die durch Semikolon getrennt sind, wobei diese Zahlen für all jene Antwortmöglichkeiten stehen, die korrekt sind (zum Beispiel 1;3;5). Bei Freitextfragen enthält sie die Limitierung für die Anzahl der abzugebenden Antworten (1 für eine, 3 für bis zu drei). Die letzten Spalten enthalten je eine Antwortmöglichkeit. Bei Zuordnungsfragen werden nur die korrekten Paarungen angegeben, wobei die Paare durch ' - ' getrennt sind." + csv_template_load: "CSV-Vorlage laden" aiken_info: "Jede Frage im Aiken-Format muss eine Angabe korrekter Antworten enthalten" - gift_info: "Zurzeit werden True / False, Multiple Choice, Short Answer, Essay und Numerical-Fragetypen im Gift-Format unterstützt" + gift_info: "Zurzeit werden True / False, Multiple Choice, Short Answer, Essay, Matching und Numerical-Fragetypen im Gift-Format unterstützt" ilias_info: "Zurzeit werden Multiple Choice, Single Choice, Freitext, Begriffe benennen und Numerische Fragen im Ilias-Format unterstützt." further_information: "Für weitere Informationen darüber, wie Formate interpretiert werden, klicken Sie hier" upload_questions_legend: "Wählen Sie eine Datei und das Format aus, um Fragen in PINGO zu importieren." diff --git a/config/locales/views/questions.en.yml b/config/locales/views/questions.en.yml index 0630678..28e60b8 100755 --- a/config/locales/views/questions.en.yml +++ b/config/locales/views/questions.en.yml @@ -14,6 +14,7 @@ en: questions_header: Question tags all_tags: show all delete_question: Delete question + delete_questions: Delete questions delete_sure: Do you really want to delete this question? own_questions: Own questions shared_questions: Shared questions @@ -30,6 +31,7 @@ en: shared_question: "shared question from %{by}" type_number: Numerical type_match: Match + type_order: Order comments: placeholder: Enter your comment here. show_session: show related survey @@ -40,10 +42,11 @@ en: select_type: Select type tags: Tags upload: Upload and import - moodle_xml_info: "Currently the Moodle XML formats truefalse, shortanswer, multichoice, numerical and essay are supported." - csv_info: "Currently commas are accepted as separator exclusively. The format is specified as follows: Each line contains one question. The first column specifies the type of the question (single, multi, number or text). Column two contains the text of the question. The following nine columns may contain question options. The last column is optional an can contain the numbers of the correct answers for multiple choice questions, in case of multiple correct answers separated by a semicolon (e.g. 1;3;5). In case of text questions it contains the limitation of the quantity of answers a respondent can give (1 for one, 3 for up to three)." + moodle_xml_info: "Currently the Moodle XML formats truefalse, shortanswer, multichoice, numerical, match and essay are supported." + csv_info: "Currently commas are accepted as separator exclusively. The format is specified as follows: Each line contains one question. The first column specifies the type of the question (single, multi, number, match or text). Column two contains the text of the question. Column three consists of numbers, that are seperated by semicolons, where these numbers stand for the correct answer options. (zum Beispiel 1;3;5). If it's a text question, this column holds the limitations for the numbers of answers to give (1 for one, 3 for up to three). In each of the following columns is an answer option. In case of match questions, only the correct pairings are given, whereby a pair is seperated by ' - '." + csv_template_load: "Load CSV-template" aiken_info: "Any question in written in Aiken must specify correct answers" - gift_info: "Currently True / False, Multiple Choice, Short Answer, Essay and Numerical questions are supported for the Gift format" + gift_info: "Currently True / False, Multiple Choice, Short Answer, Essay, Matching and Numerical questions are supported for the Gift format" ilias_info: "Currently Multiple Choice, Single Choice, Text, Textsubset and Numeric questions are supported for the Ilias format." further_information: "For further information on how imported files are interpreted click here" upload_questions_legend: "Please choose a file and format to import questions into PINGO." diff --git a/config/locales/views/surveys.de.yml b/config/locales/views/surveys.de.yml index 4f470dc..466ab15 100755 --- a/config/locales/views/surveys.de.yml +++ b/config/locales/views/surveys.de.yml @@ -9,8 +9,10 @@ de: edit_survey: Umfrage bearbeiten add_option: Antwortmöglichkeit hinzufügen add_answer_pair: Antwortpaar hinzufügen + add_order_option: Zu ordnende Option hinzufügen options_for_survey: Antwortmöglichkeiten für diese Umfrage answer_pairs_for_match_survey: Antwortpaare für diese Umfrage + order_options_for_order_survey: Zu ordnende Begriffe für diese Umfrage changed: header: Vergleich des Antwortverhaltens wait: "Einen Moment bitte, Daten werden berechnet" @@ -30,6 +32,7 @@ de: choose-number: "Bitte geben Sie eine Zahl ein" choose-match: "Bitte ordnen Sie die Felder einander zu, indem Sie nacheinander eines auf der linken und eines auf der rechten Seite anklicken" chosen-match: "Sie haben zugeordnet" + choose-order: "Sie verändern die Reihenfolge der Felder durch Anklicken, Verschieben und Loslassen (Drag and Drop)" show: survey: Umfrage from: vom @@ -39,6 +42,7 @@ de: running: Am laufen? is_text: Dies ist eine Freitext-Frage. is_match: Dies ist eine Zuordnungsfrage. + is_order: Dies ist eine Reihenfolge-Frage. votes_participants: Teilnehmer is_multi: Dies ist eine Multiple-Choice-Umfrage. running_notice: 'Diese Umfrage läuft. Teilnahme ist über %{url} möglich.' @@ -46,6 +50,7 @@ de: time_left: "Zeit übrig" options: Antwortmöglichkeiten answer_pairs: Antwortpaare + order_options: Zu ordnende Begriffe correct_answer_pairs: Korrekte Antwortpaare stop1: Stoppen start1: Jetzt starten diff --git a/config/locales/views/surveys.en.yml b/config/locales/views/surveys.en.yml index ccdac05..37cda69 100755 --- a/config/locales/views/surveys.en.yml +++ b/config/locales/views/surveys.en.yml @@ -9,8 +9,10 @@ en: edit_survey: Edit survey add_option: Add option add_answer_pair: Add answer pair + add_order_option: Add option to bring in order options_for_survey: Answer options for this survey answer_pairs_for_match_survey: Answer pairs for this survey + order_options_for_order_survey: Options to bring in order changed: header: Comparison of voting behaviour wait: "One moment please, gathering data" @@ -30,6 +32,7 @@ en: choose-number: "Please enter your (numerical) answer" choose-match: "Please match the fields by successively clicking one on the left and one on the right side" chosen-match: "You've matched" + choose-order: "Change the order of the fields via drag and drop." show: survey: Survey from: from @@ -39,6 +42,7 @@ en: running: running? is_text: This is a text question is_match: This is a match question + is_order: This is an order question. votes_participants: participants is_multi: This is a multiple-choice survey. running_notice: 'This survey is running. People can access this survey at %{url}' @@ -46,6 +50,7 @@ en: time_left: time left options: options answer_pairs: answer pairs + order_options: Options to bring in order correct_answer_pairs: correct answer pairs stop1: stop start1: start now diff --git a/config/routes.rb b/config/routes.rb index 039d7b6..016a52d 100755 --- a/config/routes.rb +++ b/config/routes.rb @@ -52,6 +52,7 @@ resources :questions do member do post 'add_to_own' + get 'clone' end resources :question_comments, only: [:create, :destroy, :index] collection do diff --git a/log.txt b/log.txt index 1b2964d..e69de29 100644 --- a/log.txt +++ b/log.txt @@ -1,4 +0,0 @@ -D, [2015-03-25T17:06:55.474238 #548] DEBUG -- : Log file created -D, [2015-03-25T17:06:55.475108 #548] DEBUG -- : Start... -D, [2015-03-25T17:12:30.431707 #548] DEBUG -- : Log file created -D, [2015-03-25T17:12:30.432547 #548] DEBUG -- : Start... diff --git a/public/templates/.DS_Store b/public/templates/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5008ddfcf53c02e82d7eee2e57c38e5672ef89f6 GIT binary patch literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0lypefJ9_qc-J8AN z@B0JJd49i{;bB-8_r0FA*0thRRe*s70^k9N004jjkS22J`5FoUfQ1JDumOnB22##W z?p99jCYs(ZR&GYDUXBjr`LNLRxd3R$-~ade57t1B=AhF@cFZ=N9Wm*4?KiKbw6tK+ zjbd1^e!wUSV@CEg3U{AhWTgg_MFe8XwprG1v2Y#lV(`6qTS1=toELAgf(ol9WU6n> z?U=_~B}Y22phEj?eOx3vnrURNt*(=ykr4eS9ic5h z%5+Nv28@eO=~1kamdxlD(!$8B0NNp`*B#-K!-pFWTs0Pi{WsG5&CSy zS;ujaE|v-(ZBQ2OT9wBqB}2Z-NLMk-z_M6^)ltboO`FN$qE+Rnf0X`PrH=(gbO)ku zUd)o%ck=sLiN4*l%5Zk;C@M#$PJ>vnz-$XvEr1BEsLW{w%HL5{8D8R7zuKiusD8?IrJ!EZ=G18bj6w6SeN0{)gWhx(LFrC z0960txnM1JsvnSV6d{g@0`XiES1SiMHrAi-|Ml4aU^o5K)+-W}RJz$wLl0$d!v-#9 z7UM7_6+9(m-&1J%2gog8fTQ106D@Yo5o2l+2Ejai)#iUYG`}buy)!^@zQ$bHXZ+efmSjO_^l01dMWh&6rv2-owII9jJ z5_TbRD6UA_YyCbYy(RO@DySJrjs42dnkK&7oy75sSF_1Q-_gXv1r+x_rQr;?nOlFU z@*QxXIJ+X$(y$S*tufDb6{Pewv2^G>mCoqEzVl^K&Kyvu9DmwRlY90`zk&OB zILo_-52?F+;Ak)~lB{G2LSlb+68X|1vulV(p27eCgaAY+F9)`N`H82qtG&6iv;9wk z`?t?PL0Arg@}GTuNEo&2VMh%<3~3LVY^9OAPdN#IUVjGseKk#uq9&7v$k!uGR~5oG96vN>(=B z@i}{C70dVHl%@RYrfJS6NXVJh|z%5m{=O zo|}X{{-}dj&W_96M$xhD{zMbU1So@VP!e-vSn2|8Z;f&Fpy9l;^9&PLyZd4Eq(z?- z>rfXfw7_cIa*ddCHraoSn|U&d(yu8hSjc6-M&nk`h#Kp+b6v~CJt}tYs{OEo@=umS z$MU?684_AOU;zLOh)F;!=g&4%psD1R0U<-rq6dkYbwUev4|VtfYA3FZ*KR^n)rG`DFs#S?D)%)SHCU1|Syc%P&af zyVZ(dJ!+Z+frl1M(uk-rc5WfBMRBagQfESnWA3PLHi|*Fy%9nR$n<(tcUVgJE63gR zG5LBoG`KHVM07`mN21S5R_m`H%5}m-s!>~|+PlX=x}8NfR>K;;oY^(t_ZIDx(QgT| z=*oS#+LWdit(@ZnT)Hyr>Q-S6TrN^P8RR{wclbWAsoH&^^R- z{vMKMlxR^fAmJzml7OTA%dp(sy&bIFeukn3Z6oIlcA#HQ!$ZKW@|Dd%0%A#ek?h+> zTXjL(YV_2eGO;)gqffREezW+{2K8XO*%VWg`7P3ApMw``ks{V(B5FKuDJ8nnVu>kT z^;Bz>CT8bHvM7o_>jG2dB(U7cd0J(cJ0k7wa&-3pKsm%lG^bsJ==_#VnxhQWgC>eb%- z1-bMn6l%tgy~{gxQJJ*MEuBekSUm?SlWsU+bDd+jh3^8u5Us%AzQ11gL{Nf4oCqUQ zh@vBMgjoXc-pJNajQ=9_HI2A2;Z}m&hD|ssracR^o4Kc<8Hg_;-H~Q9iKIe+JCrwd zQB--=u5X)wG+Bwzd8CT(Vy3mCi_Xdc2xTv8F%V2EZ&|bB{%u|gP6vmaP=O#hd!bG1 z5;J&mJ788Y*g#$@KsIddqKNxh!89g}Oq0;*OkLn|^fV!7dLLY`0RuaiSv~oN2;K|S!HJD7Y zrZsQFfo>Dsf;&Lepwc-^AN~Tb5TrUsI_Oh(@DQDmhAXdu(yMt@$ALm zwziA;VlfBsZI+-=={C#+=S*t1V6998n@K{DSk+C-Dp7u2V?WyLeU7Fv$rW8bOqFZ_?^1V{WQyRgdw=_13?O0{_4CYg+MWy_C#^NmJQX-c{*$uYyj)lZ`;(EY> z9<-^Z{$5zLZz=`3Xkp3=``40(g-#S$+)-lbpD`7qG3sW??6Ru%B;P0 zOwx0c&H7+HQ~E$yziPq86>L~p*Ftu!BlfgUK5rBH3rO6X*_3x1NA zHrapvdBAzh0KXvc#+&*NQx z7gChT&UkHjMnGslA;*5#PxC<(d+F#Y%VR||CiN+W4j_gvIAu7d=fv0ph{`*Q8sIB!I)ovg`ZD}y8zz#)Dv5EZfv-W zZ}4W^2$vE)Lyu>kZiNn6x4^ThIr90+(jigHzq0^DViArrn__KGhf!9Rf72hQi-S@d zqDFm(-|gS?r8WksG){E$i`*M;_Q9)2qKS$!JI50fga$Tc@FDZMpH7gVh`QeWUW^}^ zu+zJaG1-&xU^#&}Q_*}`fdQHQlK^vxUC;Audp~s8BFB;8({rSM(g03%nQ$9q=S=@U z4RHKP1Ea{0sxA01@DTId>C;Qh_#$KJBgQkRWXqc%N36QzVrOU8z`zwp>y*1^MPJ2= z)fN~|R8Nz;z^pvbL1)7c6P6u)W)y{do^|_oGeT zcm*-$r0C0mQBEw2r*c6_ha??g>YD?(JMw;76(*29{ylQ?e2ur&gHSRv#5(Z*_WXZ8 z`J|*_r+IcvnG3jU4A_gwZVyU>8e&+Ez-MZ?HrKjS(*u-}cDf0TiN1be>MZ!tD9zB+ z#~gyhOD$_B=e;(K2wONFIOB;?T-(&2%jUIjZ<@l&1*}EGt8fX0N-mka{NG<+nt6*~ z>=^`fhEH5YG*QfPDz!OuA?Dp|=Jl$Ihc?&DngtP!PpF z88{F+JOasuk!HkUvXWr=b!^GB%D!pP{~Y0gX=RO`96D4|a(|Vyfp#L8@!Z~2nUbC4P4Pa}T^`#6UO(^0ZjqgwGISP! z*HNlcR33u9z1?)G^Sl$=%xUq6YLRvRMnNf>u=2ENeIe9#`JWOAa7LvGBU0}DE@850 zPp_2X$0O~>cvrfEB2>rL#}K&t3vUV#baSrtVQcjTh1u&6Wqg?OS5FeYTD#>@n{OLM z?RVsA2_rR{;0(K~Fv_;R;gfu4nIg&H(POpseCnZ7Z7+Oy{G04aWc|CjCwv02RQqgw zkl$t8hYU&)lx8Y*~`+p5{#S)=DrW*&YRWN z@=cHL|GtePpB>YzKKZagy8Gc`)oZNMA41oEH%DwG%!mj`+iaESXY1@&hUji%;0Dp?&*y>5%FQR<82FJ`lv8}NiZjfhfzpg5!KKf^sl=3i;lTeFMGwYyDJ74 z2s^^fl)nYUbFWLKgDO{)J3OsK#MM{b!wFR6m{Ktb7Up~}vUa_sdZ{T8H;Y|ingVr8 z9W1P5LfNA>w6f!Y+0o6iHG$QX`UJ?n(5~2xb^4{;+E|KHfI@z#+V{Gu49{x>-p*T* z3u~!k1S=BTmG;1pl4|itD_e#kxku?S1@MI47O0Sx063U&gl*t(PO&Q-j7_?TuBeNW zM_5L7({g-`Ma{e#>^=i0O&e{%I`+o%*@Jw5qM>G|rupyM)+eZdFbap69rYx=-AbK# zjWoEpJKf~P(rG3hJd?N%?N2RVoSJq=4e^+!1NQp$kvfcRryI3NK0xXDwgp#%n*_5$ zgZRiJos*8*>_YGDfgu_g;z zBkb~4J_2I2rS2rKR1O5<55_!Lu_UKQR}Ix*HOsBj|E~3UrTV@yO@*gTbcwu~eH=Zc zj=Mlhf)mKCQMuw5M+hXZ&VF^VbEWZP=PGe3Y+RY_-s^gM@_RQ~1+(=Uy7IfVo|I+Z z>wX=wyyYDKyOZNB{}0S-udeRD<-EEc!3c)UIDF{EQ}OpZU++!Hxjo;v!0=UAk$AFH zj1<4kDxyE#4ab@N=5e^e7tKLLBodCY)V z<>658i3b)q-G7-u{9aZTaYT6N0?BQ}3p*A^*_ZN$-%KXx&>ZI`NjNjSCVW>OE;|PC zTZs_$^#>+{dl;x27XCY2c)`2h7CSLsfZ3*@_>eC&?spfD$6;g?C z^M>)a814OwsFTZG82m;%2k(>k4@5H%4<-iGY)Q$l2X(zFyb@jb$mkq`-R@Zf!K zoIIQ|{?#oX9z6$dr^rDiS!bVWXf7|Ey^cv~m37sZ@Z5Bw0a#R<34X4JN_I-y)g=R+ zAt38=Mxk|V7R6O^TwY`mZOJN_K>rO({uP&lzF8glyn8c{(Pygs^9wwSQYmwAf0&0? ztf6LB zf%Qe@8$DP)tvoE=y>Z27*i~-Mymw}LA@8y6FFu8mkPZZE&g=H^a*w0Mu*kJRCBxtD9Wrw`&fop==mT|EQy>~t-C zXw4Wk@@1mkV6$cFWxvmHl*yrUk*ejLCPiE|)-x?Q1>?BnnWHl&^>XhaHS2IKKutp9 z^&H^`B0DvWzLJPJdzIm)9V%yU!#x8P9hd7uTB?g#htXh}e~4-}bGuhZsmD4XttnxY zrUyn?PpxU+>RN3{0@V)pb@En2K16NWfuMfiW#A25^!& zI`2-_LCn97fFzQ%vI?;<^qG6PXtXRtxXj)!e7;)&4db`o9yk~ceCkmDZagtpzcykt zHrP9>lY__Q;bhkTxmSMH!cO*UFK}jKvLTTphU0K9;_&0;iYWg}q9uW-w1jiVk1)+z z!K~fwjREUTV>}vs5C2$$x~(Nn_d_x%2?%}tADPrI{)*BvfRv;7Kg&_mt2T~;_0RxD z$8?@WL8bTZ<1rjv5nUr5lBb6k1R(7M2RqV0$C&Y}18F|C5NV&PXjQAIyVqe)*wW-> zTHYMT9uAi?fcidh7OKA$?n7`oQaZUe(qwAm5!k|olCm|=G%yGW#!o&COn+VGh2+dx zh+=0}&ex-vKGo2oDa-le0|!G1{qteWohFwOX6z_7;5^QU29`IQ3Hmk5>-n4{23<>% zI;w4pS~`k2II0yP!1IYXbIlqTFvHs-dnEskODHQ6&w7D(Y_L;9B_rqoF%6;FH^Nk0 z(28acho83XUYe!hYQH+G*B-T>mE&{b7Plr1NeIDTDGTEb){ z=DvWJ1uaGFanQ*DuU9iGzIP#q87~r?cqg%tO$GAnF^U8fQuQ~)>Sj_s^Xs`2_;_(0 zw*eQv9Ol~$AULPMz$2ga8`yzfr>2j^Bd1fl@`B<#K#|DFgnwWQ6z6?k<}{TdnUGTo zJaU(U<^a3V?7S!4Ym+=zm4K5oV+Lu;Yc0#`JIxObXtgnxXZfx5O`vsVK5_A?27hYn zZk*Zdb~*6ra_1%piX#dVlDo4kU9Fp9pmG(Cl3m8EdFa`uE?Zf`o*{xFmCfc6;q8)b za@orLN`f&+OE!`bLWyf>8AV}@g^ zs&v(}(eDc148og~4BqR;A6u1Fbg)c^?MAj)$h-kpH=ry5?JN>riaZ>LCBDG1E_cU8 z0*HIM66bT`CW(y&l}3YfY|T(}&gkqq zrV7ESy&9&XZWKz$@+IuH z6LlDNeNVT=hHj#K7*qEY)E;U5S#hIPb*lS#vfRSGc>%a%`toRJrMH&w%(S!+l)?d& zf70Eh_wZ!*euAy~>u_Gw$@qp9wE>iJ{45%OOQ@ftp-dtRVN_3$*PVg*%7>i9*4QM@ zqU_4u@V;%m5__y~gOisoFN3+`tyq;+&-Nb5@E0k-9LI;W+|-ehG8&wWlU!}LR2-eA ztvp>Ad3obB)n4DC@P!_hrs*{aQ`+h)MoJ?armIwE`r9kI)D7)+7shN)QWL*bPMKyf zmD^i3yAg|#j5<`h^{gBc6YWa*er-9}Z_>H|%YXT(34Ss_Pu|)< zX5wTk%%{9$Ub0XnD+Z)y=}9<2TvJ?sjxy6E3U(Gm$MdjxMMm8uaQwC)Ucku;L9!b` z-9I7}Cik-RNZ z>4Pm^a)0+lZJ-c0tuq{eVx|PWvbCk+Igun09>^LsRV~m5X&= z`Mt-IHWaF=f=P?IHT+tCPiFg&l~CX?5t+-hNj+WYwfrl-^x@ zXIalG*(3KEN54M1w2_j>#WS|4iw-a6TQ*OVUjmGThhamZ8dA>P&=u?8>MkGOUOHGG z9$}$9AY{r&TBn1Bbvg6NZi@$ePB3ilfA;SG9s^LjNeX_>g=8Qk2>e&==4NB&YGtY6 z?)ozj{A{1Ne^OI`;Xnnfcy>LgUKe0g%}+bpRZGFQqnskRdp_4`F0xK+-Cv%kVAQ;x zW0S*{{BgaFaEugh*a;e=)nEY3PY5jVojBgO)+YqcnOlbiOblSh8Di8iBge}N9gr#;dE498ucDBwU=Dht(8ZJ-L?!_o3{U>t|mW{!u@Qy znL%{*1TsUjbhc1+b#`%Mvv78``l%?$xcR@MGl=Sf6C~`r$?-!EgYLpsMAQ;FBB&YM z-xcG)@6OFB{jet_j4mOJN>~a%v1G3j0vh_q|o#u^hG6$ z4mnSg%fPWiJ(+2D)^f1kpo_N}~auv0IZm`6NdLEiX^tu3f(Lr92 z5u6LeJKe2ZHLTp-fARIBdk$7}TPIhG0qYXe0ZV!_RZ~QBSu0sfS*QdVabrLbN)S;h zEA-G7lvY5`Boq}2)i6n}>Foo^0|c)es<%K(%zzq&x`!$lr6^7)&B@NsnQFRCZ33{Q zL=3P2QAasZLKgA&SaM}5A&02d^bf{1@9~%GKmiK*HcXFqeY8DtloR@q|@Fkng#*4ME@r|nJ z;6i#427`2XOV-QDC$oozi`4tu4Q0I3~$9F1- z$V=fKJr&V;tvukykzBmR7tW>Xw*V*_T}@q+Nb+kGd!2}LAyFBS|KngL>Mn+I{?(-) z*8!adBe@ZV4P-=F_*h)`AGuK<5Nz4ULvpP#J|H~Q0ArpJPR zJ<;)J!DUD>`+uMBc#QLSzW*DE08$q`n)W{yemukdE$j+8OaKx7J<)wE`gn--TeJfG zfB*0QYozrU@bOIOH((Vc_xWQZe+T?k;`}=K@)+>(nB_NM1?FSG-$R$jD3812zfpuB z&2q@H9{0*013d0g{02BD_{U}Z+ROIu8H< From 4d3b182ea163c7c0f2c7cb7135adda06e67be6c4 Mon Sep 17 00:00:00 2001 From: KKrenz Date: Wed, 15 Apr 2015 14:43:27 +0200 Subject: [PATCH 13/22] =?UTF-8?q?Kleine=20Korrektur=20Ilias=20Parser,=20Er?= =?UTF-8?q?ste=20Versuche=20f=C3=BCr=20Teilnahme=20an=20Reihenfolge-Fragen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/parsers/ilias_parser.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/parsers/ilias_parser.rb b/app/parsers/ilias_parser.rb index 03f5b7e..e762de6 100755 --- a/app/parsers/ilias_parser.rb +++ b/app/parsers/ilias_parser.rb @@ -192,7 +192,9 @@ def import (xml_file, user, tags) end end elsif question_type == 'MATCHING QUESTION' - element.elements.each(#...) + element.elements.each do |elem| + #TODO implement + end end q.user = user From 5fbba1e2de658b5cf90ab9ed318ead44813bc578 Mon Sep 17 00:00:00 2001 From: KKrenz Date: Wed, 15 Apr 2015 19:46:38 +0200 Subject: [PATCH 14/22] Finish participate partial for order_questions --- app/assets/stylesheets/surveys.css.less | 10 + app/services/order_survey.rb | 4 +- app/views/surveys/_order_list.html.erb | 66 +- app/views/surveys/_show.html.erb | 9 +- config/locales/defaults/de.yml | 2 + config/locales/defaults/en.yml | 2 + public/scripts/Sortable.js | 1106 +++++++++++++++++++++++ public/scripts/Sortable.min.js | 2 + 8 files changed, 1170 insertions(+), 31 deletions(-) create mode 100755 public/scripts/Sortable.js create mode 100755 public/scripts/Sortable.min.js diff --git a/app/assets/stylesheets/surveys.css.less b/app/assets/stylesheets/surveys.css.less index ea30189..413b914 100755 --- a/app/assets/stylesheets/surveys.css.less +++ b/app/assets/stylesheets/surveys.css.less @@ -6,6 +6,16 @@ #survey-options-list li { margin-bottom:10px; } + +.move_handler { + cursor: move; +} + +.ghost { + opacity: .5; + background: #FECA40; +} + #overmsg { display:none; background-color: #FCC; diff --git a/app/services/order_survey.rb b/app/services/order_survey.rb index edbde0f..e6b1beb 100644 --- a/app/services/order_survey.rb +++ b/app/services/order_survey.rb @@ -24,11 +24,13 @@ def vote(voter, option_position_pairs) if self.survey.running?(false) unless self.survey.matches?(voters: voter) #:fixme: is this "enough" concurrency safe? self.survey.add_to_set(:voters, voter.to_s) + #TODO: erstelle objekt zum füllen der relativen Tabelle if option_position_pairs.respond_to?(:each) option_position_pairs.each do |pair| pairArray = pair.split(' - ') if(pairArray.length == 2) - self.survey.order_options.where(name: pairArray[0]).first.vote_up(Integer(pairArray[1])) + #TODO rausfinden, warum folgender Befehl nicht funktionert + self.survey.order_options.where(name: pairArray[0]).first.vote_up(Integer(pairArray[1])) end end elsif option_position_pairs.nil? diff --git a/app/views/surveys/_order_list.html.erb b/app/views/surveys/_order_list.html.erb index 1f8b51d..2cf73c0 100644 --- a/app/views/surveys/_order_list.html.erb +++ b/app/views/surveys/_order_list.html.erb @@ -1,30 +1,38 @@ - - - - - - -
      -
    • testWordA
    • -
    • testWordB
    • -
    • testWordC
    • -
    • testWordD
    • -
    -
    - +
    +
      + <% survey.order_options.shuffle! %> + <% survey.order_options.each do |option| %> +
    • <%= option.name %>
    • + <% end %> +
    +
    +
    +
    - \ No newline at end of file + + + + + \ No newline at end of file diff --git a/app/views/surveys/_show.html.erb b/app/views/surveys/_show.html.erb index ee9a4f9..8f30b7a 100755 --- a/app/views/surveys/_show.html.erb +++ b/app/views/surveys/_show.html.erb @@ -105,7 +105,14 @@ <% elsif survey.has_order_options? %>
    -

    <%= t("results") %>

    +

    <%= t("absolute_results") %>

    +
    + <%= render partial: "order_option_result_table", locals: {survey: survey} %> + <%= icon_tag("download-alt") %> + <%= t("surveys.show.mark_corrects") %> +
    +

    <%= t("relative_results") %>

    +
    <%= render partial: "order_option_result_table", locals: {survey: survey} %> <%= icon_tag("download-alt") %> diff --git a/config/locales/defaults/de.yml b/config/locales/defaults/de.yml index edf37c3..58ec397 100755 --- a/config/locales/defaults/de.yml +++ b/config/locales/defaults/de.yml @@ -38,6 +38,8 @@ de: password_confirmation: "Bestätigen Sie Ihr Kennwort" update: "Aktualisieren" results: "Ergebnisse" + absolute_results: "Absolute Ergebnisse" + relative_results: "Relative Ergebnisse" optional: "optional" positive: "positiv" neutral: "neutral" diff --git a/config/locales/defaults/en.yml b/config/locales/defaults/en.yml index f714fd6..e982f14 100755 --- a/config/locales/defaults/en.yml +++ b/config/locales/defaults/en.yml @@ -37,6 +37,8 @@ en: password_confirmation: "Password confirmation" update: "Update" results: "results" + absolute_results: "Absolute Results" + relative_results: "Relative Results" optional: "optional" positive: "positive" neutral: "neutral" diff --git a/public/scripts/Sortable.js b/public/scripts/Sortable.js new file mode 100755 index 0000000..4527f6c --- /dev/null +++ b/public/scripts/Sortable.js @@ -0,0 +1,1106 @@ +/**! + * Sortable + * @author RubaXa + * @license MIT + */ + + +(function (factory) { + "use strict"; + + if (typeof define === "function" && define.amd) { + define(factory); + } + else if (typeof module != "undefined" && typeof module.exports != "undefined") { + module.exports = factory(); + } + else if (typeof Package !== "undefined") { + Sortable = factory(); // export for Meteor.js + } + else { + /* jshint sub:true */ + window["Sortable"] = factory(); + } +})(function () { + "use strict"; + + var dragEl, + ghostEl, + cloneEl, + rootEl, + nextEl, + + scrollEl, + scrollParentEl, + + lastEl, + lastCSS, + + oldIndex, + newIndex, + + activeGroup, + autoScroll = {}, + + tapEvt, + touchEvt, + + /** @const */ + RSPACE = /\s+/g, + + expando = 'Sortable' + (new Date).getTime(), + + win = window, + document = win.document, + parseInt = win.parseInt, + + supportDraggable = !!('draggable' in document.createElement('div')), + + _silent = false, + + _dispatchEvent = function (sortable, rootEl, name, targetEl, fromEl, startIndex, newIndex) { + var evt = document.createEvent('Event'), + options = (sortable || rootEl[expando]).options, + onName = 'on' + name.charAt(0).toUpperCase() + name.substr(1); + + evt.initEvent(name, true, true); + + evt.item = targetEl || rootEl; + evt.from = fromEl || rootEl; + evt.clone = cloneEl; + + evt.oldIndex = startIndex; + evt.newIndex = newIndex; + + if (options[onName]) { + options[onName].call(sortable, evt); + } + + rootEl.dispatchEvent(evt); + }, + + abs = Math.abs, + slice = [].slice, + + touchDragOverListeners = [], + + _autoScroll = _throttle(function (/**Event*/evt, /**Object*/options, /**HTMLElement*/rootEl) { + // Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=505521 + if (rootEl && options.scroll) { + var el, + rect, + sens = options.scrollSensitivity, + speed = options.scrollSpeed, + + x = evt.clientX, + y = evt.clientY, + + winWidth = window.innerWidth, + winHeight = window.innerHeight, + + vx, + vy + ; + + // Delect scrollEl + if (scrollParentEl !== rootEl) { + scrollEl = options.scroll; + scrollParentEl = rootEl; + + if (scrollEl === true) { + scrollEl = rootEl; + + do { + if ((scrollEl.offsetWidth < scrollEl.scrollWidth) || + (scrollEl.offsetHeight < scrollEl.scrollHeight) + ) { + break; + } + /* jshint boss:true */ + } while (scrollEl = scrollEl.parentNode); + } + } + + if (scrollEl) { + el = scrollEl; + rect = scrollEl.getBoundingClientRect(); + vx = (abs(rect.right - x) <= sens) - (abs(rect.left - x) <= sens); + vy = (abs(rect.bottom - y) <= sens) - (abs(rect.top - y) <= sens); + } + + + if (!(vx || vy)) { + vx = (winWidth - x <= sens) - (x <= sens); + vy = (winHeight - y <= sens) - (y <= sens); + + /* jshint expr:true */ + (vx || vy) && (el = win); + } + + + if (autoScroll.vx !== vx || autoScroll.vy !== vy || autoScroll.el !== el) { + autoScroll.el = el; + autoScroll.vx = vx; + autoScroll.vy = vy; + + clearInterval(autoScroll.pid); + + if (el) { + autoScroll.pid = setInterval(function () { + if (el === win) { + win.scrollTo(win.pageXOffset + vx * speed, win.pageYOffset + vy * speed); + } else { + vy && (el.scrollTop += vy * speed); + vx && (el.scrollLeft += vx * speed); + } + }, 24); + } + } + } + }, 30) + ; + + + + /** + * @class Sortable + * @param {HTMLElement} el + * @param {Object} [options] + */ + function Sortable(el, options) { + this.el = el; // root element + this.options = options = _extend({}, options); + + + // Export instance + el[expando] = this; + + + // Default options + var defaults = { + group: Math.random(), + sort: true, + disabled: false, + store: null, + handle: null, + scroll: true, + scrollSensitivity: 30, + scrollSpeed: 10, + draggable: /[uo]l/i.test(el.nodeName) ? 'li' : '>*', + ghostClass: 'sortable-ghost', + ignore: 'a, img', + filter: null, + animation: 0, + setData: function (dataTransfer, dragEl) { + dataTransfer.setData('Text', dragEl.textContent); + }, + dropBubble: false, + dragoverBubble: false, + dataIdAttr: 'data-id', + delay: 0 + }; + + + // Set default options + for (var name in defaults) { + !(name in options) && (options[name] = defaults[name]); + } + + + var group = options.group; + + if (!group || typeof group != 'object') { + group = options.group = { name: group }; + } + + + ['pull', 'put'].forEach(function (key) { + if (!(key in group)) { + group[key] = true; + } + }); + + + options.groups = ' ' + group.name + (group.put.join ? ' ' + group.put.join(' ') : '') + ' '; + + + // Bind all private methods + for (var fn in this) { + if (fn.charAt(0) === '_') { + this[fn] = _bind(this, this[fn]); + } + } + + + // Bind events + _on(el, 'mousedown', this._onTapStart); + _on(el, 'touchstart', this._onTapStart); + + _on(el, 'dragover', this); + _on(el, 'dragenter', this); + + touchDragOverListeners.push(this._onDragOver); + + // Restore sorting + options.store && this.sort(options.store.get(this)); + } + + + Sortable.prototype = /** @lends Sortable.prototype */ { + constructor: Sortable, + + _onTapStart: function (/** Event|TouchEvent */evt) { + var _this = this, + el = this.el, + options = this.options, + type = evt.type, + touch = evt.touches && evt.touches[0], + target = (touch || evt).target, + originalTarget = target, + filter = options.filter; + + + if (type === 'mousedown' && evt.button !== 0 || options.disabled) { + return; // only left button or enabled + } + + target = _closest(target, options.draggable, el); + + if (!target) { + return; + } + + // get the index of the dragged element within its parent + oldIndex = _index(target); + + // Check filter + if (typeof filter === 'function') { + if (filter.call(this, evt, target, this)) { + _dispatchEvent(_this, originalTarget, 'filter', target, el, oldIndex); + evt.preventDefault(); + return; // cancel dnd + } + } + else if (filter) { + filter = filter.split(',').some(function (criteria) { + criteria = _closest(originalTarget, criteria.trim(), el); + + if (criteria) { + _dispatchEvent(_this, criteria, 'filter', target, el, oldIndex); + return true; + } + }); + + if (filter) { + evt.preventDefault(); + return; // cancel dnd + } + } + + + if (options.handle && !_closest(originalTarget, options.handle, el)) { + return; + } + + + // Prepare `dragstart` + this._prepareDragStart(evt, touch, target); + }, + + _prepareDragStart: function (/** Event */evt, /** Touch */touch, /** HTMLElement */target) { + var _this = this, + el = _this.el, + options = _this.options, + ownerDocument = el.ownerDocument, + dragStartFn; + + if (target && !dragEl && (target.parentNode === el)) { + tapEvt = evt; + + rootEl = el; + dragEl = target; + nextEl = dragEl.nextSibling; + activeGroup = options.group; + + dragStartFn = function () { + // Delayed drag has been triggered + // we can re-enable the events: touchmove/mousemove + _this._disableDelayedDrag(); + + // Make the element draggable + dragEl.draggable = true; + + // Disable "draggable" + options.ignore.split(',').forEach(function (criteria) { + _find(dragEl, criteria.trim(), _disableDraggable); + }); + + // Bind the events: dragstart/dragend + _this._triggerDragStart(touch); + }; + + _on(ownerDocument, 'mouseup', _this._onDrop); + _on(ownerDocument, 'touchend', _this._onDrop); + _on(ownerDocument, 'touchcancel', _this._onDrop); + + if (options.delay) { + // If the user moves the pointer before the delay has been reached: + // disable the delayed drag + _on(ownerDocument, 'mousemove', _this._disableDelayedDrag); + _on(ownerDocument, 'touchmove', _this._disableDelayedDrag); + + _this._dragStartTimer = setTimeout(dragStartFn, options.delay); + } else { + dragStartFn(); + } + } + }, + + _disableDelayedDrag: function () { + var ownerDocument = this.el.ownerDocument; + + clearTimeout(this._dragStartTimer); + + _off(ownerDocument, 'mousemove', this._disableDelayedDrag); + _off(ownerDocument, 'touchmove', this._disableDelayedDrag); + }, + + _triggerDragStart: function (/** Touch */touch) { + if (touch) { + // Touch device support + tapEvt = { + target: dragEl, + clientX: touch.clientX, + clientY: touch.clientY + }; + + this._onDragStart(tapEvt, 'touch'); + } + else if (!supportDraggable) { + this._onDragStart(tapEvt, true); + } + else { + _on(dragEl, 'dragend', this); + _on(rootEl, 'dragstart', this._onDragStart); + } + + try { + if (document.selection) { + document.selection.empty(); + } else { + window.getSelection().removeAllRanges(); + } + } catch (err) { + } + }, + + _dragStarted: function () { + if (rootEl && dragEl) { + // Apply effect + _toggleClass(dragEl, this.options.ghostClass, true); + + Sortable.active = this; + + // Drag start event + _dispatchEvent(this, rootEl, 'start', dragEl, rootEl, oldIndex); + } + }, + + _emulateDragOver: function () { + if (touchEvt) { + _css(ghostEl, 'display', 'none'); + + var target = document.elementFromPoint(touchEvt.clientX, touchEvt.clientY), + parent = target, + groupName = ' ' + this.options.group.name + '', + i = touchDragOverListeners.length; + + if (parent) { + do { + if (parent[expando] && parent[expando].options.groups.indexOf(groupName) > -1) { + while (i--) { + touchDragOverListeners[i]({ + clientX: touchEvt.clientX, + clientY: touchEvt.clientY, + target: target, + rootEl: parent + }); + } + + break; + } + + target = parent; // store last element + } + /* jshint boss:true */ + while (parent = parent.parentNode); + } + + _css(ghostEl, 'display', ''); + } + }, + + + _onTouchMove: function (/**TouchEvent*/evt) { + if (tapEvt) { + var touch = evt.touches ? evt.touches[0] : evt, + dx = touch.clientX - tapEvt.clientX, + dy = touch.clientY - tapEvt.clientY, + translate3d = evt.touches ? 'translate3d(' + dx + 'px,' + dy + 'px,0)' : 'translate(' + dx + 'px,' + dy + 'px)'; + + touchEvt = touch; + + _css(ghostEl, 'webkitTransform', translate3d); + _css(ghostEl, 'mozTransform', translate3d); + _css(ghostEl, 'msTransform', translate3d); + _css(ghostEl, 'transform', translate3d); + + evt.preventDefault(); + } + }, + + + _onDragStart: function (/**Event*/evt, /**boolean*/useFallback) { + var dataTransfer = evt.dataTransfer, + options = this.options; + + this._offUpEvents(); + + if (activeGroup.pull == 'clone') { + cloneEl = dragEl.cloneNode(true); + _css(cloneEl, 'display', 'none'); + rootEl.insertBefore(cloneEl, dragEl); + } + + if (useFallback) { + var rect = dragEl.getBoundingClientRect(), + css = _css(dragEl), + ghostRect; + + ghostEl = dragEl.cloneNode(true); + + _css(ghostEl, 'top', rect.top - parseInt(css.marginTop, 10)); + _css(ghostEl, 'left', rect.left - parseInt(css.marginLeft, 10)); + _css(ghostEl, 'width', rect.width); + _css(ghostEl, 'height', rect.height); + _css(ghostEl, 'opacity', '0.8'); + _css(ghostEl, 'position', 'fixed'); + _css(ghostEl, 'zIndex', '100000'); + + rootEl.appendChild(ghostEl); + + // Fixing dimensions. + ghostRect = ghostEl.getBoundingClientRect(); + _css(ghostEl, 'width', rect.width * 2 - ghostRect.width); + _css(ghostEl, 'height', rect.height * 2 - ghostRect.height); + + if (useFallback === 'touch') { + // Bind touch events + _on(document, 'touchmove', this._onTouchMove); + _on(document, 'touchend', this._onDrop); + _on(document, 'touchcancel', this._onDrop); + } else { + // Old brwoser + _on(document, 'mousemove', this._onTouchMove); + _on(document, 'mouseup', this._onDrop); + } + + this._loopId = setInterval(this._emulateDragOver, 150); + } + else { + if (dataTransfer) { + dataTransfer.effectAllowed = 'move'; + options.setData && options.setData.call(this, dataTransfer, dragEl); + } + + _on(document, 'drop', this); + } + + setTimeout(this._dragStarted, 0); + }, + + _onDragOver: function (/**Event*/evt) { + var el = this.el, + target, + dragRect, + revert, + options = this.options, + group = options.group, + groupPut = group.put, + isOwner = (activeGroup === group), + canSort = options.sort; + + if (evt.preventDefault !== void 0) { + evt.preventDefault(); + !options.dragoverBubble && evt.stopPropagation(); + } + + if (activeGroup && !options.disabled && + (isOwner + ? canSort || (revert = !rootEl.contains(dragEl)) + : activeGroup.pull && groupPut && ( + (activeGroup.name === group.name) || // by Name + (groupPut.indexOf && ~groupPut.indexOf(activeGroup.name)) // by Array + ) + ) && + (evt.rootEl === void 0 || evt.rootEl === this.el) + ) { + // Smart auto-scrolling + _autoScroll(evt, options, this.el); + + if (_silent) { + return; + } + + target = _closest(evt.target, options.draggable, el); + dragRect = dragEl.getBoundingClientRect(); + + + if (revert) { + _cloneHide(true); + + if (cloneEl || nextEl) { + rootEl.insertBefore(dragEl, cloneEl || nextEl); + } + else if (!canSort) { + rootEl.appendChild(dragEl); + } + + return; + } + + + if ((el.children.length === 0) || (el.children[0] === ghostEl) || + (el === evt.target) && (target = _ghostInBottom(el, evt)) + ) { + if (target) { + if (target.animated) { + return; + } + targetRect = target.getBoundingClientRect(); + } + + _cloneHide(isOwner); + + el.appendChild(dragEl); + this._animate(dragRect, dragEl); + target && this._animate(targetRect, target); + } + else if (target && !target.animated && target !== dragEl && (target.parentNode[expando] !== void 0)) { + if (lastEl !== target) { + lastEl = target; + lastCSS = _css(target); + } + + + var targetRect = target.getBoundingClientRect(), + width = targetRect.right - targetRect.left, + height = targetRect.bottom - targetRect.top, + floating = /left|right|inline/.test(lastCSS.cssFloat + lastCSS.display), + isWide = (target.offsetWidth > dragEl.offsetWidth), + isLong = (target.offsetHeight > dragEl.offsetHeight), + halfway = (floating ? (evt.clientX - targetRect.left) / width : (evt.clientY - targetRect.top) / height) > 0.5, + nextSibling = target.nextElementSibling, + after + ; + + _silent = true; + setTimeout(_unsilent, 30); + + _cloneHide(isOwner); + + if (floating) { + after = (target.previousElementSibling === dragEl) && !isWide || halfway && isWide; + } else { + after = (nextSibling !== dragEl) && !isLong || halfway && isLong; + } + + if (after && !nextSibling) { + el.appendChild(dragEl); + } else { + target.parentNode.insertBefore(dragEl, after ? nextSibling : target); + } + + this._animate(dragRect, dragEl); + this._animate(targetRect, target); + } + } + }, + + _animate: function (prevRect, target) { + var ms = this.options.animation; + + if (ms) { + var currentRect = target.getBoundingClientRect(); + + _css(target, 'transition', 'none'); + _css(target, 'transform', 'translate3d(' + + (prevRect.left - currentRect.left) + 'px,' + + (prevRect.top - currentRect.top) + 'px,0)' + ); + + target.offsetWidth; // repaint + + _css(target, 'transition', 'all ' + ms + 'ms'); + _css(target, 'transform', 'translate3d(0,0,0)'); + + clearTimeout(target.animated); + target.animated = setTimeout(function () { + _css(target, 'transition', ''); + _css(target, 'transform', ''); + target.animated = false; + }, ms); + } + }, + + _offUpEvents: function () { + var ownerDocument = this.el.ownerDocument; + + _off(document, 'touchmove', this._onTouchMove); + _off(ownerDocument, 'mouseup', this._onDrop); + _off(ownerDocument, 'touchend', this._onDrop); + _off(ownerDocument, 'touchcancel', this._onDrop); + }, + + _onDrop: function (/**Event*/evt) { + var el = this.el, + options = this.options; + + clearInterval(this._loopId); + clearInterval(autoScroll.pid); + + clearTimeout(this.dragStartTimer); + + // Unbind events + _off(document, 'drop', this); + _off(document, 'mousemove', this._onTouchMove); + _off(el, 'dragstart', this._onDragStart); + + this._offUpEvents(); + + if (evt) { + evt.preventDefault(); + !options.dropBubble && evt.stopPropagation(); + + ghostEl && ghostEl.parentNode.removeChild(ghostEl); + + if (dragEl) { + _off(dragEl, 'dragend', this); + + _disableDraggable(dragEl); + _toggleClass(dragEl, this.options.ghostClass, false); + + if (rootEl !== dragEl.parentNode) { + newIndex = _index(dragEl); + + // drag from one list and drop into another + _dispatchEvent(null, dragEl.parentNode, 'sort', dragEl, rootEl, oldIndex, newIndex); + _dispatchEvent(this, rootEl, 'sort', dragEl, rootEl, oldIndex, newIndex); + + // Add event + _dispatchEvent(null, dragEl.parentNode, 'add', dragEl, rootEl, oldIndex, newIndex); + + // Remove event + _dispatchEvent(this, rootEl, 'remove', dragEl, rootEl, oldIndex, newIndex); + } + else { + // Remove clone + cloneEl && cloneEl.parentNode.removeChild(cloneEl); + + if (dragEl.nextSibling !== nextEl) { + // Get the index of the dragged element within its parent + newIndex = _index(dragEl); + + // drag & drop within the same list + _dispatchEvent(this, rootEl, 'update', dragEl, rootEl, oldIndex, newIndex); + _dispatchEvent(this, rootEl, 'sort', dragEl, rootEl, oldIndex, newIndex); + } + } + + // Drag end event + Sortable.active && _dispatchEvent(this, rootEl, 'end', dragEl, rootEl, oldIndex, newIndex); + } + + // Nulling + rootEl = + dragEl = + ghostEl = + nextEl = + cloneEl = + + scrollEl = + scrollParentEl = + + tapEvt = + touchEvt = + + lastEl = + lastCSS = + + activeGroup = + Sortable.active = null; + + // Save sorting + this.save(); + } + }, + + + handleEvent: function (/**Event*/evt) { + var type = evt.type; + + if (type === 'dragover' || type === 'dragenter') { + if (dragEl) { + this._onDragOver(evt); + _globalDragOver(evt); + } + } + else if (type === 'drop' || type === 'dragend') { + this._onDrop(evt); + } + }, + + + /** + * Serializes the item into an array of string. + * @returns {String[]} + */ + toArray: function () { + var order = [], + el, + children = this.el.children, + i = 0, + n = children.length, + options = this.options; + + for (; i < n; i++) { + el = children[i]; + if (_closest(el, options.draggable, this.el)) { + order.push(el.getAttribute(options.dataIdAttr) || _generateId(el)); + } + } + + return order; + }, + + + /** + * Sorts the elements according to the array. + * @param {String[]} order order of the items + */ + sort: function (order) { + var items = {}, rootEl = this.el; + + this.toArray().forEach(function (id, i) { + var el = rootEl.children[i]; + + if (_closest(el, this.options.draggable, rootEl)) { + items[id] = el; + } + }, this); + + order.forEach(function (id) { + if (items[id]) { + rootEl.removeChild(items[id]); + rootEl.appendChild(items[id]); + } + }); + }, + + + /** + * Save the current sorting + */ + save: function () { + var store = this.options.store; + store && store.set(this); + }, + + + /** + * For each element in the set, get the first element that matches the selector by testing the element itself and traversing up through its ancestors in the DOM tree. + * @param {HTMLElement} el + * @param {String} [selector] default: `options.draggable` + * @returns {HTMLElement|null} + */ + closest: function (el, selector) { + return _closest(el, selector || this.options.draggable, this.el); + }, + + + /** + * Set/get option + * @param {string} name + * @param {*} [value] + * @returns {*} + */ + option: function (name, value) { + var options = this.options; + + if (value === void 0) { + return options[name]; + } else { + options[name] = value; + } + }, + + + /** + * Destroy + */ + destroy: function () { + var el = this.el; + + el[expando] = null; + + _off(el, 'mousedown', this._onTapStart); + _off(el, 'touchstart', this._onTapStart); + + _off(el, 'dragover', this); + _off(el, 'dragenter', this); + + // Remove draggable attributes + Array.prototype.forEach.call(el.querySelectorAll('[draggable]'), function (el) { + el.removeAttribute('draggable'); + }); + + touchDragOverListeners.splice(touchDragOverListeners.indexOf(this._onDragOver), 1); + + this._onDrop(); + + this.el = el = null; + } + }; + + + function _cloneHide(state) { + if (cloneEl && (cloneEl.state !== state)) { + _css(cloneEl, 'display', state ? 'none' : ''); + !state && cloneEl.state && rootEl.insertBefore(cloneEl, dragEl); + cloneEl.state = state; + } + } + + + function _bind(ctx, fn) { + var args = slice.call(arguments, 2); + return fn.bind ? fn.bind.apply(fn, [ctx].concat(args)) : function () { + return fn.apply(ctx, args.concat(slice.call(arguments))); + }; + } + + + function _closest(/**HTMLElement*/el, /**String*/selector, /**HTMLElement*/ctx) { + if (el) { + ctx = ctx || document; + selector = selector.split('.'); + + var tag = selector.shift().toUpperCase(), + re = new RegExp('\\s(' + selector.join('|') + ')\\s', 'g'); + + do { + if ( + (tag === '>*' && el.parentNode === ctx) || ( + (tag === '' || el.nodeName.toUpperCase() == tag) && + (!selector.length || ((' ' + el.className + ' ').match(re) || []).length == selector.length) + ) + ) { + return el; + } + } + while (el !== ctx && (el = el.parentNode)); + } + + return null; + } + + + function _globalDragOver(/**Event*/evt) { + evt.dataTransfer.dropEffect = 'move'; + evt.preventDefault(); + } + + + function _on(el, event, fn) { + el.addEventListener(event, fn, false); + } + + + function _off(el, event, fn) { + el.removeEventListener(event, fn, false); + } + + + function _toggleClass(el, name, state) { + if (el) { + if (el.classList) { + el.classList[state ? 'add' : 'remove'](name); + } + else { + var className = (' ' + el.className + ' ').replace(RSPACE, ' ').replace(' ' + name + ' ', ' '); + el.className = (className + (state ? ' ' + name : '')).replace(RSPACE, ' '); + } + } + } + + + function _css(el, prop, val) { + var style = el && el.style; + + if (style) { + if (val === void 0) { + if (document.defaultView && document.defaultView.getComputedStyle) { + val = document.defaultView.getComputedStyle(el, ''); + } + else if (el.currentStyle) { + val = el.currentStyle; + } + + return prop === void 0 ? val : val[prop]; + } + else { + if (!(prop in style)) { + prop = '-webkit-' + prop; + } + + style[prop] = val + (typeof val === 'string' ? '' : 'px'); + } + } + } + + + function _find(ctx, tagName, iterator) { + if (ctx) { + var list = ctx.getElementsByTagName(tagName), i = 0, n = list.length; + + if (iterator) { + for (; i < n; i++) { + iterator(list[i], i); + } + } + + return list; + } + + return []; + } + + + function _disableDraggable(el) { + el.draggable = false; + } + + + function _unsilent() { + _silent = false; + } + + + /** @returns {HTMLElement|false} */ + function _ghostInBottom(el, evt) { + var lastEl = el.lastElementChild, rect = lastEl.getBoundingClientRect(); + return (evt.clientY - (rect.top + rect.height) > 5) && lastEl; // min delta + } + + + /** + * Generate id + * @param {HTMLElement} el + * @returns {String} + * @private + */ + function _generateId(el) { + var str = el.tagName + el.className + el.src + el.href + el.textContent, + i = str.length, + sum = 0; + + while (i--) { + sum += str.charCodeAt(i); + } + + return sum.toString(36); + } + + /** + * Returns the index of an element within its parent + * @param el + * @returns {number} + * @private + */ + function _index(/**HTMLElement*/el) { + var index = 0; + while (el && (el = el.previousElementSibling)) { + if (el.nodeName.toUpperCase() !== 'TEMPLATE') { + index++; + } + } + return index; + } + + function _throttle(callback, ms) { + var args, _this; + + return function () { + if (args === void 0) { + args = arguments; + _this = this; + + setTimeout(function () { + if (args.length === 1) { + callback.call(_this, args[0]); + } else { + callback.apply(_this, args); + } + + args = void 0; + }, ms); + } + }; + } + + function _extend(dst, src) { + if (dst && src) { + for (var key in src) { + if (src.hasOwnProperty(key)) { + dst[key] = src[key]; + } + } + } + + return dst; + } + + + // Export utils + Sortable.utils = { + on: _on, + off: _off, + css: _css, + find: _find, + bind: _bind, + is: function (el, selector) { + return !!_closest(el, selector, el); + }, + extend: _extend, + throttle: _throttle, + closest: _closest, + toggleClass: _toggleClass, + index: _index + }; + + + Sortable.version = '1.2.0'; + + + /** + * Create sortable instance + * @param {HTMLElement} el + * @param {Object} [options] + */ + Sortable.create = function (el, options) { + return new Sortable(el, options); + }; + + // Export + return Sortable; +}); diff --git a/public/scripts/Sortable.min.js b/public/scripts/Sortable.min.js new file mode 100755 index 0000000..6b3c942 --- /dev/null +++ b/public/scripts/Sortable.min.js @@ -0,0 +1,2 @@ +/*! Sortable 1.2.0 - MIT | git://github.com/rubaxa/Sortable.git */ +!function(a){"use strict";"function"==typeof define&&define.amd?define(a):"undefined"!=typeof module&&"undefined"!=typeof module.exports?module.exports=a():"undefined"!=typeof Package?Sortable=a():window.Sortable=a()}(function(){"use strict";function a(a,b){this.el=a,this.options=b=q({},b),a[H]=this;var d={group:Math.random(),sort:!0,disabled:!1,store:null,handle:null,scroll:!0,scrollSensitivity:30,scrollSpeed:10,draggable:/[uo]l/i.test(a.nodeName)?"li":">*",ghostClass:"sortable-ghost",ignore:"a, img",filter:null,animation:0,setData:function(a,b){a.setData("Text",b.textContent)},dropBubble:!1,dragoverBubble:!1,dataIdAttr:"data-id",delay:0};for(var e in d)!(e in b)&&(b[e]=d[e]);var g=b.group;g&&"object"==typeof g||(g=b.group={name:g}),["pull","put"].forEach(function(a){a in g||(g[a]=!0)}),b.groups=" "+g.name+(g.put.join?" "+g.put.join(" "):"")+" ";for(var h in this)"_"===h.charAt(0)&&(this[h]=c(this,this[h]));f(a,"mousedown",this._onTapStart),f(a,"touchstart",this._onTapStart),f(a,"dragover",this),f(a,"dragenter",this),Q.push(this._onDragOver),b.store&&this.sort(b.store.get(this))}function b(a){t&&t.state!==a&&(i(t,"display",a?"none":""),!a&&t.state&&u.insertBefore(t,r),t.state=a)}function c(a,b){var c=P.call(arguments,2);return b.bind?b.bind.apply(b,[a].concat(c)):function(){return b.apply(a,c.concat(P.call(arguments)))}}function d(a,b,c){if(a){c=c||J,b=b.split(".");var d=b.shift().toUpperCase(),e=new RegExp("\\s("+b.join("|")+")\\s","g");do if(">*"===d&&a.parentNode===c||(""===d||a.nodeName.toUpperCase()==d)&&(!b.length||((" "+a.className+" ").match(e)||[]).length==b.length))return a;while(a!==c&&(a=a.parentNode))}return null}function e(a){a.dataTransfer.dropEffect="move",a.preventDefault()}function f(a,b,c){a.addEventListener(b,c,!1)}function g(a,b,c){a.removeEventListener(b,c,!1)}function h(a,b,c){if(a)if(a.classList)a.classList[c?"add":"remove"](b);else{var d=(" "+a.className+" ").replace(G," ").replace(" "+b+" "," ");a.className=(d+(c?" "+b:"")).replace(G," ")}}function i(a,b,c){var d=a&&a.style;if(d){if(void 0===c)return J.defaultView&&J.defaultView.getComputedStyle?c=J.defaultView.getComputedStyle(a,""):a.currentStyle&&(c=a.currentStyle),void 0===b?c:c[b];b in d||(b="-webkit-"+b),d[b]=c+("string"==typeof c?"":"px")}}function j(a,b,c){if(a){var d=a.getElementsByTagName(b),e=0,f=d.length;if(c)for(;f>e;e++)c(d[e],e);return d}return[]}function k(a){a.draggable=!1}function l(){M=!1}function m(a,b){var c=a.lastElementChild,d=c.getBoundingClientRect();return b.clientY-(d.top+d.height)>5&&c}function n(a){for(var b=a.tagName+a.className+a.src+a.href+a.textContent,c=b.length,d=0;c--;)d+=b.charCodeAt(c);return d.toString(36)}function o(a){for(var b=0;a&&(a=a.previousElementSibling);)"TEMPLATE"!==a.nodeName.toUpperCase()&&b++;return b}function p(a,b){var c,d;return function(){void 0===c&&(c=arguments,d=this,setTimeout(function(){1===c.length?a.call(d,c[0]):a.apply(d,c),c=void 0},b))}}function q(a,b){if(a&&b)for(var c in b)b.hasOwnProperty(c)&&(a[c]=b[c]);return a}var r,s,t,u,v,w,x,y,z,A,B,C,D,E,F={},G=/\s+/g,H="Sortable"+(new Date).getTime(),I=window,J=I.document,K=I.parseInt,L=!!("draggable"in J.createElement("div")),M=!1,N=function(a,b,c,d,e,f,g){var h=J.createEvent("Event"),i=(a||b[H]).options,j="on"+c.charAt(0).toUpperCase()+c.substr(1);h.initEvent(c,!0,!0),h.item=d||b,h.from=e||b,h.clone=t,h.oldIndex=f,h.newIndex=g,i[j]&&i[j].call(a,h),b.dispatchEvent(h)},O=Math.abs,P=[].slice,Q=[],R=p(function(a,b,c){if(c&&b.scroll){var d,e,f,g,h=b.scrollSensitivity,i=b.scrollSpeed,j=a.clientX,k=a.clientY,l=window.innerWidth,m=window.innerHeight;if(x!==c&&(w=b.scroll,x=c,w===!0)){w=c;do if(w.offsetWidth=l-j)-(h>=j),g=(h>=m-k)-(h>=k),(f||g)&&(d=I)),(F.vx!==f||F.vy!==g||F.el!==d)&&(F.el=d,F.vx=f,F.vy=g,clearInterval(F.pid),d&&(F.pid=setInterval(function(){d===I?I.scrollTo(I.pageXOffset+f*i,I.pageYOffset+g*i):(g&&(d.scrollTop+=g*i),f&&(d.scrollLeft+=f*i))},24)))}},30);return a.prototype={constructor:a,_onTapStart:function(a){var b=this,c=this.el,e=this.options,f=a.type,g=a.touches&&a.touches[0],h=(g||a).target,i=h,j=e.filter;if(!("mousedown"===f&&0!==a.button||e.disabled)&&(h=d(h,e.draggable,c))){if(A=o(h),"function"==typeof j){if(j.call(this,a,h,this))return N(b,i,"filter",h,c,A),void a.preventDefault()}else if(j&&(j=j.split(",").some(function(a){return a=d(i,a.trim(),c),a?(N(b,a,"filter",h,c,A),!0):void 0})))return void a.preventDefault();(!e.handle||d(i,e.handle,c))&&this._prepareDragStart(a,g,h)}},_prepareDragStart:function(a,b,c){var d,e=this,g=e.el,h=e.options,i=g.ownerDocument;c&&!r&&c.parentNode===g&&(D=a,u=g,r=c,v=r.nextSibling,C=h.group,d=function(){e._disableDelayedDrag(),r.draggable=!0,h.ignore.split(",").forEach(function(a){j(r,a.trim(),k)}),e._triggerDragStart(b)},f(i,"mouseup",e._onDrop),f(i,"touchend",e._onDrop),f(i,"touchcancel",e._onDrop),h.delay?(f(i,"mousemove",e._disableDelayedDrag),f(i,"touchmove",e._disableDelayedDrag),e._dragStartTimer=setTimeout(d,h.delay)):d())},_disableDelayedDrag:function(){var a=this.el.ownerDocument;clearTimeout(this._dragStartTimer),g(a,"mousemove",this._disableDelayedDrag),g(a,"touchmove",this._disableDelayedDrag)},_triggerDragStart:function(a){a?(D={target:r,clientX:a.clientX,clientY:a.clientY},this._onDragStart(D,"touch")):L?(f(r,"dragend",this),f(u,"dragstart",this._onDragStart)):this._onDragStart(D,!0);try{J.selection?J.selection.empty():window.getSelection().removeAllRanges()}catch(b){}},_dragStarted:function(){u&&r&&(h(r,this.options.ghostClass,!0),a.active=this,N(this,u,"start",r,u,A))},_emulateDragOver:function(){if(E){i(s,"display","none");var a=J.elementFromPoint(E.clientX,E.clientY),b=a,c=" "+this.options.group.name,d=Q.length;if(b)do{if(b[H]&&b[H].options.groups.indexOf(c)>-1){for(;d--;)Q[d]({clientX:E.clientX,clientY:E.clientY,target:a,rootEl:b});break}a=b}while(b=b.parentNode);i(s,"display","")}},_onTouchMove:function(a){if(D){var b=a.touches?a.touches[0]:a,c=b.clientX-D.clientX,d=b.clientY-D.clientY,e=a.touches?"translate3d("+c+"px,"+d+"px,0)":"translate("+c+"px,"+d+"px)";E=b,i(s,"webkitTransform",e),i(s,"mozTransform",e),i(s,"msTransform",e),i(s,"transform",e),a.preventDefault()}},_onDragStart:function(a,b){var c=a.dataTransfer,d=this.options;if(this._offUpEvents(),"clone"==C.pull&&(t=r.cloneNode(!0),i(t,"display","none"),u.insertBefore(t,r)),b){var e,g=r.getBoundingClientRect(),h=i(r);s=r.cloneNode(!0),i(s,"top",g.top-K(h.marginTop,10)),i(s,"left",g.left-K(h.marginLeft,10)),i(s,"width",g.width),i(s,"height",g.height),i(s,"opacity","0.8"),i(s,"position","fixed"),i(s,"zIndex","100000"),u.appendChild(s),e=s.getBoundingClientRect(),i(s,"width",2*g.width-e.width),i(s,"height",2*g.height-e.height),"touch"===b?(f(J,"touchmove",this._onTouchMove),f(J,"touchend",this._onDrop),f(J,"touchcancel",this._onDrop)):(f(J,"mousemove",this._onTouchMove),f(J,"mouseup",this._onDrop)),this._loopId=setInterval(this._emulateDragOver,150)}else c&&(c.effectAllowed="move",d.setData&&d.setData.call(this,c,r)),f(J,"drop",this);setTimeout(this._dragStarted,0)},_onDragOver:function(a){var c,e,f,g=this.el,h=this.options,j=h.group,k=j.put,n=C===j,o=h.sort;if(void 0!==a.preventDefault&&(a.preventDefault(),!h.dragoverBubble&&a.stopPropagation()),C&&!h.disabled&&(n?o||(f=!u.contains(r)):C.pull&&k&&(C.name===j.name||k.indexOf&&~k.indexOf(C.name)))&&(void 0===a.rootEl||a.rootEl===this.el)){if(R(a,h,this.el),M)return;if(c=d(a.target,h.draggable,g),e=r.getBoundingClientRect(),f)return b(!0),void(t||v?u.insertBefore(r,t||v):o||u.appendChild(r));if(0===g.children.length||g.children[0]===s||g===a.target&&(c=m(g,a))){if(c){if(c.animated)return;q=c.getBoundingClientRect()}b(n),g.appendChild(r),this._animate(e,r),c&&this._animate(q,c)}else if(c&&!c.animated&&c!==r&&void 0!==c.parentNode[H]){y!==c&&(y=c,z=i(c));var p,q=c.getBoundingClientRect(),w=q.right-q.left,x=q.bottom-q.top,A=/left|right|inline/.test(z.cssFloat+z.display),B=c.offsetWidth>r.offsetWidth,D=c.offsetHeight>r.offsetHeight,E=(A?(a.clientX-q.left)/w:(a.clientY-q.top)/x)>.5,F=c.nextElementSibling;M=!0,setTimeout(l,30),b(n),p=A?c.previousElementSibling===r&&!B||E&&B:F!==r&&!D||E&&D,p&&!F?g.appendChild(r):c.parentNode.insertBefore(r,p?F:c),this._animate(e,r),this._animate(q,c)}}},_animate:function(a,b){var c=this.options.animation;if(c){var d=b.getBoundingClientRect();i(b,"transition","none"),i(b,"transform","translate3d("+(a.left-d.left)+"px,"+(a.top-d.top)+"px,0)"),b.offsetWidth,i(b,"transition","all "+c+"ms"),i(b,"transform","translate3d(0,0,0)"),clearTimeout(b.animated),b.animated=setTimeout(function(){i(b,"transition",""),i(b,"transform",""),b.animated=!1},c)}},_offUpEvents:function(){var a=this.el.ownerDocument;g(J,"touchmove",this._onTouchMove),g(a,"mouseup",this._onDrop),g(a,"touchend",this._onDrop),g(a,"touchcancel",this._onDrop)},_onDrop:function(b){var c=this.el,d=this.options;clearInterval(this._loopId),clearInterval(F.pid),clearTimeout(this.dragStartTimer),g(J,"drop",this),g(J,"mousemove",this._onTouchMove),g(c,"dragstart",this._onDragStart),this._offUpEvents(),b&&(b.preventDefault(),!d.dropBubble&&b.stopPropagation(),s&&s.parentNode.removeChild(s),r&&(g(r,"dragend",this),k(r),h(r,this.options.ghostClass,!1),u!==r.parentNode?(B=o(r),N(null,r.parentNode,"sort",r,u,A,B),N(this,u,"sort",r,u,A,B),N(null,r.parentNode,"add",r,u,A,B),N(this,u,"remove",r,u,A,B)):(t&&t.parentNode.removeChild(t),r.nextSibling!==v&&(B=o(r),N(this,u,"update",r,u,A,B),N(this,u,"sort",r,u,A,B))),a.active&&N(this,u,"end",r,u,A,B)),u=r=s=v=t=w=x=D=E=y=z=C=a.active=null,this.save())},handleEvent:function(a){var b=a.type;"dragover"===b||"dragenter"===b?r&&(this._onDragOver(a),e(a)):("drop"===b||"dragend"===b)&&this._onDrop(a)},toArray:function(){for(var a,b=[],c=this.el.children,e=0,f=c.length,g=this.options;f>e;e++)a=c[e],d(a,g.draggable,this.el)&&b.push(a.getAttribute(g.dataIdAttr)||n(a));return b},sort:function(a){var b={},c=this.el;this.toArray().forEach(function(a,e){var f=c.children[e];d(f,this.options.draggable,c)&&(b[a]=f)},this),a.forEach(function(a){b[a]&&(c.removeChild(b[a]),c.appendChild(b[a]))})},save:function(){var a=this.options.store;a&&a.set(this)},closest:function(a,b){return d(a,b||this.options.draggable,this.el)},option:function(a,b){var c=this.options;return void 0===b?c[a]:void(c[a]=b)},destroy:function(){var a=this.el;a[H]=null,g(a,"mousedown",this._onTapStart),g(a,"touchstart",this._onTapStart),g(a,"dragover",this),g(a,"dragenter",this),Array.prototype.forEach.call(a.querySelectorAll("[draggable]"),function(a){a.removeAttribute("draggable")}),Q.splice(Q.indexOf(this._onDragOver),1),this._onDrop(),this.el=a=null}},a.utils={on:f,off:g,css:i,find:j,bind:c,is:function(a,b){return!!d(a,b,a)},extend:q,throttle:p,closest:d,toggleClass:h,index:o},a.version="1.2.0",a.create=function(b,c){return new a(b,c)},a}); \ No newline at end of file From dbc223442f3943552c244b3afff4b679b1dce90e Mon Sep 17 00:00:00 2001 From: KKrenz Date: Tue, 21 Apr 2015 12:14:14 +0200 Subject: [PATCH 15/22] =?UTF-8?q?Balken=20in=20result=20table=20f=C3=BCr?= =?UTF-8?q?=20order-=20und=20match-questions=20wachsen=20nun=20von=20unten?= =?UTF-8?q?=20nach=20oben;=20re-do=20create-interface=20of=20order=20quest?= =?UTF-8?q?ions;=20start=20to=20build=20relative=20result=20table=20and=20?= =?UTF-8?q?its=20database=20representation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/assets/stylesheets/questions.css.less | 15 +++++ app/assets/stylesheets/surveys.css.less | 10 +--- app/models/order_option.rb | 7 ++- app/models/relative_option_order_object.rb | 49 +++++++++++++++ app/views/questions/_order_form.html.erb | 60 ++++++++++++++++--- ...rder_question_order_option_fields.html.erb | 15 ++--- .../_answer_pair_result_table.html.erb | 4 +- ...er_option_absolute_results_table.html.erb} | 4 +- ...der_option_relative_results_table.html.erb | 46 ++++++++++++++ app/views/surveys/_show.html.erb | 5 +- config/locales/defaults/de.yml | 2 +- config/locales/defaults/en.yml | 2 +- 12 files changed, 185 insertions(+), 34 deletions(-) create mode 100644 app/models/relative_option_order_object.rb rename app/views/surveys/{_order_option_result_table.html.erb => _order_option_absolute_results_table.html.erb} (94%) create mode 100644 app/views/surveys/_order_option_relative_results_table.html.erb diff --git a/app/assets/stylesheets/questions.css.less b/app/assets/stylesheets/questions.css.less index cee4043..134ef5c 100755 --- a/app/assets/stylesheets/questions.css.less +++ b/app/assets/stylesheets/questions.css.less @@ -24,3 +24,18 @@ input[type="checkbox"].questions-table__checkbox { .import-info, #compatibility { display: none; } + +.move_handler { + cursor: move; +} + +.ghost { + opacity: .5; + background: #FECA40; +} + +.create_order_option_list { + list-style-type: none; + margin: 0; + padding: 0; +} \ No newline at end of file diff --git a/app/assets/stylesheets/surveys.css.less b/app/assets/stylesheets/surveys.css.less index 413b914..4a3982c 100755 --- a/app/assets/stylesheets/surveys.css.less +++ b/app/assets/stylesheets/surveys.css.less @@ -86,12 +86,6 @@ border-radius: 5px; word-wrap: break-word; } - - .handle { - float: left; - margin-right: 10px; - cursor: move; - } } .leftOptions { @@ -305,10 +299,10 @@ div { position: absolute; left: 0px; - top: 0px; + bottom: 0px; z-index:-1; background-color: #DAEDF7; - height: 100%; + width: 100%; } p { diff --git a/app/models/order_option.rb b/app/models/order_option.rb index f534e7b..b67a6d0 100644 --- a/app/models/order_option.rb +++ b/app/models/order_option.rb @@ -11,9 +11,10 @@ class OrderOption # But since there's is no Mongoid field type "IntegerArray", we do it via a String, # e.g. "5,8,0,0,5,3" - validates_presence_of :name - validates_presence_of :position - validates_format_of :name, :without => / - / + # TODO: Why are the messages not working? + validates_presence_of :name, message: ": Name of option can't be blank." + validates_presence_of :position, message: ": Positions of options are missing." + validates_format_of :name, :without => / - /, message: ": No ' - ' inside option names." def vote_up(position) votesArray = self.votes.split(",") diff --git a/app/models/relative_option_order_object.rb b/app/models/relative_option_order_object.rb new file mode 100644 index 0000000..acc289d --- /dev/null +++ b/app/models/relative_option_order_object.rb @@ -0,0 +1,49 @@ +class RelativeOptionOrderObject + include Mongoid::Document + + embedded_in :question + embedded_in :survey + + # Every order_option is a key in this hash. + # Its value is another hash, in which all + # the other order_options are a key, and + # behind each key you find the number of + # votes, indicating that this order_option + # belongs after the super order_option. E.g. + # + # contentHash: + # { + # "A" => { + # "B" => 2, //i.e. 2 people voted, that A belongs before B + # "C" => 4 //i.e. 4 people voted, that A belongs before B + # }, + # "B" => { + # "A" => 2, + # "C" => 3 + # }, + # "C" => { + # "A" => 0, + # "B" => 1 + # } + # } + field :contentHash, type: Hash + + def vote_up(beforeName, afterName) + if self.contentHash[beforeName].nil? + self.contentHash[beforeName] = Hash[afterName, 1] + elsif self.contentHash[beforeName][afterName].nil? + self.contentHash[beforeName][afterName] = 1 + else + self.contentHash[beforeName][afterName] += 1 + end + end + + def get_votes_for(beforeName, afterName) + if self.contentHash[beforeName][afterName].nil? + return(0) + else + return(self.contentHash[beforeName][afterName]) + end + end + +end \ No newline at end of file diff --git a/app/views/questions/_order_form.html.erb b/app/views/questions/_order_form.html.erb index 3b3321b..531cc5c 100644 --- a/app/views/questions/_order_form.html.erb +++ b/app/views/questions/_order_form.html.erb @@ -21,15 +21,17 @@

    <%= t("surveys.edit.order_options_for_order_survey") %>

    - <%= form.semantic_fields_for :order_options, class: "form-inline" do |option| %> - <%= render "order_question_order_option_fields", f: option %> - <% end %> - +
      + <%= form.semantic_fields_for :order_options, class: "form-inline" do |option| %> + <%= render "order_question_order_option_fields", f: option %> + <% end %> + +

    -
    +
    <%= form.hidden_field :collaborators_form, class:"collaborators-form" %> <%= form.submit class: "btn btn-primary", id: "single_question_submit" %> @@ -55,4 +57,48 @@ }); }); + + + + <% end %> \ No newline at end of file diff --git a/app/views/questions/_order_question_order_option_fields.html.erb b/app/views/questions/_order_question_order_option_fields.html.erb index dc10526..0399c46 100644 --- a/app/views/questions/_order_question_order_option_fields.html.erb +++ b/app/views/questions/_order_question_order_option_fields.html.erb @@ -1,7 +1,8 @@ -
    -
    - <%= link_to_remove_association icon_tag("minus-sign"), f %> - <%= f.text_field :name, placeholder: t("name") %> - <%= f.number_field :position, placeholder: t("position") %> -
    -
    +
  • +
    +
    + <%= link_to_remove_association icon_tag("minus-sign"), f %> + <%= f.text_field :name, placeholder: t("name"), class: "name_field_for_order_option" %> +
    +
    +
  • diff --git a/app/views/surveys/_answer_pair_result_table.html.erb b/app/views/surveys/_answer_pair_result_table.html.erb index 9aa08e8..29945bd 100755 --- a/app/views/surveys/_answer_pair_result_table.html.erb +++ b/app/views/surveys/_answer_pair_result_table.html.erb @@ -24,14 +24,14 @@ <% if current_answer_pair.correct? %>
    -
    +

    <%= percentage %>

    <% else %>
    -
    +

    <%= percentage %>

    diff --git a/app/views/surveys/_order_option_result_table.html.erb b/app/views/surveys/_order_option_absolute_results_table.html.erb similarity index 94% rename from app/views/surveys/_order_option_result_table.html.erb rename to app/views/surveys/_order_option_absolute_results_table.html.erb index df925c2..b12cb74 100644 --- a/app/views/surveys/_order_option_result_table.html.erb +++ b/app/views/surveys/_order_option_absolute_results_table.html.erb @@ -25,14 +25,14 @@ <% if option.position == currentPosition %>
    -
    +

    <%= percentage %>

    <% else %>
    -
    +

    <%= percentage %>

    diff --git a/app/views/surveys/_order_option_relative_results_table.html.erb b/app/views/surveys/_order_option_relative_results_table.html.erb new file mode 100644 index 0000000..b12cb74 --- /dev/null +++ b/app/views/surveys/_order_option_relative_results_table.html.erb @@ -0,0 +1,46 @@ + + + + + <% numberOfOptions = survey.order_options.length %> + <% columnWidthPercentage = number_to_percentage(1.to_f / (1 + numberOfOptions).to_f * 100.to_f, :precision => 0) %> + + <% for index in 1..numberOfOptions %> + + <% end %> + + + + <% survey.order_options.shuffle! %> + <% survey.order_options.each do |option| %> + + <% currentPosition = 1 %> + <% option.votes.split(",").each do |votesForPosition| %> + <% votesForPositionInteger = Integer(votesForPosition) %> + <% percentage = "0%" %> + <% if survey.total_votes > 0 %> + <% percentage = number_to_percentage(votesForPositionInteger.to_f / total_votes.to_f * 100.to_f, :precision => 0) %> + <% end %> + <% rowHeightPercentage = number_to_percentage(1.to_f / (1 + survey.order_options.length).to_f * 100.to_f, :precision => 0) %> + <% if option.position == currentPosition %> + + <% else %> + + <% end %> + <% currentPosition += 1 %> + <% end %> + + <% end %> + +
    Position<%= index %>
    <%= option.name %> +
    +
    +

    <%= percentage %>

    +
    +
    +
    +
    +

    <%= percentage %>

    +
    +
    + \ No newline at end of file diff --git a/app/views/surveys/_show.html.erb b/app/views/surveys/_show.html.erb index 8f30b7a..337be73 100755 --- a/app/views/surveys/_show.html.erb +++ b/app/views/surveys/_show.html.erb @@ -107,16 +107,15 @@

    <%= t("absolute_results") %>

    - <%= render partial: "order_option_result_table", locals: {survey: survey} %> + <%= render partial: "order_option_absolute_results_table", locals: {survey: survey} %> <%= icon_tag("download-alt") %> <%= t("surveys.show.mark_corrects") %>

    <%= t("relative_results") %>

    - <%= render partial: "order_option_result_table", locals: {survey: survey} %> + <%= render partial: "order_option_relative_results_table", locals: {survey: survey} %> <%= icon_tag("download-alt") %> - <%= t("surveys.show.mark_corrects") %>
    diff --git a/config/locales/defaults/de.yml b/config/locales/defaults/de.yml index 58ec397..066ae28 100755 --- a/config/locales/defaults/de.yml +++ b/config/locales/defaults/de.yml @@ -24,7 +24,7 @@ de: remove: "Entfernen" start: "Starten" name: "Name" - position: "Position (1,2,3, ...)" + position: "Position" description: "Beschreibung" there_were_errors_saving: "Beim Speichern sind Fehler aufgetreten" forgot_password: "Passwort vergessen?" diff --git a/config/locales/defaults/en.yml b/config/locales/defaults/en.yml index e982f14..5b3beee 100755 --- a/config/locales/defaults/en.yml +++ b/config/locales/defaults/en.yml @@ -25,7 +25,7 @@ en: start: "Start" there_were_errors_saving: "Errors occured during saving" name: "Name" - position: "Position (1,2,3, ...)" + position: "Position" description: "Description" forgot_password: "Forgot your password?" remember_me: "Remember me" From 165bb915e8ddce26b2f7f71772c27ff5e551ad7c Mon Sep 17 00:00:00 2001 From: KKrenz Date: Sat, 25 Apr 2015 16:46:22 +0200 Subject: [PATCH 16/22] =?UTF-8?q?Fertigstellung=20von=20Ergebnisdarstellun?= =?UTF-8?q?g=20von=20order=5Fsurveys;=20alle=20parser=20in=20hinsicht=20au?= =?UTF-8?q?f=20order=5Fquestions=20=C3=BCberarbeitet=20bis=20auf=20qti-par?= =?UTF-8?q?ser?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/assets/stylesheets/surveys.css.less | 3 +- app/controllers/questions_controller.rb | 8 +- app/controllers/surveys_controller.rb | 27 ++++++- app/models/order_option.rb | 18 ++++- app/models/question.rb | 5 ++ app/models/relative_option_order_object.rb | 19 ++--- app/models/survey.rb | 12 ++- app/parsers/aiken_parser.rb | 8 ++ app/parsers/csv_parser.rb | 18 ++--- app/parsers/gift_txt_parser.rb | 4 + app/parsers/moodle_xml_parser.rb | 6 ++ app/services/order_survey.rb | 17 ++++- .../_answer_pair_result_table.html.erb | 2 +- app/views/surveys/_order_list.html.erb | 25 +------ ...der_option_absolute_results_table.html.erb | 8 +- ...der_option_relative_results_table.html.erb | 74 ++++++++++--------- app/views/surveys/_show.html.erb | 15 +++- app/views/surveys/participate.html.erb | 25 ++++++- config/locales/defaults/de.yml | 1 + config/locales/defaults/en.yml | 1 + log.txt | 2 + 21 files changed, 201 insertions(+), 97 deletions(-) diff --git a/app/assets/stylesheets/surveys.css.less b/app/assets/stylesheets/surveys.css.less index 4a3982c..09a300d 100755 --- a/app/assets/stylesheets/surveys.css.less +++ b/app/assets/stylesheets/surveys.css.less @@ -268,7 +268,7 @@ RESULT TABLE ======================================== */ -#result-table { +.result-table { table-layout:fixed; div { @@ -283,7 +283,6 @@ } } - .result-table-td { text-align: center; word-wrap: break-word; diff --git a/app/controllers/questions_controller.rb b/app/controllers/questions_controller.rb index d0e71a2..783ee4b 100755 --- a/app/controllers/questions_controller.rb +++ b/app/controllers/questions_controller.rb @@ -160,6 +160,7 @@ def create @question.order_options.each do |option| option.votes = votesString end + @question.relative_option_order_object = Hash.new end # shitty work-around: Don't know why, but the first answer_pair doesn't seem to get into @@ -326,7 +327,12 @@ def check_access end def question_params - params.require(:question).permit(:name, :type, :description, :tags, :public, :collaborators_form, question_options_attributes: [:name, :correct, :id, :_destroy], answer_pairs_attributes: [:answer1, :answer2, :correct, :id, :_destroy], order_options_attributes: [:name, :position, :id, :_destroy]) + params.require(:question).permit(:name, :type, :description, :tags, + :public, :collaborators_form, + question_options_attributes: [:name, :correct, :id, :_destroy], + answer_pairs_attributes: [:answer1, :answer2, :correct, :id, :_destroy], + order_options_attributes: [:name, :position, :id, :_destroy], + relative_option_order_object_attributes: [:content_hash, :id, :_destroy]) end end diff --git a/app/controllers/surveys_controller.rb b/app/controllers/surveys_controller.rb index 99f4e69..9361bc8 100755 --- a/app/controllers/surveys_controller.rb +++ b/app/controllers/surveys_controller.rb @@ -205,6 +205,9 @@ def repeat original_survey.answer_pairs.map do |pair| @survey.answer_pairs.new(answer1: pair.answer1, answer2: pair.answer2, correct: pair.correct) end + original_survey.order_options.map do |option| + @survey.order_options.new(name: option.name, position: option.position) + end @survey.type = original_survey.type @survey.settings = original_survey.settings @survey.original_survey = original_survey @@ -256,6 +259,14 @@ def vote voted_for = t("matrix_keys.no_answer") end end + elsif @survey.has_order_options? + if @survey.type == "order" + unless params[:option].nil? + voted_for = '
      '+params[:option].map { |o| '
    • '+o.split(" - ")[1]+') '+ o.split(" - ")[0] +'
    • '}.join + '
    ' + else + voted_for = t("matrix_keys.no_answer") + end + end else if params[:option].respond_to? :each voted_for = "
    - " + params[:option].reject {|o| o.blank? }.join("
    - ") + "
    " @@ -400,7 +411,9 @@ def exit_question end def changed - @survey = Survey.only(:original_survey_id, :type, :options, :answer_pairs, :voters_hash, :event_id).find(params[:id]).service + @survey = Survey.only(:original_survey_id, :type, :options, :answer_pairs, + :order_options, :relative_option_order_object, :voters_hash, + :event_id).find(params[:id]).service check_access return if performed? @@ -437,7 +450,9 @@ def changed end def changed_aggregated - @survey = Survey.only(:original_survey_id, :type, :options, :answer_pairs, :voters_hash, :event_id).find(params[:id]).service + @survey = Survey.only(:original_survey_id, :type, :options, :answer_pairs, + :order_options, :relative_option_order_object, :voters_hash, + :event_id).find(params[:id]).service check_access return if performed? @@ -464,7 +479,7 @@ def changed_aggregated end def results - @survey = Survey.only(:type, :options, :answer_pairs, :voters_hash, :event_id, :voters).find(params[:id]).service + @survey = Survey.only(:type, :options, :answer_pairs, :order_options, :relative_option_order_object, :voters_hash, :event_id, :voters).find(params[:id]).service check_access return if performed? @@ -504,7 +519,11 @@ def api protected def survey_params - params.require(:survey).permit(:name, :description, options_attributes: [:name, :correct, :id], answer_pairs_attributes: [:answer1, :answer2, :correct, :id]) + params.require(:survey).permit(:name, :description, + options_attributes: [:name, :correct, :id], + answer_pairs_attributes: [:answer1, :answer2, :correct, :id], + order_options_attributes: [:name, :position, :id, :_destroy], + relative_option_order_object_attributes: [:content_hash, :id, :_destroy]) end def check_access diff --git a/app/models/order_option.rb b/app/models/order_option.rb index b67a6d0..3ab2d02 100644 --- a/app/models/order_option.rb +++ b/app/models/order_option.rb @@ -18,12 +18,24 @@ class OrderOption def vote_up(position) votesArray = self.votes.split(",") - votesArray[position] = (Integer(votesArray[position]) + 1).to_s + votesArray[position-1] = Integer(votesArray[position-1]) + 1 + self.votes = votesArray.to_s + self.votes.gsub! '"', '' + self.votes.gsub! '[', '' + self.votes.gsub! ']', '' + self.votes.gsub! ' ', '' + self.save! end - def vote_down + def vote_down(position) votesArray = self.votes.split(",") - votesArray[position] = (Integer(votesArray[position]) - 1).to_s + votesArray[position-1] = Integer(votesArray[position-1]) - 1 + self.votes = votesArray.to_s + self.votes.gsub! '"', '' + self.votes.gsub! '[', '' + self.votes.gsub! ']', '' + self.votes.gsub! ' ', '' + self.save! end end \ No newline at end of file diff --git a/app/models/question.rb b/app/models/question.rb index 957ab31..f089811 100755 --- a/app/models/question.rb +++ b/app/models/question.rb @@ -29,6 +29,9 @@ def self.question_types embeds_many :order_options accepts_nested_attributes_for :order_options, allow_destroy: true + embeds_one :relative_option_order_object + accepts_nested_attributes_for :relative_option_order_object, allow_destroy: true + belongs_to :user # TODO can questions exist without user? belongs_to :original_question, class_name: "Question", inverse_of: :copied_questions has_many :copied_questions, class_name: "Question", inverse_of: :original_question @@ -76,6 +79,7 @@ def to_survey order_options.each do |oo| survey.order_options.push oo end + survey.relative_option_order_object = self.relative_option_order_object survey.question = self survey.settings = self.settings if self.settings survey @@ -100,6 +104,7 @@ def self.new_from_existing(original_question) original_question.order_options.each do |option| question.order_options.build(name: option.name, position: option.position) end + question.relative_option_order_object = original_question.relative_option_order_object question.type = original_question.type question.original_question = original_question question.description = original_question.description diff --git a/app/models/relative_option_order_object.rb b/app/models/relative_option_order_object.rb index acc289d..b782f68 100644 --- a/app/models/relative_option_order_object.rb +++ b/app/models/relative_option_order_object.rb @@ -11,7 +11,7 @@ class RelativeOptionOrderObject # votes, indicating that this order_option # belongs after the super order_option. E.g. # - # contentHash: + # content_hash: # { # "A" => { # "B" => 2, //i.e. 2 people voted, that A belongs before B @@ -26,23 +26,24 @@ class RelativeOptionOrderObject # "B" => 1 # } # } - field :contentHash, type: Hash + field :content_hash, type: Hash, default: Hash.new def vote_up(beforeName, afterName) - if self.contentHash[beforeName].nil? - self.contentHash[beforeName] = Hash[afterName, 1] - elsif self.contentHash[beforeName][afterName].nil? - self.contentHash[beforeName][afterName] = 1 + if self.content_hash[beforeName].nil? + self.content_hash[beforeName] = Hash[afterName, 1] + elsif self.content_hash[beforeName][afterName].nil? + self.content_hash[beforeName][afterName] = 1 else - self.contentHash[beforeName][afterName] += 1 + self.content_hash[beforeName][afterName] += 1 end + self.save! end def get_votes_for(beforeName, afterName) - if self.contentHash[beforeName][afterName].nil? + if self.content_hash[beforeName].nil? || self.content_hash[beforeName][afterName].nil? return(0) else - return(self.contentHash[beforeName][afterName]) + return(self.content_hash[beforeName][afterName]) end end diff --git a/app/models/survey.rb b/app/models/survey.rb index c234578..3583772 100755 --- a/app/models/survey.rb +++ b/app/models/survey.rb @@ -18,6 +18,9 @@ class Survey embeds_many :order_options accepts_nested_attributes_for :order_options, :allow_destroy => true + + embeds_one :relative_option_order_object + accepts_nested_attributes_for :relative_option_order_object, :allow_destroy => true field :name, type: String field :description, type: String @@ -42,8 +45,13 @@ class Survey belongs_to :question scope :current, where(:starts.gte => DateTime.now).and(:ends.lt => DateTime.now) - scope :display_fields, only(:description, :ends, :name, :options, :answer_pairs, :order_options, :starts, :event_id, :quick, :created_at, :multi, :type, :settings, :voters, :voters_hash, :original_survey_id, :exit_q, :question_id) - scope :participate_fields, only(:description, :ends, :name, :options, :answer_pairs, :order_options, :starts, :event_id, :quick, :multi, :type, :exit_q, :settings) + scope :display_fields, only(:description, :ends, :name, :options, :answer_pairs, + :order_options, :relative_option_order_object, :starts, :event_id, :quick, + :created_at, :multi, :type, :settings, :voters, :voters_hash, :original_survey_id, + :exit_q, :question_id) + scope :participate_fields, only(:description, :ends, :name, :options, :answer_pairs, + :order_options, :relative_option_order_object, :starts, :event_id, :quick, :multi, + :type, :exit_q, :settings) scope :worker_fields, only(:voters, :multi, :type, :starts, :ends) validates :event, presence: true diff --git a/app/parsers/aiken_parser.rb b/app/parsers/aiken_parser.rb index f53a1d6..208839f 100755 --- a/app/parsers/aiken_parser.rb +++ b/app/parsers/aiken_parser.rb @@ -1,9 +1,17 @@ class AikenParser def export(questions) + result = "" # Über alle Fragen iterieren questions.each_with_index do |question, index| + # aiken doesn't support matching nor order questions, so skip them + if question.has_answer_pairs? + next + elsif question.has_order_options? + next + end + result << question.name + "\r\n" option_index = "A" diff --git a/app/parsers/csv_parser.rb b/app/parsers/csv_parser.rb index cedb306..be2d96d 100755 --- a/app/parsers/csv_parser.rb +++ b/app/parsers/csv_parser.rb @@ -25,8 +25,10 @@ def export(questions) elsif question.type == 'match' question.answer_pairs.where(correct: true).each do |pair| current << pair.answer1 + ' - ' + pair.answer2 - correct_options << option_number if pair.correct? - option_number = option_number + 1 + end + elsif question.type == 'order' + question.order_options.each do |option| + current << option.position.to_s + ") " + option.name end end unless correct_options.empty? @@ -71,7 +73,11 @@ def import(csv_file, user, tags, separator = ",") if question[0] == "match" question.drop(3).each do |pair| # Die ersten drei Elemente beinhalten keine Antworten - q.answer_pairs << AnswerPair.new(answer1: pair.split(' - ')[0], answer2: pair.split(' - ')[1], correct: false) # AnswerPairs sind in der Frage eingebettet und werden mitgesichert + q.answer_pairs << AnswerPair.new(answer1: pair.split(' - ')[0], answer2: pair.split(' - ')[1]) + end + elsif question[0] == "order" + question.drop(3).each do |option| + q.order_options << OrderOption.new(name: option.split(') ')[1], position: option.split(') ')[0]) end else question.drop(3).each do |option| # Die ersten drei Elemente beinhalten keine Antworten @@ -90,12 +96,6 @@ def import(csv_file, user, tags, separator = ",") elsif answers.first.blank? q.add_setting "answers", TextSurvey::MULTI_ANSWERS end - elsif q.type == "match" - if answers - answers.each do |answer| - q.answer_pairs[answer.to_i-1].correct = true - end - end else if answers answers.each do |answer| diff --git a/app/parsers/gift_txt_parser.rb b/app/parsers/gift_txt_parser.rb index 071ddcd..0376f43 100755 --- a/app/parsers/gift_txt_parser.rb +++ b/app/parsers/gift_txt_parser.rb @@ -6,6 +6,10 @@ class GiftTxtParser def export(questions) txt_content = "" questions.each do |question| + if question.has_order_options? + # the gift format doesn't support order-questions, so skip them + next + end txt_content << question.name if(question.has_options?) txt_content << "{\r\n" diff --git a/app/parsers/moodle_xml_parser.rb b/app/parsers/moodle_xml_parser.rb index e65d790..d9ca55a 100755 --- a/app/parsers/moodle_xml_parser.rb +++ b/app/parsers/moodle_xml_parser.rb @@ -6,6 +6,11 @@ def export(questions) # Über Fragen iterieren questions.each do |question| + + if question.type == "order" + # moodle xml doesn't support order-questions, so we skip them + next + end # Grundbaum der Frage aufbauen question_node = root.add_element "question" name_node = question_node.add_element "name" @@ -66,6 +71,7 @@ def export(questions) end (question_node.add_element "shuffleanswers").text = "true" end + end s = "" diff --git a/app/services/order_survey.rb b/app/services/order_survey.rb index e6b1beb..9d305f8 100644 --- a/app/services/order_survey.rb +++ b/app/services/order_survey.rb @@ -24,12 +24,25 @@ def vote(voter, option_position_pairs) if self.survey.running?(false) unless self.survey.matches?(voters: voter) #:fixme: is this "enough" concurrency safe? self.survey.add_to_set(:voters, voter.to_s) - #TODO: erstelle objekt zum füllen der relativen Tabelle + + # fill relative_option_order_object + if option_position_pairs.length > 0 + for outer_index in 0..(option_position_pairs.length-1) + beforeName = option_position_pairs[outer_index].split(' - ')[0] + if option_position_pairs.length > (outer_index + 1) + for inner_index in (outer_index + 1)..(option_position_pairs.length - 1) + afterName = option_position_pairs[inner_index].split(' - ')[0] + self.survey.relative_option_order_object.vote_up(beforeName, afterName) + end + end + end + end + + # fill order_option.votes if option_position_pairs.respond_to?(:each) option_position_pairs.each do |pair| pairArray = pair.split(' - ') if(pairArray.length == 2) - #TODO rausfinden, warum folgender Befehl nicht funktionert self.survey.order_options.where(name: pairArray[0]).first.vote_up(Integer(pairArray[1])) end end diff --git a/app/views/surveys/_answer_pair_result_table.html.erb b/app/views/surveys/_answer_pair_result_table.html.erb index 29945bd..5f17541 100755 --- a/app/views/surveys/_answer_pair_result_table.html.erb +++ b/app/views/surveys/_answer_pair_result_table.html.erb @@ -1,5 +1,5 @@ - +
    <% answer2s = survey.get_all_answer2 %> diff --git a/app/views/surveys/_order_list.html.erb b/app/views/surveys/_order_list.html.erb index 2cf73c0..f992038 100644 --- a/app/views/surveys/_order_list.html.erb +++ b/app/views/surveys/_order_list.html.erb @@ -1,38 +1,17 @@ -
    -
      +
        <% survey.order_options.shuffle! %> <% survey.order_options.each do |option| %> -
      • <%= option.name %>
      • +
      • <%= option.name %>
      • <% end %>

      -
      \ No newline at end of file diff --git a/app/views/surveys/_order_option_absolute_results_table.html.erb b/app/views/surveys/_order_option_absolute_results_table.html.erb index b12cb74..bdc197a 100644 --- a/app/views/surveys/_order_option_absolute_results_table.html.erb +++ b/app/views/surveys/_order_option_absolute_results_table.html.erb @@ -1,5 +1,4 @@ - -
    +
    <% numberOfOptions = survey.order_options.length %> @@ -19,7 +18,7 @@ <% votesForPositionInteger = Integer(votesForPosition) %> <% percentage = "0%" %> <% if survey.total_votes > 0 %> - <% percentage = number_to_percentage(votesForPositionInteger.to_f / total_votes.to_f * 100.to_f, :precision => 0) %> + <% percentage = number_to_percentage(votesForPositionInteger.to_f / survey.total_votes.to_f * 100.to_f, :precision => 0) %> <% end %> <% rowHeightPercentage = number_to_percentage(1.to_f / (1 + survey.order_options.length).to_f * 100.to_f, :precision => 0) %> <% if option.position == currentPosition %> @@ -42,5 +41,4 @@ <% end %> -
    - \ No newline at end of file + \ No newline at end of file diff --git a/app/views/surveys/_order_option_relative_results_table.html.erb b/app/views/surveys/_order_option_relative_results_table.html.erb index b12cb74..df71a42 100644 --- a/app/views/surveys/_order_option_relative_results_table.html.erb +++ b/app/views/surveys/_order_option_relative_results_table.html.erb @@ -1,35 +1,44 @@ - - - - - <% numberOfOptions = survey.order_options.length %> - <% columnWidthPercentage = number_to_percentage(1.to_f / (1 + numberOfOptions).to_f * 100.to_f, :precision => 0) %> - - <% for index in 1..numberOfOptions %> - +
    Position<%= index %>
    + + + <% numberOfOptions = survey.order_options.length %> + <% columnWidthPercentage = number_to_percentage(1.to_f / (1 + numberOfOptions).to_f * 100.to_f, :precision => 0) %> + + + <% if survey.total_votes > 0 %> + <% name_highest_voted_position_map = Hash.new %> + <% survey.order_options.each do |option| %> + <% current_high_score = 0 %> + <% most_voted_position = 0 %> + <% current_index = 0 %> + <% option.votes.split(',').each do |vote_number| %> + <% if current_high_score < vote_number.to_i %> + <% most_voted_position = current_index %> + <% end %> + <% current_index += 1 %> <% end %> - - - - <% survey.order_options.shuffle! %> - <% survey.order_options.each do |option| %> - - <% currentPosition = 1 %> - <% option.votes.split(",").each do |votesForPosition| %> - <% votesForPositionInteger = Integer(votesForPosition) %> - <% percentage = "0%" %> - <% if survey.total_votes > 0 %> - <% percentage = number_to_percentage(votesForPositionInteger.to_f / total_votes.to_f * 100.to_f, :precision => 0) %> - <% end %> - <% rowHeightPercentage = number_to_percentage(1.to_f / (1 + survey.order_options.length).to_f * 100.to_f, :precision => 0) %> - <% if option.position == currentPosition %> - + <% end %> + + + + <% for before_index in 0..(name_highest_voted_position_map.length-1) %> + + <% for after_index in 0..(name_highest_voted_position_map.length-1) %> + <% rowHeightPercentage = number_to_percentage(1.to_f / (1 + survey.order_options.length).to_f * 100.to_f, :precision => 0) %> + <% if before_index == after_index %> + <% else %> + <% percentage = number_to_percentage(survey.relative_option_order_object.get_votes_for(name_highest_voted_position_map[before_index][0], name_highest_voted_position_map[after_index][0]).to_f / survey.total_votes.to_f * 100.to_f, :precision => 0) %> <% end %> - <% currentPosition += 1 %> <% end %> - + <% end %> - -
    <%= t("x_before_y") %>
    <%= option.name %> -
    -
    -

    <%= percentage %>

    + <% name_highest_voted_position_map[option.name] = most_voted_position %> + <% end %> + <% name_highest_voted_position_map = name_highest_voted_position_map.sort {|a,b| a[1]<=>b[1]} %> + <% name_highest_voted_position_map.each do |name_position| %> +
    <%= name_position[0] %>
    <%= name_highest_voted_position_map[before_index][0] %> +
    +
    +

    /

    @@ -37,10 +46,9 @@
    - \ No newline at end of file + <% end %> + + diff --git a/app/views/surveys/_show.html.erb b/app/views/surveys/_show.html.erb index 337be73..e523df7 100755 --- a/app/views/surveys/_show.html.erb +++ b/app/views/surveys/_show.html.erb @@ -112,10 +112,9 @@ <%= t("surveys.show.mark_corrects") %>

    <%= t("relative_results") %>

    -
    <%= render partial: "order_option_relative_results_table", locals: {survey: survey} %> - <%= icon_tag("download-alt") %> + <%= icon_tag("download-alt") %>
    @@ -223,6 +222,18 @@ } }); + $(document).on("click", "#save_relative_table_btn", function(e) { + if($("#relative-result-table").length > 0) { + var base_str = 'data:text/html,' + '' + + '

    <%= survey.name || t(".survey") %>


    ' + + '
    ' + + '' + + $("#relative-result-table").html() + '
    '; + $(this).attr("href", base_str); + return true; + } + }); + if(window.PINGO.isMSIE()){ $(".canvas_downloadable").removeClass("canvas_downloadable"); } diff --git a/app/views/surveys/participate.html.erb b/app/views/surveys/participate.html.erb index 8eaff9a..151afdd 100755 --- a/app/views/surveys/participate.html.erb +++ b/app/views/surveys/participate.html.erb @@ -33,7 +33,7 @@ fieldset[data-role="controlgroup"] label { <% end %> <% end %> - <%= form_tag("/vote", style: 'clear:both;') %> + <%= form_tag("/vote", style: 'clear:both;', id: "participate_order_form") %>
    @@ -173,6 +173,29 @@ fieldset[data-role="controlgroup"] label { connect_timeout = setTimeout(function() {if(!connected && !running) { location.reload(); }}, 7500); + <% if @survey.type == "order" %> + + <% end %> + <% if @survey && @survey.mathjax? %> +<% end %> \ No newline at end of file diff --git a/app/views/questions/_category_question_category_fields.html.erb b/app/views/questions/_category_question_category_fields.html.erb new file mode 100644 index 0000000..9c60df5 --- /dev/null +++ b/app/views/questions/_category_question_category_fields.html.erb @@ -0,0 +1,17 @@ +
    +
    + <%= link_to_remove_association icon_tag("minus-sign"), f %> + <%= f.text_field :name, placeholder: t("surveys.category_name"), class: "category_name_field" %> + <%= f.hidden_field :sub_words, value: "", class: "hidden_sub_words_field" %> +
      + <% question.sub_words.where(category: cat.name).each do |sub_word| %> + <%= form.semantic_fields_for :sub_words, sub_word, class: "form-inline" do |word| %> + <%= render "category_question_sub_words_fields", f: word %> + <% end %> + <% end %> + +
    +
    +
    diff --git a/app/views/questions/_category_question_category_fields_without_locals.html.erb b/app/views/questions/_category_question_category_fields_without_locals.html.erb new file mode 100644 index 0000000..f01c52d --- /dev/null +++ b/app/views/questions/_category_question_category_fields_without_locals.html.erb @@ -0,0 +1,16 @@ +
    +
    + <%= link_to_remove_association icon_tag("minus-sign"), f %> + <%= f.text_field :name, placeholder: t("surveys.category_name"), class: "category_name_field" %> + <%= f.hidden_field :sub_words, value: "", class: "hidden_sub_words_field" %> +
      + <%= form.semantic_fields_for :sub_words, class: "form-inline" do |word| %> + <%= render "category_question_sub_words_fields", f: word %> + <% break %> + <% end %> + +
    +
    +
    diff --git a/app/views/questions/_category_question_sub_words_fields.html.erb b/app/views/questions/_category_question_sub_words_fields.html.erb new file mode 100644 index 0000000..743d10e --- /dev/null +++ b/app/views/questions/_category_question_sub_words_fields.html.erb @@ -0,0 +1,9 @@ +
  • + + <%= icon_tag("minus-sign") %> + + <%= f.text_field :name, placeholder: t("surveys.sub_word_name"), class: "sub_word_name_field" %> + <%= f.hidden_field :category, value: "", class: "hidden_category_name_field" %> + <%= f.hidden_field :_destroy, value: "", class: "hidden_destroy_field" %> +
  • + diff --git a/app/views/questions/_single_form.html.erb b/app/views/questions/_single_form.html.erb index 565e59b..41862eb 100755 --- a/app/views/questions/_single_form.html.erb +++ b/app/views/questions/_single_form.html.erb @@ -24,7 +24,7 @@
    <%= form.semantic_fields_for :question_options do |option| %> - <%= render "single_question_option_fields", f: option %> + <%= render "single_question_option_fields", f: option %> <% end %> +<% elsif survey.has_categories? %> +
    +
    +

    <%= t("results") %>

    +
    + <%= render partial: "category_results_table", locals: {survey: survey} %> + <%= icon_tag("download-alt") %> + <%= t("surveys.show.mark_corrects") %> +
    +
    +
    + <% elsif survey.type == "text" %> <% if !survey.running? && survey.total_votes > 0 %>
    @@ -199,6 +215,8 @@ <% end %> diff --git a/config/locales/views/questions.de.yml b/config/locales/views/questions.de.yml index e7ec9b5..53455d0 100755 --- a/config/locales/views/questions.de.yml +++ b/config/locales/views/questions.de.yml @@ -46,11 +46,11 @@ de: tags: Tags upload: Hochladen und importieren moodle_xml_info: "Zurzeit werden die Moodle XML-Formate truefalse, shortanswer, multichoice, numerical, match und essay unterstützt." - csv_info: "Zurzeit werden als Trennzeichen ausschließlich Kommata akzeptiert. Das Format sieht vor, dass eine Zeile pro Frage verwendet wird. Die erste Spalte stellt den Typ der Frage dar (single, multi, number, match oder text). Spalte zwei enthält den Text der Frage. Spalte drei enthält Zahlen, die durch Semikolon getrennt sind, wobei diese Zahlen für all jene Antwortmöglichkeiten stehen, die korrekt sind (zum Beispiel 1;3;5). Bei Freitextfragen enthält sie die Limitierung für die Anzahl der abzugebenden Antworten (1 für eine, 3 für bis zu drei). Die letzten Spalten enthalten je eine Antwortmöglichkeit. Bei Zuordnungsfragen werden nur die korrekten Paarungen angegeben, wobei die Paare durch ' - ' getrennt sind." + csv_info: "Zurzeit werden als Trennzeichen ausschließlich Kommata akzeptiert. Das Format sieht vor, dass eine Zeile pro Frage verwendet wird. Die erste Spalte stellt den Typ der Frage dar (single, multi, number, match, order, category oder text). Spalte zwei enthält den Text der Frage. Spalte drei enthält Zahlen, die durch Semikolon getrennt sind, wobei diese Zahlen für all jene Antwortmöglichkeiten stehen, die korrekt sind (zum Beispiel 1;3;5). Bei Freitextfragen enthält sie die Limitierung für die Anzahl der abzugebenden Antworten (1 für eine, 3 für bis zu drei). Die letzten Spalten enthalten je eine Antwortmöglichkeit. Bei Zuordnungsfragen werden nur die korrekten Paarungen angegeben, wobei die Paare durch ' - ' getrennt sind. Bei Reihenfolgefragen kommt zuerst die Position, dann Klammer zu und dann das Wort, z.B. '1) Baum'. Bei Kategoriefragen kommmt zuerst die Kategorie gefolgt von drei Bars und dann die durch Semikolon getrennten Begriffe, z.B. 'Bäume|||Eiche;Ahorn;Kastanie'." csv_template_load: "CSV-Vorlage laden" aiken_info: "Jede Frage im Aiken-Format muss eine Angabe korrekter Antworten enthalten" gift_info: "Zurzeit werden True / False, Multiple Choice, Short Answer, Essay, Matching und Numerical-Fragetypen im Gift-Format unterstützt" - ilias_info: "Zurzeit werden Multiple Choice, Single Choice, Freitext, Begriffe benennen und Numerische Fragen im Ilias-Format unterstützt." + ilias_info: "Zurzeit werden Multiple Choice, Single Choice, Freitext, Begriffe benennen, Zuordnungsfragen, Anordnungsfragen und Numerische Fragen im Ilias-Format unterstützt." further_information: "Für weitere Informationen darüber, wie Formate interpretiert werden, klicken Sie hier" upload_questions_legend: "Wählen Sie eine Datei und das Format aus, um Fragen in PINGO zu importieren." share_button: diff --git a/config/locales/views/questions.en.yml b/config/locales/views/questions.en.yml index 5d15f7a..e724534 100755 --- a/config/locales/views/questions.en.yml +++ b/config/locales/views/questions.en.yml @@ -44,11 +44,11 @@ en: tags: Tags upload: Upload and import moodle_xml_info: "Currently the Moodle XML formats truefalse, shortanswer, multichoice, numerical, match and essay are supported." - csv_info: "Currently commas are accepted as separator exclusively. The format is specified as follows: Each line contains one question. The first column specifies the type of the question (single, multi, number, match or text). Column two contains the text of the question. Column three consists of numbers, that are seperated by semicolons, where these numbers stand for the correct answer options. (zum Beispiel 1;3;5). If it's a text question, this column holds the limitations for the numbers of answers to give (1 for one, 3 for up to three). In each of the following columns is an answer option. In case of match questions, only the correct pairings are given, whereby a pair is seperated by ' - '." + csv_info: "Currently commas are accepted as separator exclusively. The format is specified as follows: Each line contains one question. The first column specifies the type of the question (single, multi, number, match or text). Column two contains the text of the question. Column three consists of numbers, that are seperated by semicolons, where these numbers stand for the correct answer options. (e.g. 1;3;5). If it's a text question, this column holds the limitations for the numbers of answers to give (1 for one, 3 for up to three). In each of the following columns is an answer option. In case of match questions, only the correct pairings are given, whereby a pair is seperated by ' - '. In the case order questions, at first there's te position, then a closing bracket and then the word, e.g. '1) Tree'. In the case of category questions, at first there's the category followed by three bars and the the semicolon-seperated word, e.g. 'Trees|||Maple;Chestnut;Palm'." csv_template_load: "Load CSV-template" aiken_info: "Any question in written in Aiken must specify correct answers" gift_info: "Currently True / False, Multiple Choice, Short Answer, Essay, Matching and Numerical questions are supported for the Gift format" - ilias_info: "Currently Multiple Choice, Single Choice, Text, Textsubset and Numeric questions are supported for the Ilias format." + ilias_info: "Currently Multiple Choice, Single Choice, Text, Textsubset, Order, Assign and Numeric questions are supported for the Ilias format." further_information: "For further information on how imported files are interpreted click here" upload_questions_legend: "Please choose a file and format to import questions into PINGO." share_button: diff --git a/config/locales/views/surveys.de.yml b/config/locales/views/surveys.de.yml index 02aced5..a0766ce 100755 --- a/config/locales/views/surveys.de.yml +++ b/config/locales/views/surveys.de.yml @@ -36,6 +36,7 @@ de: choose-match: "Bitte ordnen Sie die Felder einander zu, indem Sie nacheinander eines auf der linken und eines auf der rechten Seite anklicken" chosen-match: "Sie haben zugeordnet" choose-order: "Sie verändern die Reihenfolge der Felder durch Anklicken, Verschieben und Loslassen (Drag and Drop)" + categorize-words: "Sie ordnen die Wörter auf der rechten Seite den Kategorien auf der linken Seite zu, indem Sie sie anklicken, verschieben und loslassen (Drag and Drop)" show: survey: Umfrage from: vom @@ -46,6 +47,7 @@ de: is_text: Dies ist eine Freitext-Frage. is_match: Dies ist eine Zuordnungsfrage. is_order: Dies ist eine Reihenfolge-Frage. + is_category: Dies ist eine Kategorie-Frage. votes_participants: Teilnehmer is_multi: Dies ist eine Multiple-Choice-Umfrage. running_notice: 'Diese Umfrage läuft. Teilnahme ist über %{url} möglich.' @@ -72,6 +74,7 @@ de: histogram: "Histogramm" repeated: "Diese Umfrage ist eine wiederholte Umfrage." mark_corrects: Korrekte markieren + correct_order_and_mark: Korrekt anordnen und markieren text_table_results: term: "Antwort" occurrences: "Häufigkeit" diff --git a/config/locales/views/surveys.en.yml b/config/locales/views/surveys.en.yml index 9aeb519..5a2dee9 100755 --- a/config/locales/views/surveys.en.yml +++ b/config/locales/views/surveys.en.yml @@ -36,6 +36,7 @@ en: choose-match: "Please match the fields by successively clicking one on the left and one on the right side" chosen-match: "You've matched" choose-order: "Change the order of the fields via drag and drop." + categorize-words: "Assign the words on the right to the categories on the left via drag and drop." show: survey: Survey from: from @@ -46,6 +47,7 @@ en: is_text: This is a text question is_match: This is a match question is_order: This is an order question. + is_category: This is a category question. votes_participants: participants is_multi: This is a multiple-choice survey. running_notice: 'This survey is running. People can access this survey at %{url}' @@ -72,6 +74,7 @@ en: histogram: "histogram" repeated: "This is a repeated survey." mark_corrects: mark correct answers + correct_order_and_mark: Order correctly and mark text_table_results: term: "answer" occurrences: "occurrences" diff --git a/log.txt b/log.txt index 79c1e38..70447cf 100644 --- a/log.txt +++ b/log.txt @@ -1,2 +1,5 @@ -D, [2015-04-25T16:31:25.827131 #389] DEBUG -- : Log file created -D, [2015-04-25T16:34:15.610292 #389] DEBUG -- : Log file created +D, [2015-06-10T16:00:30.934205 #3171] DEBUG -- : Log file created +D, [2015-06-10T16:00:44.476884 #3171] DEBUG -- : LOLZ testOrder +D, [2015-06-10T16:00:44.478470 #3171] DEBUG -- : LOLZ A +D, [2015-06-10T16:00:44.479457 #3171] DEBUG -- : LOLZ B +D, [2015-06-10T16:00:44.479971 #3171] DEBUG -- : LOLZ C From 2096aff55bed7cb0202e7c45dbd1857bb789fa55 Mon Sep 17 00:00:00 2001 From: KKrenz Date: Wed, 17 Jun 2015 17:22:08 +0200 Subject: [PATCH 19/22] finish participate@categorySurveys; fix show-results4category --- app/assets/stylesheets/surveys.css.less | 26 ++--- app/controllers/surveys_controller.rb | 2 +- app/views/surveys/_category_lists.html.erb | 99 ++++++++++--------- .../surveys/_category_results_table.html.erb | 4 +- app/views/surveys/participate.html.erb | 32 ++++++ 5 files changed, 104 insertions(+), 59 deletions(-) diff --git a/app/assets/stylesheets/surveys.css.less b/app/assets/stylesheets/surveys.css.less index 0856451..a3aa150 100755 --- a/app/assets/stylesheets/surveys.css.less +++ b/app/assets/stylesheets/surveys.css.less @@ -12,9 +12,9 @@ } .categoryDiv { - border: 1px solid red; - width: 90%; - height: 50px; + border: 1px solid white; + width: 100%; + height: 36px; } .ghost { @@ -25,12 +25,12 @@ #overmsg { display:none; background-color: #FCC; - border: solid 1px #C66; - -moz-border-radius: 5px; - border-radius: 5px; - -moz-box-shadow: 5px 5px 2px #C66; - -webkit-box-shadow: 5px 5px 2px #C66; - box-shadow: 5px 5px 2px #C66; + border: solid 1px #C66; + -moz-border-radius: 5px; + border-radius: 5px; + -moz-box-shadow: 5px 5px 2px #C66; + -webkit-box-shadow: 5px 5px 2px #C66; + box-shadow: 5px 5px 2px #C66; margin-bottom:10px; } #not_running { @@ -51,8 +51,12 @@ font-weight: bold; } -#survey-table td { - width: 50%; +#survey-table { + width: 100%; + + td { + width: 50%; + } } .pointer { diff --git a/app/controllers/surveys_controller.rb b/app/controllers/surveys_controller.rb index 035509d..252fca6 100755 --- a/app/controllers/surveys_controller.rb +++ b/app/controllers/surveys_controller.rb @@ -281,7 +281,7 @@ def vote voted_for = '
      ' params[:option].map do |o| voted_for += '
    • '+o.split(" - ")[0]+':
        ' - o.split(";").each do |word| + o.split(" - ")[1].split(";").each do |word| voted_for += '
      • ' + word + '
      • ' end voted_for += '
    • ' diff --git a/app/views/surveys/_category_lists.html.erb b/app/views/surveys/_category_lists.html.erb index b602e06..0aa49b0 100644 --- a/app/views/surveys/_category_lists.html.erb +++ b/app/views/surveys/_category_lists.html.erb @@ -1,47 +1,56 @@ - - - <% categories = survey.categories %> - <% sub_words = survey.sub_words %> - <% categories.shuffle! %> - <% sub_words.shuffle! %> - - - - -
      -
        - <% for j in 0..(categories.length - 1) %> -
      • <%= categories[j].name %>:
      • -
      • -
        -
      • - <% end %> -
      -
      -
        - <% for j in 0..(sub_words.length - 1) %> -
      • <%= sub_words[j].name %>
      • - <% end %> -
      -
      -
      + + <% categories = survey.categories %> + <% sub_words = survey.sub_words %> + <% categories.shuffle! %> + <% sub_words.shuffle! %> + + + + +
      +
        + <% for j in 0..(categories.length - 1) %> +
      • + <%= categories[j].name %>:
        +
        +
      • + <% end %> +
      +
      +
        + <% for j in 0..(sub_words.length - 1) %> +
      • <%= sub_words[j].name %>
      • + <% end %> +
      +
      +
      +
      - - - + + + - - \ No newline at end of file + \ No newline at end of file diff --git a/app/views/surveys/_category_results_table.html.erb b/app/views/surveys/_category_results_table.html.erb index 5d29685..cc66b61 100644 --- a/app/views/surveys/_category_results_table.html.erb +++ b/app/views/surveys/_category_results_table.html.erb @@ -21,14 +21,14 @@ <% percentage = number_to_percentage(sub_word.get_votes_for(category.name).to_f / survey.total_votes.to_f * 100.to_f, :precision => 0) %> <% end %> <% if category.name == currently_correct_category %> - +

      <%= percentage %>

      <% else %> - +

      <%= percentage %>

      diff --git a/app/views/surveys/participate.html.erb b/app/views/surveys/participate.html.erb index 151afdd..646e5f8 100755 --- a/app/views/surveys/participate.html.erb +++ b/app/views/surveys/participate.html.erb @@ -196,6 +196,38 @@ fieldset[data-role="controlgroup"] label { <% end %> + <% if @survey.type == "category" %> + + <% end %> + <% if @survey && @survey.mathjax? %>