diff --git a/app/controllers/answers_controller.rb b/app/controllers/answers_controller.rb index c60fbd3..498603b 100644 --- a/app/controllers/answers_controller.rb +++ b/app/controllers/answers_controller.rb @@ -36,6 +36,41 @@ @answer.update(params[:answer]) end + @section_id = @answer.question.section.id + + # these are used for updating the status line + @username = @answer.user.name + @timestamp = "" + + if @answer.text.present? + @timestamp = @answer.updated_at.iso8601 + end + + + @nquestions = 0 + @nanswers = 0 + @n_section_questions = 0 + @n_section_answers = 0 + + plan = Plan.find(plan_id) + plan.template.phases.each do |phase| + phase.sections.each do |section| + section.questions.each do |question| + @nquestions += 1 + if section.id == @section_id + @n_section_questions += 1 + end + question.answers = question.answers.to_a.select {|answer| answer.plan_id == plan.id} + if question.answers.present? && question.answers.first.text.present? + @nanswers += 1 + if section.id == @section_id + @n_section_answers += 1 + end + end + end + end + end + respond_to do |format| # pass new lock_version back to the client or they'll never save again @lock_version = @answer.lock_version @@ -49,4 +84,5 @@ format.js {} end end + end diff --git a/app/controllers/phases_controller.rb b/app/controllers/phases_controller.rb index afe9711..f1890ca 100644 --- a/app/controllers/phases_controller.rb +++ b/app/controllers/phases_controller.rb @@ -15,14 +15,22 @@ # the eager_load pulls in ALL answers # need to restrict to just ones for this plan + # at the same time count the questions and answers for the status + @nquestions = 0 + @nanswers = 0 + @plan.template.phases.each do |phase| - phase.sections do |section| + phase.sections.each do |section| section.questions.each do |question| + @nquestions += 1 question.answers = question.answers.to_a.select {|answer| answer.plan_id == @plan.id} + if question.answers.present? && question.answers.first.text.present? + @nanswers += 1 + end end end end - + # Now we need to get all the themed guidance for the plan. # TODO: think this through again, there may be a better way to do this. # diff --git a/app/views/answers/update.js.erb b/app/views/answers/update.js.erb index 57e2234..3ddb49f 100644 --- a/app/views/answers/update.js.erb +++ b/app/views/answers/update.js.erb @@ -3,6 +3,9 @@ // On success this will be "" on error it will be the // conflicting answer +// go back from "Saving..." message to "Save" button +$("#saving-<%=@question.id%>").hide(); +$("#saving-<%=@question.id%>").prev().show(); <% if @old_answer %> $("#answer_notice_<%=@question.id%>").html("<%= escape_javascript(render partial: '/phases/answer', locals: { question: @question, answer: @old_answer}) %>"); @@ -15,3 +18,24 @@ // this it will fail forever. $("#answer_lock_version-<%=@question.id%>").val(<%= @lock_version %>); + +// update the answer status + +var q_status = $("#<%=@question.id%>-status"); +var timestamp = "<%=@timestamp%>"; + +if( timestamp != "") { + q_status.text(""); + // TODO: i18n this + q_status.append( "Answered \" title=\"<%=@timestamp%>\"><%=@timestamp%> by <%=@username%>"); + $('abbr.timeago').timeago(); +} + + +// update plan progress bar +$(".progress").html("<%= escape_javascript(render :partial => "/plans/progress", locals: {nquestions: @nquestions, nanswers: @nanswers}) %>"); + + +// update the section progress message +//TODO: I18n this +$("#<%=@section_id%>-status").html("(<%=@n_section_questions%> questions, <%=@n_section_answers%> answered)"); diff --git a/app/views/notes/archive.js.erb b/app/views/notes/archive.js.erb new file mode 100644 index 0000000..f2687fa --- /dev/null +++ b/app/views/notes/archive.js.erb @@ -0,0 +1,29 @@ + +// remove all tinymce explicitly or re-init will not work later +tinymce.remove(".tinymce"); + +// render the list of notes and invisible view and edit sections +<% listlabel = "#comment-question-area-#{@question.id}" %> +$("<%=listlabel%>").html( + "<%= escape_javascript( render partial: '/phases/note', locals: {question: @question, answer: @answer, plan: @plan } ) %>" +); + +// TODO: this duplicates what is in the .yml file +// DRY it out! +tinymce.init({ + selector: ".tinymce", + statusbar: false, + menubar: false, + toolbar: "bold italic | bullist numlist | link | table", + plugins: [ "table", "link", "paste" ], + target_list: false, + autoresize_min_height: 130, + extended_valid_elements: [ "a[href|target=_blank]" ], + paste_auto_cleanup_on_paste : true, + paste_remove_styles: true, + paste_retain_style_properties: "none", + paste_convert_middot_lists: true, + paste_remove_styles_if_webkit: true, + paste_remove_spans: true, + paste_strip_class_attributes: "all" +}); diff --git a/app/views/notes/create.js.erb b/app/views/notes/create.js.erb new file mode 100644 index 0000000..4cd1b85 --- /dev/null +++ b/app/views/notes/create.js.erb @@ -0,0 +1,31 @@ + +// rewrite the number of notes heading e.g. Notes(3) +<% noteslabel = "#notes_number_#{@question.id}" %> +$("<%=noteslabel%>").html("Notes (<%= @num_notes %>)"); + +// need to remove the existing tinymce editor otherwise +tinymce.remove(".tinymce"); + +// render the list of notes and invisible view and edit sections +<% listlabel = "#comment-question-area-#{@question.id}" %> +$("<%=listlabel%>").html( + "<%= escape_javascript( render partial: '/phases/note', locals: {question: @question, answer: @answer, plan: @plan } ) %>" +); + +tinymce.init({ + selector: ".tinymce", + statusbar: false, + menubar: false, + toolbar: "bold italic | bullist numlist | link | table", + plugins: [ "table", "link", "paste" ], + target_list: false, + autoresize_min_height: 130, + extended_valid_elements: [ "a[href|target=_blank]" ], + paste_auto_cleanup_on_paste : true, + paste_remove_styles: true, + paste_retain_style_properties: "none", + paste_convert_middot_lists: true, + paste_remove_styles_if_webkit: true, + paste_remove_spans: true, + paste_strip_class_attributes: "all" +}); diff --git a/app/views/notes/update.js.erb b/app/views/notes/update.js.erb new file mode 100644 index 0000000..45c5eb5 --- /dev/null +++ b/app/views/notes/update.js.erb @@ -0,0 +1,27 @@ + +// need to remove the existing tinymce editor otherwise +tinymce.remove(".tinymce"); + +// render the list of notes and invisible view and edit sections +<% listlabel = "#comment-question-area-#{@question.id}" %> +$("<%=listlabel%>").html( + "<%= escape_javascript( render partial: '/phases/note', locals: {question: @question, answer: @answer, plan: @plan } ) %>" +); + +tinymce.init({ + selector: ".tinymce", + statusbar: false, + menubar: false, + toolbar: "bold italic | bullist numlist | link | table", + plugins: [ "table", "link", "paste" ], + target_list: false, + autoresize_min_height: 130, + extended_valid_elements: [ "a[href|target=_blank]" ], + paste_auto_cleanup_on_paste : true, + paste_remove_styles: true, + paste_retain_style_properties: "none", + paste_convert_middot_lists: true, + paste_remove_styles_if_webkit: true, + paste_remove_spans: true, + paste_strip_class_attributes: "all" +}); diff --git a/app/views/phases/_answer_form.html.erb b/app/views/phases/_answer_form.html.erb index 6ee222a..16c60e0 100644 --- a/app/views/phases/_answer_form.html.erb +++ b/app/views/phases/_answer_form.html.erb @@ -104,10 +104,10 @@ <% end %> - <% if answer.nil? || answer.created_at.nil? %> + <% if answer.nil? || !answer.text.present? %> <%= _('Not answered yet') %> <% else %> - <%= _('Answered')%> <%= answer.created_at %><%= _(' by')%> <%= answer.user.name %> + <%= _('Answered')%> <%= answer.updated_at.iso8601 %><%= _(' by')%> <%= answer.user.name %> <% end %> diff --git a/app/views/phases/edit.html.erb b/app/views/phases/edit.html.erb index 3dbdc34..7563044 100644 --- a/app/views/phases/edit.html.erb +++ b/app/views/phases/edit.html.erb @@ -10,24 +10,9 @@ <%= render :partial => "/plans/plan_title", locals: {plan: @plan} %> - -<% status = @plan.status %>
- <%space_used = status["space_used"].to_i - space_title = _('approx. %{space_used}%% of available space used (max %{num_pages} pages)') % { space_used: space_used, num_pages: @plan.template.settings(:export).max_pages } - answered = %(#{status["num_answers"]}/#{status["num_questions"]})%> -
- <%= answered -%> <%= _('questions answered')%> - ;" title="<%= answered -%> <%= _('questions answered')%>"> -
- -
- -
- = 100 ? "class=bar-full-text" : "" -%>><%= space_title -%> - " style="width: <%= space_used -%>%;" title="<%= space_title -%>"> -
-
+ <%= render :partial => "/plans/progress", locals: {nquestions: @nquestions, nanswers: @nanswers} %> + <%= render :partial => "/plans/plan_nav_tabs", locals: {plan: @plan, active: @phase.title} %> diff --git a/app/views/plans/_progress.html.erb b/app/views/plans/_progress.html.erb new file mode 100644 index 0000000..9a2fa84 --- /dev/null +++ b/app/views/plans/_progress.html.erb @@ -0,0 +1,5 @@ +<% answered = %(#{nanswers}/#{nquestions})%> +
+ <%= answered -%> <%= _('questions answered')%> + +
diff --git a/lib/assets/javascripts/plans.js b/lib/assets/javascripts/plans.js index b14b5f7..f436530 100644 --- a/lib/assets/javascripts/plans.js +++ b/lib/assets/javascripts/plans.js @@ -124,16 +124,6 @@ saving_message.show(); s_status = $(this).closest(".accordion-group").find(".section-status:first"); s_status.toggle_dirty(q_id, false); - // Allow quarter of a second for database to update - timeout = setTimeout(function(){ - $.getJSON("status.json", function(data) { - $.fn.update_plan_progress(data); - $.fn.update_timestamp(q_id, data); - s_status.update_section_progress(data); - submit_button.parent().show(); - saving_message.hide(); - }); - },250); }); //accordion guidance @@ -159,40 +149,17 @@ // Handle section actions on accordion expansion/collapse $('.section-collapse').on('show', function() { - var section = $(this); - - $.getJSON("status.json", function(data) { - $.fn.update_plan_progress(data); - $(".section-status").each(function(){ - $(this).update_section_progress(data); - }); - - //For each question in section, check answer timestamp against currently displayed - var section_id = section.attr("id").split('-')[1]; - var num_questions = data.sections[section_id]["questions"].length; - for (var i = 0; i < num_questions; i++) { - question_id = data.sections[section_id]["questions"][i]; - $.fn.update_timestamp(question_id, data) - } - }); + $('abbr.timeago').timeago(); }).on('hide', function(){ - var section = $(this); - // Only attempt unlock if there are forms on the page (not read-only) - if ($('.question-form').length > 0) { - var section_id = section.attr("id").split('-')[1]; - // LIBDMP-137 - // Changed post request 'unlock_section' to 'unlock_section.json'. 'unlock_section' unnecessary returns a huge html response and takes a quite lot of time to process(3sec) lowering server - // performance when there are large number of concurrent users. - //$.post('unlock_section.json', {section_id: section_id}); - - if ($.fn.is_dirty(section_id)) { + var section = $(this); + var section_id = section.attr("id").split('-')[1]; + if ($.fn.is_dirty(section_id)) { $('#unsaved-answers-'+section_id).text(""); $.each($.fn.get_unsaved_questions(section_id), function(index, question_text){ $('#unsaved-answers-'+section_id).append("
  • "+question_text+"
  • "); }); $('#section-' + section_id + '-collapse-alert').modal(); - } - } + } }); $(".cancel-section-collapse").click(function () { @@ -237,14 +204,6 @@ $('#guidance-question-area-'+ q_id).show(); e.preventDefault(); }); - - - - - - - - }); $.fn.get_unsaved_questions = function(section_id) { @@ -270,8 +229,6 @@ }); return questions; } - - }; $.fn.is_dirty = function(section_id, question_id) { @@ -343,15 +300,39 @@ } }; +$.fn.update_question_timestamp = function(question_id) { + q_status = $('#'+question_id+'-status'); + var t = q_status.children("abbr:first"); + var timestamp = new Date(t.attr('data-time')); + if (timestamp != null) { + timestamp = new Date(Number(timestamp) * 1000); + q_status.text(""); + // TODO: i18n this + q_status.append( "Answered" + " " + "by" + " " + data.questions[question_id]["answered_by"]); + t = q_status.children("abbr:first"); + // Update label to indicate successful submission + q_status.removeClass("label-info label-warning"); + q_status.addClass("label-success"); + // Set timestamp text and data + t.text(timestamp.toUTCString()); + t.attr('title', timestamp.toISOString()).data("timeago",null).timeago(); + t.attr('data-time', timestamp.toISOString()); + return true; + } + return false; +}; + $.fn.update_timestamp = function(question_id, data) { q_status = $('#'+question_id+'-status'); var t = q_status.children("abbr:first"); var current_timestamp = new Date(t.attr('data-time')); var timestamp = data.questions[question_id]["answer_updated_at"]; + alert(timestamp); if (timestamp != null) { timestamp = new Date(Number(timestamp) * 1000); if (timestamp.getTime() != current_timestamp.getTime()) { q_status.text(""); + // TODO: i18n this q_status.append( "Answered" + " " + "by" + " " + data.questions[question_id]["answered_by"]); t = q_status.children("abbr:first"); // Update label to indicate successful submission