Mise à jour avec formulaire et AJAX dans les lignes du table

ajax
Nolwenn LAVIELLE 3 years ago
parent 1bc93f2c9c
commit 165b314d88
  1. 31
      .gitignore
  2. 1
      .ruby-version
  3. 2
      Gemfile
  4. 120
      Gemfile.lock
  5. 98
      app/assets/javascripts/livres.js
  6. 5
      app/controllers/livres_controller.rb
  7. BIN
      app/views/livres/.index.html.erb.swp
  8. 17
      app/views/livres/index.html.erb

31
.gitignore vendored

@ -0,0 +1,31 @@
# See https://help.github.com/articles/ignoring-files for more about ignoring files.
#
# If you find yourself ignoring temporary files generated by your text editor
# or operating system, you probably want to add a global ignore instead:
# git config --global core.excludesfile '~/.gitignore_global'
# Ignore bundler config.
/.bundle
# Ignore the default SQLite database.
/db/*.sqlite3
/db/*.sqlite3-journal
# Ignore all logfiles and tempfiles.
/log/*
/tmp/*
!/log/.keep
!/tmp/.keep
# Ignore uploaded files in development
/storage/*
!/storage/.keep
/node_modules
/yarn-error.log
/public/assets
.byebug_history
# Ignore master key for decrypting credentials and more.
/config/master.key

@ -0,0 +1 @@
2.6.3

@ -2,7 +2,7 @@ source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 5.2.4', '>= 5.2.4.1'
gem 'rails'
gem 'puma', '~> 3.11'
# Use SCSS for stylesheets
gem 'sass-rails', '~> 5.0'

@ -1,57 +1,70 @@
GEM
remote: https://rubygems.org/
specs:
actioncable (5.2.4.1)
actionpack (= 5.2.4.1)
actioncable (6.0.2.1)
actionpack (= 6.0.2.1)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
actionmailer (5.2.4.1)
actionpack (= 5.2.4.1)
actionview (= 5.2.4.1)
activejob (= 5.2.4.1)
actionmailbox (6.0.2.1)
actionpack (= 6.0.2.1)
activejob (= 6.0.2.1)
activerecord (= 6.0.2.1)
activestorage (= 6.0.2.1)
activesupport (= 6.0.2.1)
mail (>= 2.7.1)
actionmailer (6.0.2.1)
actionpack (= 6.0.2.1)
actionview (= 6.0.2.1)
activejob (= 6.0.2.1)
mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 2.0)
actionpack (5.2.4.1)
actionview (= 5.2.4.1)
activesupport (= 5.2.4.1)
actionpack (6.0.2.1)
actionview (= 6.0.2.1)
activesupport (= 6.0.2.1)
rack (~> 2.0, >= 2.0.8)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.2)
actionview (5.2.4.1)
activesupport (= 5.2.4.1)
rails-html-sanitizer (~> 1.0, >= 1.2.0)
actiontext (6.0.2.1)
actionpack (= 6.0.2.1)
activerecord (= 6.0.2.1)
activestorage (= 6.0.2.1)
activesupport (= 6.0.2.1)
nokogiri (>= 1.8.5)
actionview (6.0.2.1)
activesupport (= 6.0.2.1)
builder (~> 3.1)
erubi (~> 1.4)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.3)
activejob (5.2.4.1)
activesupport (= 5.2.4.1)
rails-html-sanitizer (~> 1.1, >= 1.2.0)
activejob (6.0.2.1)
activesupport (= 6.0.2.1)
globalid (>= 0.3.6)
activemodel (5.2.4.1)
activesupport (= 5.2.4.1)
activerecord (5.2.4.1)
activemodel (= 5.2.4.1)
activesupport (= 5.2.4.1)
arel (>= 9.0)
activestorage (5.2.4.1)
actionpack (= 5.2.4.1)
activerecord (= 5.2.4.1)
activemodel (6.0.2.1)
activesupport (= 6.0.2.1)
activerecord (6.0.2.1)
activemodel (= 6.0.2.1)
activesupport (= 6.0.2.1)
activestorage (6.0.2.1)
actionpack (= 6.0.2.1)
activejob (= 6.0.2.1)
activerecord (= 6.0.2.1)
marcel (~> 0.3.1)
activesupport (5.2.4.1)
activesupport (6.0.2.1)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2)
minitest (~> 5.1)
tzinfo (~> 1.1)
zeitwerk (~> 2.2)
addressable (2.7.0)
public_suffix (>= 2.0.2, < 5.0)
archive-zip (0.12.0)
io-like (~> 0.3.0)
arel (9.0.0)
autoprefixer-rails (9.7.4)
execjs
awesome_print (1.8.0)
bindex (0.8.1)
bootsnap (1.4.5)
bootsnap (1.4.6)
msgpack (~> 1.0)
bootstrap (4.3.1)
autoprefixer-rails (>= 9.1.0)
@ -144,7 +157,7 @@ GEM
multi_json (1.14.1)
nenv (0.3.0)
nio4r (2.5.2)
nokogiri (1.10.8)
nokogiri (1.10.9)
mini_portile2 (~> 2.4.0)
notiffany (0.1.3)
nenv (~> 0.1)
@ -154,45 +167,47 @@ GEM
coderay (~> 1.1.0)
method_source (~> 0.9.0)
public_suffix (4.0.3)
puma (3.12.2)
puma (3.12.4)
rack (2.2.2)
rack-livereload (0.3.17)
rack
rack-test (1.1.0)
rack (>= 1.0, < 3)
rails (5.2.4.1)
actioncable (= 5.2.4.1)
actionmailer (= 5.2.4.1)
actionpack (= 5.2.4.1)
actionview (= 5.2.4.1)
activejob (= 5.2.4.1)
activemodel (= 5.2.4.1)
activerecord (= 5.2.4.1)
activestorage (= 5.2.4.1)
activesupport (= 5.2.4.1)
rails (6.0.2.1)
actioncable (= 6.0.2.1)
actionmailbox (= 6.0.2.1)
actionmailer (= 6.0.2.1)
actionpack (= 6.0.2.1)
actiontext (= 6.0.2.1)
actionview (= 6.0.2.1)
activejob (= 6.0.2.1)
activemodel (= 6.0.2.1)
activerecord (= 6.0.2.1)
activestorage (= 6.0.2.1)
activesupport (= 6.0.2.1)
bundler (>= 1.3.0)
railties (= 5.2.4.1)
railties (= 6.0.2.1)
sprockets-rails (>= 2.0.0)
rails-dom-testing (2.0.3)
activesupport (>= 4.2.0)
nokogiri (>= 1.6)
rails-html-sanitizer (1.3.0)
loofah (~> 2.3)
railties (5.2.4.1)
actionpack (= 5.2.4.1)
activesupport (= 5.2.4.1)
railties (6.0.2.1)
actionpack (= 6.0.2.1)
activesupport (= 6.0.2.1)
method_source
rake (>= 0.8.7)
thor (>= 0.19.0, < 2.0)
thor (>= 0.20.3, < 2.0)
rake (13.0.1)
rb-fsevent (0.10.3)
rb-inotify (0.10.1)
ffi (~> 1.0)
regexp_parser (1.6.0)
regexp_parser (1.7.0)
rerun (0.13.0)
listen (~> 3.0)
ruby_dep (1.5.0)
rubyzip (2.2.0)
rubyzip (2.3.0)
sass (3.7.4)
sass-listen (~> 4.0.0)
sass-listen (4.0.0)
@ -238,16 +253,17 @@ GEM
thread_safe (~> 0.1)
uglifier (4.2.0)
execjs (>= 0.3.0, < 3)
web-console (3.7.0)
actionview (>= 5.0)
activemodel (>= 5.0)
web-console (4.0.1)
actionview (>= 6.0.0)
activemodel (>= 6.0.0)
bindex (>= 0.4.0)
railties (>= 5.0)
railties (>= 6.0.0)
websocket-driver (0.7.1)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.4)
xpath (3.2.0)
nokogiri (~> 1.8)
zeitwerk (2.3.0)
PLATFORMS
ruby
@ -269,7 +285,7 @@ DEPENDENCIES
listen (>= 3.0.5, < 3.2)
puma (~> 3.11)
rack-livereload
rails (~> 5.2.4, >= 5.2.4.1)
rails
rerun
sass-rails (~> 5.0)
selenium-webdriver
@ -282,4 +298,4 @@ DEPENDENCIES
web-console (>= 3.3.0)
BUNDLED WITH
1.17.2
2.1.4

@ -1,18 +1,105 @@
// supprime un livre basé sur son ID
function deleteLivre(id) {
fetch ('/livres/' + id, {
method: 'DELETE',
}).then(async (response) => {
const tr = document.querySelector('tr[data-id="' + id + '"]');
const attributes = {};
tr.querySelectorAll("td").forEach((td) => {
const name = td.dataset["name"];
const value = td.textContent;
attributes[name] = value;
});
let suppr = window.confirm('Êtes-vous sûr de vouloir supprimer le livre ' + attributes["titre"] + ' ?');
if (suppr) {
fetch ('/livres/' + id, {
method: 'DELETE',
}).then(async (response) => {
if (response.status === 200) {
tr.parentNode.removeChild(tr);
} else {
const error = livre["error"];
alert(error);
}
});
}
}
// modifie un livre basé sur son ID
function editLivre(id) {
const tr = document.querySelector('tr[data-id="' + id + '"]');
const attributes = {};
tr.querySelectorAll("td[data-name]").forEach((td) => {
const name = td.dataset["name"];
const value = td.textContent;
attributes[name] = value;
td.removeAttribute("data-name");
td.textContent = '';
let input = document.createElement("input");
input.setAttribute("data-name", name);
input.setAttribute("value", value);
td.append(input);
});
const btns = tr.querySelector('div.btn-group');
btns.querySelectorAll('a').forEach((a) => {
console.info(a);
if (a.dataset["action"] == "edit") {
a.setAttribute("data-action", "save");
a.removeAttribute("onclick");
a.setAttribute("onclick", "saveLivre("+id+")");
a.textContent = "Sauver";
}
if (a.dataset["action"] == "destroy") {
a.setAttribute("data-action", "cancel");
a.removeAttribute("onclick");
a.setAttribute("onclick", "cancel("+id+")");
a.textContent = "Annuler";
}
});
console.info(tr);
/*fetch ('/livres/' + id, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(attributes)
})*/
/*.then(async (response) => {
if (response.status === 200) {
let tr = document.querySelector('tr[data-id="' + id + '"]');
tr.parentNode.removeChild(tr);
} else {
const error = livre["error"];
alert(error);
}
})*/;
}
// annuler la modification d’un livre
function cancel(id) {
const tr = document.querySelector('tr[data-id="' + id + '"]');
const attributes = {};
tr.querySelectorAll("input[data-name]").forEach((input) => {
const name = input.dataset["name"];
const value = input.value;
const td = input.offsetParent;
td.setAttribute("data-name", name);
td.textContent = value;
});
const btns = tr.querySelector('div.btn-group');
btns.querySelectorAll('a').forEach((a) => {
if (a.dataset["action"] == "save") {
a.setAttribute("data-action", "edit");
a.removeAttribute("onclick");
a.setAttribute("onclick", "editLivre("+id+")");
a.textContent = "Modifier";
}
if (a.dataset["action"] == "cancel") {
a.setAttribute("data-action", "destroy");
a.removeAttribute("onclick");
a.setAttribute("onclick", "deleteLivre("+id+")");
a.textContent = "Supprimer";
}
});
}
// ajoute un livre
document.addEventListener('DOMContentLoaded', async function () {
const table = document.querySelector("table");
const tbody = table.querySelector("tbody");
@ -43,6 +130,7 @@ document.addEventListener('DOMContentLoaded', async function () {
tbody.insertBefore(tr, tbody.firstChild);
for (const name in attributes) {
const td = document.createElement("td");
td.setAttribute("data-name", name);
td.textContent = livre[name];
tr.appendChild(td);
}

@ -16,14 +16,14 @@ class LivresController < ApplicationController
def edit
end
def create
@livre = Livre.create! params.require(:livre).permit :titre, :auteur, :synopsis, :style, :isbn
render json: @livre
end
def update
render json: @livre
=begin
respond_to do |format|
if @livre.update(livre_params)
format.js
@ -34,6 +34,7 @@ class LivresController < ApplicationController
format.json { render json: @livre.errors, status: :unprocessable_entity }
end
end
=end
end
def destroy

@ -19,7 +19,7 @@
</td>
<% end %>
<td>
<a data-action="create" href="#">Ajouter</a>
<a class="btn btn-sm btn-dark" data-action="create" href="#">Ajouter</a>
</td>
</tr>
</thead>
@ -27,13 +27,16 @@
<tbody>
<% @livres.each do |livre| %>
<tr data-id="<%= livre.id %>">
<td><%= livre.titre %></td>
<td><%= livre.auteur %></td>
<td><%= livre.synopsis[0..120] %></td>
<td><%= livre.style %></td>
<td><%= livre.isbn %></td>
<td data-name="titre"><%= livre.titre %></td>
<td data-name="auteur"><%= livre.auteur %></td>
<td data-name="synopsis"><%= livre.synopsis[0..120] %></td>
<td data-name="style"><%= livre.style %></td>
<td data-name="isbn"><%= livre.isbn %></td>
<td>
<a data-action="destroy" href="#" onclick="deleteLivre(<%= livre.id %>)">Supprimer</a>
<div class="btn-group" role="group">
<a class="btn btn-sm btn-dark" data-action="edit" href="#" onclick="editLivre(<%= livre.id %>)">Modifier</a>
<a class="btn btn-sm btn-dark" data-action="destroy" href="#" onclick="deleteLivre(<%= livre.id %>)">Supprimer</a>
</div>
</td>
</tr>
<% end %>

Loading…
Cancel
Save