Skip to content

Commit

Permalink
Js shakapacker and Boostrap confirm (#140)
Browse files Browse the repository at this point in the history
* Manage js in app/javascript/app_views

* Pull most javascript from html to compile with webpacker

* Override default confirm dialog with a bootstrap modal

* Remove useless fields for confirm dialog
  • Loading branch information
relf committed Oct 31, 2022
1 parent 2b66de5 commit 2b4276d
Show file tree
Hide file tree
Showing 18 changed files with 312 additions and 224 deletions.
3 changes: 3 additions & 0 deletions app/assets/javascripts/application.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// Include jquery for inline scroipt using $
// does not work with shakapacker config

// = require jquery
// = require popper
// = require bootstrap
Expand Down
74 changes: 74 additions & 0 deletions app/javascript/application_views/analyses_index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import $ from 'jquery';

class AnalysesIndex {
constructor(relRoot, apiKey, userId) {
this.relRoot = relRoot;
this.apiKey = apiKey;
this.userId = userId;
}

start() {
const { relRoot, apiKey, userId } = this;
const SPINNER_TIMEOUT = 1500; // ms
function setAnalysesListSettings() {
const query = $(this).data('analyses-query');
const order = $(this).data('analyses-order');
let timeout;
$.ajax({
type: 'PATCH',
xhrFields: { withCredentials: true },
headers: { Authorization: `Token ${apiKey}` },
url: `${relRoot}/api/v1/users/${userId}`,
data: { user: { settings: { analyses_query: query, analyses_order: order } } },
beforeSend() {
timeout = setTimeout(() => {
$('.spinner').show();
}, SPINNER_TIMEOUT);
},
success() {
$.getScript(this.href, () => {
if (timeout) { clearTimeout(timeout); }
$('.spinner').hide();
});
},
});
}

$('input[data-analyses-query]').on('click', setAnalysesListSettings);
$('input[data-analyses-order]').on('click', setAnalysesListSettings);

let current_design_project_id = '<%= current_user.analyses_scope_design_project_id %>';

$('#designProjectScope').on('click', function (e) {
const design_project_id = this.value;
let timeout;
if (design_project_id !== current_design_project_id) {
$.ajax({
type: 'PATCH',
xhrFields: { withCredentials: true },
headers: { Authorization: `Token ${apiKey}` },
url: `${relRoot}/api/v1/users/${userId}`,
data: { user: { settings: { analyses_scope_design_project_id: design_project_id } } },
beforeSend() {
timeout = setTimeout(() => {
$('.spinner').show();
}, SPINNER_TIMEOUT);
},
success() {
$.getScript(this.href, () => {
if (timeout) { clearTimeout(timeout); console.log('CLEAR'); }
$('.spinner').hide();
});
},
}).always(() => {
current_design_project_id = design_project_id;
});
}
});

// hide spinner
$('.spinner').hide();
}
}

export default AnalysesIndex;
53 changes: 53 additions & 0 deletions app/javascript/application_views/operations_index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import $ from 'jquery';

class OperationsIndex {
constructor(relRoot) {
this.relRoot = relRoot;
}

start() {
const relativeUrlRoot = this.relRoot;
const opeEdit = {};
const $modal = $('#editModal');
const $input = $("input[name='operation[name]']");

$modal.on('show.bs.modal', (e) => {
opeEdit.invoker = $(e.relatedTarget);
opeEdit.id = opeEdit.invoker.data('ope-id');
opeEdit.name = opeEdit.invoker.data('ope-name');
opeEdit.apiKey = opeEdit.invoker.data('api-key');
$input.val(opeEdit.name);
$input.on('focus');
});

$('button[data-save="true"]').on(
'click',
() => {
const newName = $input.val();
$.ajax({
type: 'PATCH',
xhrFields: { withCredentials: true },
headers: { Authorization: `Token ${opeEdit.apiKey}` },
url: `${relativeUrlRoot}/api/v1/operations/${opeEdit.id}`,
data: { operation: { name: newName } },
success() {
$(`a[id=${opeEdit.id}]`).text(newName);
opeEdit.invoker.data('ope-name', newName);
$modal.modal('hide');
},
error(xhr) {
console.log(xhr.responseJSON.message);
$('#errorPlaceHolder').html(
`<div class="alert bg-warning" role="alert"><a href="#" data-dismiss="alert" class="close">×</a>${
xhr.responseJSON.message
}</div>`,
);
$modal.modal('hide');
},
});
},
);
}
}

export default OperationsIndex;
64 changes: 64 additions & 0 deletions app/javascript/application_views/optimizations_index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import $ from 'jquery';
import { Tooltip } from 'bootstrap';

class OptimizationsIndex {
start() {
$('#need_selected').hide();

// Initialize tooltips BS5
const tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'));
const tooltipList = tooltipTriggerList.map((triggerEl) => new Tooltip(triggerEl));

$('#selectAll').change(function () {
checked = this.checked;

$('.checkbox_child').map(function () {
$(this).prop('checked', checked);
});

$('#selectStatus').prop('checked', checked);
update_checkbox_count();
});

$('#selectStatus').change(function () {
checked = this.checked;
status = $('#status-select').val();

$('.checkbox_child').map(function () {
if (~$(this).attr('class').indexOf(status)) {
$(this).prop('checked', checked);
}
});
update_checkbox_count();
});

$('#status-select').change(() => {
$('#selectStatus').prop('checked', false);
});

$('.checkbox_child').change(() => { update_checkbox_count(); });

function update_checkbox_count() {
$('#display_checkbox_count').text(($('.checkbox_child:checked').length === 0) ? `0/${$('.checkbox_child').length}` : `${$('.checkbox_child:checked').length}/${$('.checkbox_child').length}`);

$('.checkbox_child').map(function () {
$(this).parent().parent().removeClass((this.checked) ? '' : 'table-primary')
.addClass((this.checked) ? 'table-primary' : '');
});

if ($('.checkbox_child:checked').length == $('.checkbox_child').length) {
$('#selectAll').prop('checked', true);
} else {
$('#selectAll').prop('checked', false);
}

if ($('.checkbox_child:checked').length > 0) {
$('#need_selected').show();
} else {
$('#need_selected').hide();
}
}
}
}

export default OptimizationsIndex;
31 changes: 31 additions & 0 deletions app/javascript/application_views/users_show.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import $ from 'jquery';

class UserShow {
constructor(relRoot, userId) {
this.relRoot = relRoot;
this.userId = userId;
}

start() {
const { relRoot, userId } = this;
$('#reset-api-key').on('click', () => {
const api_key = $('#user-api-key').text();
$.ajax({
type: 'PATCH',
xhrFields: {
withCredentials: true,
},
headers: {
Authorization: `Token ${api_key}`,
},
url: `${relRoot}/api/v1/users/${userId}/api_key`,
success() {
$.getScript(this.href);
return false;
},
});
});
}
}

export default UserShow;
34 changes: 34 additions & 0 deletions app/javascript/packs/application.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,37 @@
import Rails from '@rails/ujs';
import AnalysesIndex from '../application_views/analyses_index';
import OperationsIndex from '../application_views/operations_index';
import OptimizationsIndex from '../application_views/optimizations_index';
import UserShow from '../application_views/users_show';

// Views are used in corresponding views/**/*.html.erb files
// in document_ready section.
// Calling start() allow to attach js callbacks to DOM element
// specially for each views.
window.App = {
AnalysesIndex,
OperationsIndex,
OptimizationsIndex,
UserShow,
};

// Override default browser confirm dialog by bootstrap version
Rails.confirm = (message, element) => {
const $element = $(element);
const $dialog = $('#confirmModal');
const $content = $dialog.find('#modal-content');
const $ok = $dialog.find('#ok-button');
$content.text(message);
$ok.on('click', (event) => {
event.preventDefault();
$dialog.modal('hide');
const old = Rails.confirm;
Rails.confirm = () => true;
$element.get(0).click();
Rails.confirm = old;
});
$dialog.modal('show');
return false;
};

Rails.start();
10 changes: 4 additions & 6 deletions app/views/analyses/_analyses.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,11 @@
<% end %>
<% if policy(mda).destroy? %>
<%= link_to mda_path(mda), method: :delete, data: { title: 'Are you sure?',
confirm: "Remove #{mda.name} analysis?",
commit: 'Yes',
cancel: 'No, cancel' },
<%= link_to mda_path(mda), method: :delete,
data: { confirm: "Remove #{mda.name} analysis?" },
class: "btn btn-sm text-danger", title:"Delete" do %>
<i class="fas fa-times"></i>
<% end %>
<i class="fas fa-times"></i>
<% end %>
<% end %>
</td>
</tr>
Expand Down
65 changes: 2 additions & 63 deletions app/views/analyses/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -48,69 +48,8 @@
<div id="analyses"><%= render 'analyses' %></div>

<% content_for :document_ready do %>

<script>
let relRoot = "<%= Rails.application.config.action_controller.relative_url_root %>";
let SPINNER_TIMEOUT = 1500; //ms
function setAnalysesListSettings() {
let query = $(this).data("analyses-query");
let order = $(this).data("analyses-order");
let timeout;
$.ajax({
type: "PATCH",
xhrFields: { withCredentials: true },
headers: {'Authorization': 'Token <%= current_user.api_key%>'},
url: relRoot+'/api/v1/users/<%= current_user.id%>',
data: { user: { settings: { analyses_query: query, analyses_order: order } } },
beforeSend: function( xhr ) {
timeout = setTimeout(function() {
$(".spinner").show();
}, SPINNER_TIMEOUT);
},
success: function() {
$.getScript(this.href, function() {
if (timeout) { clearTimeout(timeout); }
$(".spinner").hide();
});
}
});
}

$("input[data-analyses-query]").on('click', setAnalysesListSettings);
$("input[data-analyses-order]").on('click', setAnalysesListSettings);

let current_design_project_id = "<%= current_user.analyses_scope_design_project_id %>";

$("#designProjectScope").on('click', function(e) {
let design_project_id = this.value;
let timeout;
if (design_project_id !== current_design_project_id) {
$.ajax({
type: "PATCH",
xhrFields: { withCredentials: true },
headers: {'Authorization': 'Token <%= current_user.api_key%>'},
url: relRoot+'/api/v1/users/<%= current_user.id%>',
data: {user: {settings: {analyses_scope_design_project_id: design_project_id}}},
beforeSend: function( xhr ) {
timeout = setTimeout(function() {
$(".spinner").show();
}, SPINNER_TIMEOUT);
},
success: function() {
$.getScript(this.href, function() {
if (timeout) { clearTimeout(timeout); console.log("CLEAR");}
$(".spinner").hide();
});
}
}).always(function() {
current_design_project_id = design_project_id;
});
}
});

// hide spinner
$(".spinner").hide();

</script>
let view = new App.AnalysesIndex(relRoot, "<%= current_user.api_key%>", "<%= current_user.id %>");
view.start();
<% end %>

8 changes: 3 additions & 5 deletions app/views/analyses/show.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,9 @@
<% end %>
<% end %>
<% if policy(@mda).destroy? %>
<%= button_to mda_path(@mda), method: :delete, data: { title: 'Are you sure?',
confirm: "Remove #{@mda.name} analysis?",
commit: 'Yes',
cancel: 'No, cancel' },
class: "btn ms-2", title:"Delete" do %>
<%= button_to mda_path(@mda), method: :delete,
data: { confirm: "Remove #{@mda.name} analysis?" },
class: "btn ms-2", title:"Delete" do %>
<span class="fa fa-times"></span>
Delete
<% end %>
Expand Down
6 changes: 2 additions & 4 deletions app/views/design_projects/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,8 @@
<% end %>
<% end %>
<% if policy(project).destroy? %>
<%= link_to design_project_path(project), method: :delete, data: { title: 'Are you sure?',
confirm: "Remove #{project.name} design project?",
commit: 'Yes',
cancel: 'No, cancel' },
<%= link_to design_project_path(project), method: :delete,
data: { confirm: "Remove #{project.name} design project?" },
class: "btn btn-sm text-danger", title:"Delete" do %>
<i class="fas fa-times"></i>
<% end %>
Expand Down
Loading

0 comments on commit 2b4276d

Please sign in to comment.