From 7ad4bd523f59c9534b5b49404219b38768e9f3da Mon Sep 17 00:00:00 2001
From: Kevin Sedgley
Date: Mon, 5 Feb 2024 14:05:56 +0000
Subject: [PATCH] Autosave tags, topics, department and notes
---
.../javascripts/admin-actions-autosave.js | 64 +++++++++++++++++++
.../stylesheets/petitions/admin/_actions.scss | 40 ++++++++++++
.../admin/archived/notes_controller.rb | 10 ++-
.../petition_departments_controller.rb | 10 ++-
.../archived/petition_tags_controller.rb | 10 ++-
.../archived/petition_topics_controller.rb | 10 ++-
app/controllers/admin/notes_controller.rb | 10 ++-
.../admin/petition_departments_controller.rb | 10 ++-
.../admin/petition_tags_controller.rb | 10 ++-
.../admin/petition_topics_controller.rb | 10 ++-
app/models/archived/petition.rb | 4 ++
.../_petition_action_departments.html.erb | 6 +-
.../admin/_petition_action_notes.html.erb | 6 +-
.../admin/_petition_action_tags.html.erb | 6 +-
.../admin/_petition_action_topics.html.erb | 6 +-
.../notes/_petition_action_notes.html.erb | 14 +++-
.../_petition_action_departments.html.erb | 14 +++-
.../_petition_action_tags.html.erb | 14 +++-
.../_petition_action_topics.html.erb | 16 +++--
.../notes/_petition_action_notes.html.erb | 16 +++--
.../_petition_action_departments.html.erb | 15 ++++-
.../_petition_action_tags.html.erb | 15 ++++-
.../_petition_action_topics.html.erb | 15 ++++-
app/views/layouts/admin.html.erb | 9 +++
config/initializers/assets.rb | 1 +
.../admin/moderator_tags_a_petition.feature | 15 +++++
features/admin/notes.feature | 15 +++++
.../moderator_tags_a_petition.rb | 28 ++++++++
features/step_definitions/notes_steps.rb | 14 ++++
features/step_definitions/reload_page.rb | 3 +
30 files changed, 358 insertions(+), 58 deletions(-)
create mode 100644 app/assets/javascripts/admin-actions-autosave.js
create mode 100644 features/step_definitions/moderator_tags_a_petition.rb
create mode 100644 features/step_definitions/notes_steps.rb
create mode 100644 features/step_definitions/reload_page.rb
diff --git a/app/assets/javascripts/admin-actions-autosave.js b/app/assets/javascripts/admin-actions-autosave.js
new file mode 100644
index 000000000..a22478310
--- /dev/null
+++ b/app/assets/javascripts/admin-actions-autosave.js
@@ -0,0 +1,64 @@
+$(function() {
+ if (typeof $ === 'undefined') { return; }
+
+ $(document).on({
+ ajaxStart: function() { $('body').addClass('ajax-active'); },
+ ajaxStop: function() { $('body').removeClass('ajax-active'); }
+ });
+
+ function debounce(f, delay) {
+ var debounceTimer = 0;
+ return function() {
+ var context = this;
+ var args = arguments;
+ clearTimeout(debounceTimer);
+ debounceTimer = setTimeout(function() {
+ f.apply(context, args);
+ }, delay);
+ }
+ }
+
+ function setHeaderOrLabelState(headerOrLabel, state) {
+ headerOrLabel.removeClass(['saving', 'saved', 'error']);
+ if(state) headerOrLabel.addClass(state);
+
+ headerOrLabel.next('.flash-alert').remove();
+ if("error" == state) {
+ headerOrLabel.after('
').next().text('There was an error saving. Please manually submit the form.')
+ }
+ }
+
+ var debouncedSubmitForm = debounce(function() {
+ var form = $(this).closest('form');
+ var headerOrLabel = form.prevAll('h2');
+ if(!headerOrLabel.length) {
+ headerOrLabel = $("label[for='" + $(this).attr('id') + "']");
+ }
+ setHeaderOrLabelState(headerOrLabel, 'saving');
+
+ $.ajax({
+ type: form.attr('method'),
+ url: form.attr('action'),
+ headers: { 'Accept': 'application/json' },
+ data: form.serialize(),
+ success: function(response) {
+ if(response && response.updated) {
+ setHeaderOrLabelState(headerOrLabel, 'saved');
+ } else {
+ setHeaderOrLabelState(headerOrLabel, 'error');
+ }
+ },
+ error: function(jqXHR, textStatus, errorThrown) {
+ setHeaderOrLabelState(headerOrLabel, 'error');
+ }
+ });
+ }, 500); //500ms delay
+
+ $('input[type=checkbox][data-autosave]').change(function() {
+ debouncedSubmitForm.call(this);
+ });
+
+ $('textarea[data-autosave]').on('input', function() {
+ debouncedSubmitForm.call(this);
+ });
+});
diff --git a/app/assets/stylesheets/petitions/admin/_actions.scss b/app/assets/stylesheets/petitions/admin/_actions.scss
index 2e69c4ba0..2969fe13e 100644
--- a/app/assets/stylesheets/petitions/admin/_actions.scss
+++ b/app/assets/stylesheets/petitions/admin/_actions.scss
@@ -1,3 +1,11 @@
+@keyframes spinner {
+ to {transform: rotate(360deg);}
+}
+@keyframes fadeOut {
+ from {opacity: 1;}
+ to {opacity: 0;}
+}
+
.admin {
.petition-actions {
margin-top: $gutter*2;
@@ -7,6 +15,38 @@
padding: $gutter-two-thirds 0;
border-top: 1px solid $border-colour;
@extend %contain-floats;
+
+ .saving::after {
+ content: "";
+ box-sizing: border-box;
+ display: inline-block;
+ top: 50%;
+ left: 50%;
+ width: 12px;
+ height: 12px;
+ margin-top: -10px;
+ margin-left: 8px;
+ border-radius: 50%;
+ border: 2px solid rgba($caution, 0.5);
+ border-top-color: $caution;
+ background: rgba($caution, 0.5);
+ animation: spinner .6s linear infinite;
+ vertical-align: 3px;
+ }
+
+ .saved::after {
+ background-color: $caution;
+ border-radius: 6px;
+ content: "";
+ display: inline-block;
+ height: 12px;
+ margin-left: 8px;
+ width: 12px;
+ vertical-align: 3px;
+ animation-name: fadeOut;
+ animation-duration: 2s;
+ animation-fill-mode: forwards;
+ }
}
.petition-action-heading {
diff --git a/app/controllers/admin/archived/notes_controller.rb b/app/controllers/admin/archived/notes_controller.rb
index f642ee0ea..afda49551 100644
--- a/app/controllers/admin/archived/notes_controller.rb
+++ b/app/controllers/admin/archived/notes_controller.rb
@@ -12,9 +12,15 @@ def show
def update
if @note.update(note_params)
- redirect_to admin_archived_petition_url(@petition)
+ respond_to do |format|
+ format.html { redirect_to admin_archived_petition_url(@petition) }
+ format.json { render json: { updated: true } }
+ end
else
- render 'admin/archived/petitions/show', alert: :petition_not_updated
+ respond_to do |format|
+ format.html { render 'admin/archived/petitions/show', alert: :petition_not_updated }
+ format.json { render json: { updated: false } }
+ end
end
end
diff --git a/app/controllers/admin/archived/petition_departments_controller.rb b/app/controllers/admin/archived/petition_departments_controller.rb
index 13c53e74c..fa782f4af 100644
--- a/app/controllers/admin/archived/petition_departments_controller.rb
+++ b/app/controllers/admin/archived/petition_departments_controller.rb
@@ -7,9 +7,15 @@ def show
def update
if @petition.update(petition_params)
- redirect_to admin_archived_petition_url(@petition), notice: :petition_updated
+ respond_to do |format|
+ format.html { redirect_to admin_archived_petition_url(@petition), notice: :petition_updated }
+ format.json { render json: { updated: true } }
+ end
else
- render 'admin/archived/petitions/show'
+ respond_to do |format|
+ format.html { render 'admin/archived/petitions/show', alert: :petition_not_updated }
+ format.json { render json: { updated: true } }
+ end
end
end
diff --git a/app/controllers/admin/archived/petition_tags_controller.rb b/app/controllers/admin/archived/petition_tags_controller.rb
index 8c765be7f..24abfd8ce 100644
--- a/app/controllers/admin/archived/petition_tags_controller.rb
+++ b/app/controllers/admin/archived/petition_tags_controller.rb
@@ -7,9 +7,15 @@ def show
def update
if @petition.update(petition_params)
- redirect_to admin_archived_petition_url(@petition), notice: :petition_updated
+ respond_to do |format|
+ format.html { redirect_to admin_archived_petition_url(@petition), notice: :petition_updated }
+ format.json { render json: { updated: true } }
+ end
else
- render 'admin/archived/petitions/show', alert: :petition_not_updated
+ respond_to do |format|
+ format.html { render 'admin/archived/petitions/show', alert: :petition_not_updated }
+ format.json { render json: { updated: true } }
+ end
end
end
diff --git a/app/controllers/admin/archived/petition_topics_controller.rb b/app/controllers/admin/archived/petition_topics_controller.rb
index 549d8e563..de444f129 100644
--- a/app/controllers/admin/archived/petition_topics_controller.rb
+++ b/app/controllers/admin/archived/petition_topics_controller.rb
@@ -7,9 +7,15 @@ def show
def update
if @petition.update(petition_params)
- redirect_to admin_archived_petition_url(@petition), notice: :petition_updated
+ respond_to do |format|
+ format.html { redirect_to admin_archived_petition_url(@petition), notice: :petition_updated }
+ format.json { render json: { updated: true } }
+ end
else
- render 'admin/archived/petitions/show', alert: :petition_not_updated
+ respond_to do |format|
+ format.html { render 'admin/archived/petitions/show', alert: :petition_not_updated }
+ format.json { render json: { updated: true } }
+ end
end
end
diff --git a/app/controllers/admin/notes_controller.rb b/app/controllers/admin/notes_controller.rb
index 5e52dce2d..2ed04eca6 100644
--- a/app/controllers/admin/notes_controller.rb
+++ b/app/controllers/admin/notes_controller.rb
@@ -12,9 +12,15 @@ def show
def update
if @note.update(note_params)
- redirect_to [:admin, @petition]
+ respond_to do |format|
+ format.html { redirect_to [:admin, @petition] }
+ format.json { render json: { updated: true } }
+ end
else
- render 'admin/petitions/show', alert: :petition_not_updated
+ respond_to do |format|
+ format.html { render 'admin/petitions/show', alert: :petition_not_updated }
+ format.json { render json: { updated: false } }
+ end
end
end
diff --git a/app/controllers/admin/petition_departments_controller.rb b/app/controllers/admin/petition_departments_controller.rb
index 26bb09b8f..495dd53db 100644
--- a/app/controllers/admin/petition_departments_controller.rb
+++ b/app/controllers/admin/petition_departments_controller.rb
@@ -7,9 +7,15 @@ def show
def update
if @petition.update(petition_params)
- redirect_to [:admin, @petition], notice: :petition_updated
+ respond_to do |format|
+ format.html { redirect_to admin_petition_url(@petition), notice: :petition_updated }
+ format.json { render json: { updated: true } }
+ end
else
- render 'admin/petitions/show'
+ respond_to do |format|
+ format.html { render 'admin/petitions/show', alert: :petition_not_updated }
+ format.json { render json: { updated: false } }
+ end
end
end
diff --git a/app/controllers/admin/petition_tags_controller.rb b/app/controllers/admin/petition_tags_controller.rb
index 4f2d4d253..68a6076ee 100644
--- a/app/controllers/admin/petition_tags_controller.rb
+++ b/app/controllers/admin/petition_tags_controller.rb
@@ -7,9 +7,15 @@ def show
def update
if @petition.update(petition_params)
- redirect_to [:admin, @petition], notice: :petition_updated
+ respond_to do |format|
+ format.html { redirect_to admin_petition_url(@petition), notice: :petition_updated }
+ format.json { render json: { updated: true } }
+ end
else
- render 'admin/petitions/show', alert: :petition_not_updated
+ respond_to do |format|
+ format.html { render 'admin/petitions/show', alert: :petition_not_updated }
+ format.json { render json: { updated: false } }
+ end
end
end
diff --git a/app/controllers/admin/petition_topics_controller.rb b/app/controllers/admin/petition_topics_controller.rb
index 0ab114591..34d53ea35 100644
--- a/app/controllers/admin/petition_topics_controller.rb
+++ b/app/controllers/admin/petition_topics_controller.rb
@@ -7,9 +7,15 @@ def show
def update
if @petition.update(petition_params)
- redirect_to [:admin, @petition], notice: :petition_updated
+ respond_to do |format|
+ format.html { redirect_to admin_petition_url(@petition), notice: :petition_updated }
+ format.json { render json: { updated: true } }
+ end
else
- render 'admin/petitions/show', alert: :petition_not_updated
+ respond_to do |format|
+ format.html { render 'admin/petitions/show', alert: :petition_not_updated }
+ format.json { render json: { updated: false } }
+ end
end
end
diff --git a/app/models/archived/petition.rb b/app/models/archived/petition.rb
index 966d17af2..ce556ac2f 100644
--- a/app/models/archived/petition.rb
+++ b/app/models/archived/petition.rb
@@ -244,6 +244,10 @@ def scheduled_for_debate
end
end
+ def notes?
+ note && note.details.present?
+ end
+
def moderated?
state.in?(MODERATED_STATES)
end
diff --git a/app/views/admin/admin/_petition_action_departments.html.erb b/app/views/admin/admin/_petition_action_departments.html.erb
index 877679d1c..f0faff238 100644
--- a/app/views/admin/admin/_petition_action_departments.html.erb
+++ b/app/views/admin/admin/_petition_action_departments.html.erb
@@ -1,7 +1,5 @@
<% if @petition.is_a?(::Archived::Petition) %>
- <%= link_to 'Departments', admin_archived_petition_departments_path(@petition), class: 'petition-action-heading' %>
-<% elsif @petition.departments? %>
- <%= link_to 'Departments', admin_petition_departments_path(@petition), class: 'petition-action-heading present' %>
+ <%= link_to 'Departments', admin_archived_petition_departments_path(@petition), class: class_names('petition-action-heading', present: @petition.departments?) %>
<% else %>
- <%= link_to 'Departments', admin_petition_departments_path(@petition), class: 'petition-action-heading' %>
+ <%= link_to 'Departments', admin_petition_departments_path(@petition), class: class_names('petition-action-heading', present: @petition.departments?) %>
<% end %>
diff --git a/app/views/admin/admin/_petition_action_notes.html.erb b/app/views/admin/admin/_petition_action_notes.html.erb
index 5ae6e850f..b47591626 100644
--- a/app/views/admin/admin/_petition_action_notes.html.erb
+++ b/app/views/admin/admin/_petition_action_notes.html.erb
@@ -1,7 +1,5 @@
<% if @petition.is_a?(::Archived::Petition) %>
- <%= link_to 'Notes', admin_archived_petition_notes_path(@petition), class: 'petition-action-heading' %>
-<% elsif @petition.notes? %>
- <%= link_to 'Notes', admin_petition_notes_path(@petition), class: 'petition-action-heading present' %>
+ <%= link_to 'Notes', admin_archived_petition_notes_path(@petition), class: class_names('petition-action-heading', present: @petition.notes?) %>
<% else %>
- <%= link_to 'Notes', admin_petition_notes_path(@petition), class: 'petition-action-heading' %>
+ <%= link_to 'Notes', admin_petition_notes_path(@petition), class: class_names('petition-action-heading', present: @petition.notes?) %>
<% end %>
diff --git a/app/views/admin/admin/_petition_action_tags.html.erb b/app/views/admin/admin/_petition_action_tags.html.erb
index e80114448..65390ee4a 100644
--- a/app/views/admin/admin/_petition_action_tags.html.erb
+++ b/app/views/admin/admin/_petition_action_tags.html.erb
@@ -1,7 +1,5 @@
<% if @petition.is_a?(::Archived::Petition) %>
- <%= link_to 'Tags', admin_archived_petition_tags_path(@petition), class: 'petition-action-heading' %>
-<% elsif @petition.tags? %>
- <%= link_to 'Tags', admin_petition_tags_path(@petition), class: 'petition-action-heading present' %>
+ <%= link_to 'Tags', admin_archived_petition_tags_path(@petition), class: class_names('petition-action-heading', present: @petition.tags?) %>
<% else %>
- <%= link_to 'Tags', admin_petition_tags_path(@petition), class: 'petition-action-heading' %>
+ <%= link_to 'Tags', admin_petition_tags_path(@petition), class: class_names('petition-action-heading', present: @petition.tags?) %>
<% end %>
diff --git a/app/views/admin/admin/_petition_action_topics.html.erb b/app/views/admin/admin/_petition_action_topics.html.erb
index 501185b38..7f1a671ca 100644
--- a/app/views/admin/admin/_petition_action_topics.html.erb
+++ b/app/views/admin/admin/_petition_action_topics.html.erb
@@ -1,7 +1,5 @@
<% if @petition.is_a?(::Archived::Petition) %>
- <%= link_to 'Topics', admin_archived_petition_topics_path(@petition), class: 'petition-action-heading' %>
-<% elsif @petition.topics? %>
- <%= link_to 'Topics', admin_petition_topics_path(@petition), class: 'petition-action-heading present' %>
+ <%= link_to 'Topics', admin_archived_petition_topics_path(@petition), class: class_names('petition-action-heading', present: @petition.topics?) %>
<% else %>
- <%= link_to 'Topics', admin_petition_topics_path(@petition), class: 'petition-action-heading' %>
+ <%= link_to 'Topics', admin_petition_topics_path(@petition), class: class_names('petition-action-heading', present: @petition.topics?) %>
<% end %>
diff --git a/app/views/admin/archived/notes/_petition_action_notes.html.erb b/app/views/admin/archived/notes/_petition_action_notes.html.erb
index 63aeffde0..5cf9d5ea9 100644
--- a/app/views/admin/archived/notes/_petition_action_notes.html.erb
+++ b/app/views/admin/archived/notes/_petition_action_notes.html.erb
@@ -2,11 +2,19 @@
<%= form_row :for => [f.object, :admin_notes] do %>
<%= f.label :details, 'Notes', class: 'form-label petition-action-heading' %>
<%= error_messages_for_field f.object, :admin_notes %>
- <%= f.text_area :details, tabindex: increment, rows: 10, class: 'form-control' %>
+ <%= f.text_area :details, tabindex: increment, data: { autosave: true }, rows: 10, class: 'form-control' %>
<% end %>
- <%= f.submit 'Save notes', class: 'button' %>
- <%= link_to 'Cancel', admin_archived_petition_path(@petition), class: 'button-secondary' %>
+ <%= link_to 'Done', admin_archived_petition_path(petition), class: 'button-secondary js-only' %>
+
+
+ <%= f.submit 'Save notes', class: 'button' %>
+ <%= link_to 'Cancel', admin_archived_petition_path(@petition), class: 'button-secondary' %>
+
<% end %>
<%= render 'edit_lock' %>
+
+<% content_for :admin_scripts do %>
+ <%= javascript_include_tag "admin-actions-autosave" %>
+<% end %>
diff --git a/app/views/admin/archived/petition_departments/_petition_action_departments.html.erb b/app/views/admin/archived/petition_departments/_petition_action_departments.html.erb
index 781a1c465..42c6346b9 100644
--- a/app/views/admin/archived/petition_departments/_petition_action_departments.html.erb
+++ b/app/views/admin/archived/petition_departments/_petition_action_departments.html.erb
@@ -5,7 +5,7 @@
<% if Department.any? %>
<%= collection_check_boxes(:petition, :departments, Department.by_name, :id, :label) do |b| %>
- <%= b.check_box %>
+ <%= b.check_box data: { autosave: true } %>
<%= b.label title: b.object.name %>
<% end %>
@@ -15,8 +15,16 @@
<% end %>
<% end %>
- <%= f.submit 'Save departments', class: 'button' %>
- <%= link_to 'Cancel', admin_archived_petition_path(petition), class: 'button-secondary' %>
+ <%= link_to 'Done', admin_archived_petition_path(petition), class: 'button-secondary js-only' %>
+
+
+ <%= f.submit 'Save departments', class: 'button' %>
+ <%= link_to 'Cancel', admin_archived_petition_path(petition), class: 'button-secondary' %>
+
<% end %>
<%= render 'edit_lock' %>
+
+<% content_for :admin_scripts do %>
+ <%= javascript_include_tag "admin-actions-autosave" %>
+<% end %>
diff --git a/app/views/admin/archived/petition_tags/_petition_action_tags.html.erb b/app/views/admin/archived/petition_tags/_petition_action_tags.html.erb
index 77e243d74..47174173c 100644
--- a/app/views/admin/archived/petition_tags/_petition_action_tags.html.erb
+++ b/app/views/admin/archived/petition_tags/_petition_action_tags.html.erb
@@ -5,7 +5,7 @@
<% if Tag.any? %>
<%= collection_check_boxes(:petition, :tags, Tag.by_name, :id, :name) do |b| %>
- <%= b.check_box %>
+ <%= b.check_box data: { autosave: true } %>
<%= b.label title: b.object.description %>
<% end %>
@@ -20,8 +20,16 @@
<% end %>
<% end %>
- <%= f.submit 'Save tags', class: 'button' %>
- <%= link_to 'Cancel', admin_archived_petition_path(petition), class: 'button-secondary' %>
+ <%= link_to 'Done', admin_archived_petition_path(petition), class: 'button-secondary js-only' %>
+
+
+ <%= f.submit 'Save tags', class: 'button' %>
+ <%= link_to 'Cancel', admin_archived_petition_path(petition), class: 'button-secondary' %>
+
<% end %>
<%= render 'edit_lock' %>
+
+<% content_for :admin_scripts do %>
+ <%= javascript_include_tag "admin-actions-autosave" %>
+<% end %>
diff --git a/app/views/admin/archived/petition_topics/_petition_action_topics.html.erb b/app/views/admin/archived/petition_topics/_petition_action_topics.html.erb
index 2130d3721..a80ca3428 100644
--- a/app/views/admin/archived/petition_topics/_petition_action_topics.html.erb
+++ b/app/views/admin/archived/petition_topics/_petition_action_topics.html.erb
@@ -5,18 +5,26 @@
<% if Topic.any? %>
<%= collection_check_boxes(:petition, :topics, Topic.by_name, :id, :name) do |b| %>
- <%= b.check_box %>
+ <%= b.check_box data: { autosave: true } %>
<%= b.label title: b.object.name %>
<% end %>
<% else %>
<%= hidden_field_tag "petition[topics][]", "" %>
- No topics have been imported
+ No topics have been created
<% end %>
<% end %>
- <%= f.submit 'Save topics', class: 'button' %>
- <%= link_to 'Cancel', admin_archived_petition_path(petition), class: 'button-secondary' %>
+ <%= link_to 'Done', admin_archived_petition_path(petition), class: 'button-secondary js-only' %>
+
+
+ <%= f.submit 'Save topics', class: 'button' %>
+ <%= link_to 'Cancel', admin_archived_petition_path(petition), class: 'button-secondary' %>
+
<% end %>
<%= render 'edit_lock' %>
+
+<% content_for :admin_scripts do %>
+ <%= javascript_include_tag "admin-actions-autosave" %>
+<% end %>
diff --git a/app/views/admin/notes/_petition_action_notes.html.erb b/app/views/admin/notes/_petition_action_notes.html.erb
index adbb35abf..4d1f625a4 100644
--- a/app/views/admin/notes/_petition_action_notes.html.erb
+++ b/app/views/admin/notes/_petition_action_notes.html.erb
@@ -3,12 +3,20 @@
<%= form_row :for => [f.object, :admin_notes] do %>
<%= f.label :details, 'Notes', class: 'form-label petition-action-heading' %>
<%= error_messages_for_field f.object, :admin_notes %>
- <%= f.text_area :details, tabindex: increment, rows: 10, class: 'form-control', disabled: @petition.editing_disabled? %>
+ <%= f.text_area :details, tabindex: increment, rows: 10, class: 'form-control', data: { autosave: true }, disabled: @petition.editing_disabled? %>
<% end %>
- <%= f.submit 'Save notes', class: 'button', disabled: @petition.editing_disabled? %>
- <%= link_to 'Cancel', admin_petition_path(@petition), class: 'button-secondary' %>
+ <%= link_to 'Done', admin_petition_path(petition), class: 'button-secondary js-only' %>
+
+
+ <%= f.submit 'Save notes', class: 'button', disabled: @petition.editing_disabled? %>
+ <%= link_to 'Cancel', admin_petition_path(@petition), class: 'button-secondary' %>
+
<% end -%>
-<%= render 'edit_lock' %>
\ No newline at end of file
+<%= render 'edit_lock' %>
+
+<% content_for :admin_scripts do %>
+ <%= javascript_include_tag "admin-actions-autosave" %>
+<% end %>
diff --git a/app/views/admin/petition_departments/_petition_action_departments.html.erb b/app/views/admin/petition_departments/_petition_action_departments.html.erb
index 56077e55c..7f076b920 100644
--- a/app/views/admin/petition_departments/_petition_action_departments.html.erb
+++ b/app/views/admin/petition_departments/_petition_action_departments.html.erb
@@ -5,7 +5,7 @@
<% if Department.any? %>
<%= collection_check_boxes(:petition, :departments, Department.by_name, :id, :label) do |b| %>
- <%= b.check_box disabled: @petition.editing_disabled? %>
+ <%= b.check_box disabled: @petition.editing_disabled?, data: { autosave: true } %>
<%= b.label title: b.object.name %>
<% end %>
@@ -14,8 +14,17 @@
No departments have been imported
<% end %>
<% end %>
- <%= f.submit 'Save departments', class: 'button', disabled: @petition.editing_disabled? %>
- <%= link_to 'Cancel', admin_petition_path(petition), class: 'button-secondary' %>
+
+ <%= link_to 'Done', admin_petition_path(petition), class: 'button-secondary js-only' %>
+
+
+ <%= f.submit 'Save departments', class: 'button', disabled: @petition.editing_disabled? %>
+ <%= link_to 'Cancel', admin_petition_path(petition), class: 'button-secondary' %>
+
<% end %>
<%= render 'edit_lock' %>
+
+<% content_for :admin_scripts do %>
+ <%= javascript_include_tag "admin-actions-autosave" %>
+<% end %>
diff --git a/app/views/admin/petition_tags/_petition_action_tags.html.erb b/app/views/admin/petition_tags/_petition_action_tags.html.erb
index 1fbb32024..605380f17 100644
--- a/app/views/admin/petition_tags/_petition_action_tags.html.erb
+++ b/app/views/admin/petition_tags/_petition_action_tags.html.erb
@@ -5,7 +5,7 @@
<% if Tag.any? %>
<%= collection_check_boxes(:petition, :tags, Tag.by_name, :id, :name) do |b| %>
- <%= b.check_box disabled: @petition.editing_disabled? %>
+ <%= b.check_box disabled: @petition.editing_disabled?, data: { autosave: true } %>
<%= b.label title: b.object.description %>
<% end %>
@@ -19,8 +19,17 @@
<% end %>
<% end %>
- <%= f.submit 'Save tags', class: 'button', disabled: @petition.editing_disabled? %>
- <%= link_to 'Cancel', admin_petition_path(petition), class: 'button-secondary' %>
+
+ <%= link_to 'Done', admin_petition_path(petition), class: 'button-secondary js-only' %>
+
+
+ <%= f.submit 'Save tags', class: 'button', disabled: @petition.editing_disabled? %>
+ <%= link_to 'Cancel', admin_petition_path(petition), class: 'button-secondary' %>
+
<% end %>
<%= render 'edit_lock' %>
+
+<% content_for :admin_scripts do %>
+ <%= javascript_include_tag "admin-actions-autosave" %>
+<% end %>
diff --git a/app/views/admin/petition_topics/_petition_action_topics.html.erb b/app/views/admin/petition_topics/_petition_action_topics.html.erb
index 50cc96d5e..03d580802 100644
--- a/app/views/admin/petition_topics/_petition_action_topics.html.erb
+++ b/app/views/admin/petition_topics/_petition_action_topics.html.erb
@@ -5,7 +5,7 @@
<% if Topic.any? %>
<%= collection_check_boxes(:petition, :topics, Topic.by_name, :id, :name) do |b| %>
- <%= b.check_box disabled: @petition.editing_disabled? %>
+ <%= b.check_box disabled: @petition.editing_disabled?, data: { autosave: true } %>
<%= b.label title: b.object.name %>
<% end %>
@@ -14,8 +14,17 @@
No topics have been created
<% end %>
<% end %>
- <%= f.submit 'Save topics', class: 'button', disabled: @petition.editing_disabled? %>
- <%= link_to 'Cancel', admin_petition_path(petition), class: 'button-secondary' %>
+
+ <%= link_to 'Done', admin_petition_path(petition), class: 'button-secondary js-only' %>
+
+
+ <%= f.submit 'Save topics', class: 'button', disabled: @petition.editing_disabled? %>
+ <%= link_to 'Cancel', admin_petition_path(petition), class: 'button-secondary' %>
+
<% end %>
<%= render 'edit_lock' %>
+
+<% content_for :admin_scripts do %>
+ <%= javascript_include_tag "admin-actions-autosave" %>
+<% end %>
diff --git a/app/views/layouts/admin.html.erb b/app/views/layouts/admin.html.erb
index ddc4dda4c..879587028 100644
--- a/app/views/layouts/admin.html.erb
+++ b/app/views/layouts/admin.html.erb
@@ -4,6 +4,7 @@
<%= page_title %>
<%= stylesheet_link_tag 'admin' %>
<%= javascript_include_tag "admin" %>
+ <%= yield :admin_scripts %>
<%= csrf_meta_tag %>
<%= yield :js %>
@@ -12,6 +13,14 @@
+
+
+
+
<%= render '/admin/shared/header' %>
<%= render '/admin/shared/messages' %>
diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb
index 1489d2860..4314cf823 100644
--- a/config/initializers/assets.rb
+++ b/config/initializers/assets.rb
@@ -16,6 +16,7 @@
delayed/web/application.css
ie.js
admin.js
+ admin-actions-autosave.js
character-counter.js
auto-updater.js
details.js
diff --git a/features/admin/moderator_tags_a_petition.feature b/features/admin/moderator_tags_a_petition.feature
index fb2d6003c..bb72dc820 100644
--- a/features/admin/moderator_tags_a_petition.feature
+++ b/features/admin/moderator_tags_a_petition.feature
@@ -54,3 +54,18 @@ Feature: A moderator user updates records notes
And I should see "Petition has been successfully updated"
When I follow "Tags"
Then the "DWP" checkbox should not be checked
+
+ @javascript
+ Scenario: Adding tags to an open petition
+ Given an open petition exists with action: "Solidarity with the Unions"
+ And a tag exists with name: "DWP"
+ When I am on the admin all petitions page
+ And I follow "Solidarity with the Unions"
+ Then I leave the form alone for 1000ms
+ And I follow "Tags"
+ Then the "DWP" JS enabled govuk style checkbox should not be checked
+ When I check "DWP"
+ Then I leave the form alone for 1000ms
+ And I wait for the petition tags to save
+ Then I reload the page
+ Then the "DWP" JS enabled govuk style checkbox should be checked
diff --git a/features/admin/notes.feature b/features/admin/notes.feature
index a2215c989..2a1868433 100644
--- a/features/admin/notes.feature
+++ b/features/admin/notes.feature
@@ -20,11 +20,26 @@ Feature: A moderator user updates records notes
And I follow "Notes"
Then I should see "I think we can debate this, will check with unions select committee first"
+ @javascript
+ Scenario: Adding notes to an open petition as you type
+ Given an open petition exists with action: "Solidarity with the Unions"
+ When I am on the admin all petitions page
+ And I follow "Solidarity with the Unions"
+ And I follow "Notes"
+ Then I should see a "Notes" textarea field
+ And the markup should be valid
+ When I fill in "Notes" with "I am just mulling this over"
+ And I stop typing for 1000ms
+ And I wait for the petition notes to save
+ Then I reload the page
+ Then I should see "I am just mulling this over"
+
Scenario: Adding notes to an in moderation petition
Given an sponsored petition exists with action: "Solidarity with the Unions"
When I am on the admin all petitions page
And I follow "Solidarity with the Unions"
And I follow "Notes"
+
Then I should see a "Notes" textarea field
And the markup should be valid
When I fill in "Notes" with "I think we can debate this, will check with unions select committee first"
diff --git a/features/step_definitions/moderator_tags_a_petition.rb b/features/step_definitions/moderator_tags_a_petition.rb
new file mode 100644
index 000000000..4bf091057
--- /dev/null
+++ b/features/step_definitions/moderator_tags_a_petition.rb
@@ -0,0 +1,28 @@
+When(/^I leave the form alone for (\d+)ms$/) do |ms|
+ page.find('//body').click
+ sleep(ms.to_f / 1000)
+end
+
+Then(/^I wait for the petition tags to save$/) do
+ Timeout.timeout(Capybara.default_max_wait_time) do
+ loop until finished_ajax_requests?
+ end
+end
+
+Then /^the "([^"]*)" JS enabled govuk style checkbox(?: within "([^"]*)")? should not be checked$/ do |label, selector|
+ with_scope(selector) do
+ field_checked = find_field(label, visible: false)['checked']
+ expect(field_checked).to be_falsey
+ end
+end
+
+Then /^the "([^"]*)" JS enabled govuk style checkbox(?: within "([^"]*)")? should be checked$/ do |label, selector|
+ with_scope(selector) do
+ field_checked = find_field(label, visible: false)['checked']
+ expect(field_checked).to be_truthy
+ end
+end
+
+def finished_ajax_requests?
+ !page.find('//body')[:class].include?('ajax-active')
+end
diff --git a/features/step_definitions/notes_steps.rb b/features/step_definitions/notes_steps.rb
new file mode 100644
index 000000000..26783e8ef
--- /dev/null
+++ b/features/step_definitions/notes_steps.rb
@@ -0,0 +1,14 @@
+When(/^I stop typing for (\d+)ms$/) do |ms|
+ page.find('//body').click
+ sleep(ms.to_f / 1000)
+end
+
+Then(/^I wait for the petition notes to save$/) do
+ Timeout.timeout(Capybara.default_max_wait_time) do
+ loop until finished_ajax_requests?
+ end
+end
+
+def finished_ajax_requests?
+ !page.find('//body')[:class].include?('ajax-active')
+end
diff --git a/features/step_definitions/reload_page.rb b/features/step_definitions/reload_page.rb
new file mode 100644
index 000000000..1f6d7119f
--- /dev/null
+++ b/features/step_definitions/reload_page.rb
@@ -0,0 +1,3 @@
+Then(/^I reload the page$/) do
+ visit current_url
+end