From ef36e1f588d132c987022f07587cc2fc96a699be Mon Sep 17 00:00:00 2001 From: Nolwenn LAVIELLE Date: Fri, 14 Feb 2020 18:18:59 +0100 Subject: [PATCH] =?UTF-8?q?D=C3=A9but=20tableau,=20formulaire=20et=20affic?= =?UTF-8?q?hage?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Gemfile.lock | 16 +- Guardfile | 76 +++ app/assets/javascripts/application.js | 1 + app/assets/javascripts/jquery.tabledit.js | 612 ++++++++++++++++++++++ app/assets/javascripts/livres.coffee | 34 ++ app/assets/stylesheets/_mixin.sass | 3 + app/assets/stylesheets/application.css | 15 - app/assets/stylesheets/application.sass | 7 + app/controllers/livres_controller.rb | 49 ++ app/views/layouts/application.html.erb | 25 +- app/views/livres/_form.html.erb | 33 ++ app/views/livres/edit.html.erb | 3 + app/views/livres/index.html.erb | 10 +- app/views/livres/new.html.erb | 3 + config/routes.rb | 2 + 15 files changed, 861 insertions(+), 28 deletions(-) create mode 100644 Guardfile create mode 100644 app/assets/javascripts/jquery.tabledit.js create mode 100644 app/assets/stylesheets/_mixin.sass delete mode 100644 app/assets/stylesheets/application.css create mode 100644 app/assets/stylesheets/application.sass create mode 100644 app/views/livres/_form.html.erb create mode 100644 app/views/livres/edit.html.erb create mode 100644 app/views/livres/new.html.erb diff --git a/Gemfile.lock b/Gemfile.lock index ba9bd0f..77aac66 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -78,7 +78,7 @@ GEM coffee-script-source execjs coffee-script-source (1.12.2) - concurrent-ruby (1.1.5) + concurrent-ruby (1.1.6) crass (1.0.6) em-websocket (0.5.1) eventmachine (>= 0.12.9) @@ -111,9 +111,9 @@ GEM http_parser.rb (0.6.0) i18n (1.8.2) concurrent-ruby (~> 1.0) - io-like (0.3.0) - jbuilder (2.9.1) - activesupport (>= 4.2.0) + io-like (0.3.1) + jbuilder (2.10.0) + activesupport (>= 5.0.0) jquery-rails (4.3.5) rails-dom-testing (>= 1, < 3) railties (>= 4.2.0) @@ -127,7 +127,7 @@ GEM loofah (2.4.0) crass (~> 1.0.2) nokogiri (>= 1.5.9) - lumberjack (1.2.1) + lumberjack (1.2.4) mail (2.7.1) mini_mime (>= 0.1.1) marcel (0.3.3) @@ -137,11 +137,11 @@ GEM mini_mime (1.0.2) mini_portile2 (2.4.0) minitest (5.14.0) - msgpack (1.3.1) + msgpack (1.3.3) multi_json (1.14.1) nenv (0.3.0) nio4r (2.5.2) - nokogiri (1.10.7) + nokogiri (1.10.8) mini_portile2 (~> 2.4.0) notiffany (0.1.3) nenv (~> 0.1) @@ -152,7 +152,7 @@ GEM method_source (~> 0.9.0) public_suffix (4.0.3) puma (3.12.2) - rack (2.1.2) + rack (2.2.2) rack-livereload (0.3.17) rack rack-test (1.1.0) diff --git a/Guardfile b/Guardfile new file mode 100644 index 0000000..fca12fd --- /dev/null +++ b/Guardfile @@ -0,0 +1,76 @@ +# A sample Guardfile +# More info at https://github.com/guard/guard#readme + +## Uncomment and set this to only include directories you want to watch +# directories %w(app lib config test spec features) \ +# .select{|d| Dir.exists?(d) ? d : UI.warning("Directory #{d} does not exist")} + +## Note: if you are using the `directories` clause above and you are not +## watching the project directory ('.'), then you will want to move +## the Guardfile to a watched dir and symlink it back, e.g. +# +# $ mkdir config +# $ mv Guardfile config/ +# $ ln -s config/Guardfile . +# +# and, you'll have to watch "config/Guardfile" instead of "Guardfile" + +guard 'livereload' do + extensions = { + css: :css, + scss: :css, + sass: :css, + js: :js, + coffee: :js, + html: :html, + png: :png, + gif: :gif, + jpg: :jpg, + jpeg: :jpeg, + # less: :less, # uncomment if you want LESS stylesheets done in browser + } + + rails_view_exts = %w(erb haml slim) + + # file types LiveReload may optimize refresh for + compiled_exts = extensions.values.uniq + watch(%r{public/.+\.(#{compiled_exts * '|'})}) + + extensions.each do |ext, type| + watch(%r{ + (?:app|vendor) + (?:/assets/\w+/(?[^.]+) # path+base without extension + (?\.#{ext})) # matching extension (must be first encountered) + (?:\.\w+|$) # other extensions + }x) do |m| + path = m[1] + "/assets/#{path}.#{type}" + end + end + + # file needing a full reload of the page anyway + watch(%r{app/views/.+\.(#{rails_view_exts * '|'})$}) + watch(%r{app/helpers/.+\.rb}) + watch(%r{config/locales/.+\.yml}) +end + +# Guard-Rails supports a lot options with default values: +# daemon: false # runs the server as a daemon. +# debugger: false # enable ruby-debug gem. +# environment: 'development' # changes server environment. +# force_run: false # kills any process that's holding the listen port before attempting to (re)start Rails. +# pid_file: 'tmp/pids/[RAILS_ENV].pid' # specify your pid_file. +# host: 'localhost' # server hostname. +# port: 3000 # server port number. +# root: '/spec/dummy' # Rails' root path. +# server: thin # webserver engine. +# start_on_start: true # will start the server when starting Guard. +# timeout: 30 # waits untill restarting the Rails server, in seconds. +# zeus_plan: server # custom plan in zeus, only works with `zeus: true`. +# zeus: false # enables zeus gem. +# CLI: 'rails server' # customizes runner command. Omits all options except `pid_file`! + +guard 'rails' do + watch('Gemfile.lock') + watch(%r{^(config|lib)/.*}) +end diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 82e6f0f..5d993fd 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -13,4 +13,5 @@ //= require rails-ujs //= require activestorage //= require turbolinks +//= require jquery.tabledit //= require_tree . diff --git a/app/assets/javascripts/jquery.tabledit.js b/app/assets/javascripts/jquery.tabledit.js new file mode 100644 index 0000000..21163e1 --- /dev/null +++ b/app/assets/javascripts/jquery.tabledit.js @@ -0,0 +1,612 @@ +/*! + * Tabledit v1.2.3 (https://github.com/markcell/jQuery-Tabledit) + * Copyright (c) 2015 Celso Marques + * Licensed under MIT (https://github.com/markcell/jQuery-Tabledit/blob/master/LICENSE) + */ + +/** + * @description Inline editor for HTML tables compatible with Bootstrap + * @version 1.2.3 + * @author Celso Marques + */ + +if (typeof jQuery === 'undefined') { + throw new Error('Tabledit requires jQuery library.'); +} + +(function($) { + 'use strict'; + + $.fn.Tabledit = function(options) { + if (!this.is('table')) { + throw new Error('Tabledit only works when applied to a table.'); + } + + var $table = this; + + var defaults = { + url: window.location.href, + inputClass: 'form-control input-sm', + toolbarClass: 'btn-toolbar', + groupClass: 'btn-group btn-group-sm', + dangerClass: 'danger', + warningClass: 'warning', + mutedClass: 'text-muted', + eventType: 'click', + rowIdentifier: 'id', + hideIdentifier: false, + autoFocus: true, + editButton: true, + deleteButton: true, + saveButton: true, + restoreButton: true, + buttons: { + edit: { + class: 'btn btn-sm btn-default', + html: '', + action: 'edit' + }, + delete: { + class: 'btn btn-sm btn-default', + html: '', + action: 'delete' + }, + save: { + class: 'btn btn-sm btn-success', + html: 'Save' + }, + restore: { + class: 'btn btn-sm btn-warning', + html: 'Restore', + action: 'restore' + }, + confirm: { + class: 'btn btn-sm btn-danger', + html: 'Confirm' + } + }, + onDraw: function() { return; }, + onSuccess: function() { return; }, + onFail: function() { return; }, + onAlways: function() { return; }, + onAjax: function() { return; } + }; + + var settings = $.extend(true, defaults, options); + + var $lastEditedRow = 'undefined'; + var $lastDeletedRow = 'undefined'; + var $lastRestoredRow = 'undefined'; + + /** + * Draw Tabledit structure (identifier column, editable columns, toolbar column). + * + * @type {object} + */ + var Draw = { + columns: { + identifier: function() { + // Hide identifier column. + if (settings.hideIdentifier) { + $table.find('th:nth-child(' + parseInt(settings.columns.identifier[0]) + 1 + '), tbody td:nth-child(' + parseInt(settings.columns.identifier[0]) + 1 + ')').hide(); + } + + var $td = $table.find('tbody td:nth-child(' + (parseInt(settings.columns.identifier[0]) + 1) + ')'); + + $td.each(function() { + // Create hidden input with row identifier. + var span = '' + $(this).text() + ''; + var input = ''; + + // Add elements to table cell. + $(this).html(span + input); + + // Add attribute "id" to table row. + $(this).parent('tr').attr(settings.rowIdentifier, $(this).text()); + }); + }, + editable: function() { + for (var i = 0; i < settings.columns.editable.length; i++) { + var $td = $table.find('tbody td:nth-child(' + (parseInt(settings.columns.editable[i][0]) + 1) + ')'); + + $td.each(function() { + // Get text of this cell. + var text = $(this).text(); + + // Add pointer as cursor. + if (!settings.editButton) { + $(this).css('cursor', 'pointer'); + } + + // Create span element. + var span = '' + text + ''; + + // Check if exists the third parameter of editable array. + if (typeof settings.columns.editable[i][2] !== 'undefined') { + // Create select element. + var input = ''; + } else { + // Create text input element. + var input = ''; + } + + // Add elements and class "view" to table cell. + $(this).html(span + input); + $(this).addClass('tabledit-view-mode'); + }); + } + }, + toolbar: function() { + if (settings.editButton || settings.deleteButton) { + var editButton = ''; + var deleteButton = ''; + var saveButton = ''; + var restoreButton = ''; + var confirmButton = ''; + + // Add toolbar column header if not exists. + if ($table.find('th.tabledit-toolbar-column').length === 0) { + $table.find('tr:first').append(''); + } + + // Create edit button. + if (settings.editButton) { + editButton = ''; + } + + // Create delete button. + if (settings.deleteButton) { + deleteButton = ''; + confirmButton = ''; + } + + // Create save button. + if (settings.editButton && settings.saveButton) { + saveButton = ''; + } + + // Create restore button. + if (settings.deleteButton && settings.restoreButton) { + restoreButton = ''; + } + + var toolbar = '
\n\ +
' + editButton + deleteButton + '
\n\ + ' + saveButton + '\n\ + ' + confirmButton + '\n\ + ' + restoreButton + '\n\ +
'; + + // Add toolbar column cells. + $table.find('tbody>tr').append('' + toolbar + ''); + } + } + } + }; + + /** + * Change to view mode or edit mode with table td element as parameter. + * + * @type object + */ + var Mode = { + view: function(td) { + // Get table row. + var $tr = $(td).parent('tr'); + // Disable identifier. + $(td).parent('tr').find('.tabledit-input.tabledit-identifier').prop('disabled', true); + // Hide and disable input element. + $(td).find('.tabledit-input').blur().hide().prop('disabled', true); + // Show span element. + $(td).find('.tabledit-span').show(); + // Add "view" class and remove "edit" class in td element. + $(td).addClass('tabledit-view-mode').removeClass('tabledit-edit-mode'); + // Update toolbar buttons. + if (settings.editButton) { + $tr.find('button.tabledit-save-button').hide(); + $tr.find('button.tabledit-edit-button').removeClass('active').blur(); + } + }, + edit: function(td) { + Delete.reset(td); + // Get table row. + var $tr = $(td).parent('tr'); + // Enable identifier. + $tr.find('.tabledit-input.tabledit-identifier').prop('disabled', false); + // Hide span element. + $(td).find('.tabledit-span').hide(); + // Get input element. + var $input = $(td).find('.tabledit-input'); + // Enable and show input element. + $input.prop('disabled', false).show(); + // Focus on input element. + if (settings.autoFocus) { + $input.focus(); + } + // Add "edit" class and remove "view" class in td element. + $(td).addClass('tabledit-edit-mode').removeClass('tabledit-view-mode'); + // Update toolbar buttons. + if (settings.editButton) { + $tr.find('button.tabledit-edit-button').addClass('active'); + $tr.find('button.tabledit-save-button').show(); + } + } + }; + + /** + * Available actions for edit function, with table td element as parameter or set of td elements. + * + * @type object + */ + var Edit = { + reset: function(td) { + $(td).each(function() { + // Get input element. + var $input = $(this).find('.tabledit-input'); + // Get span text. + var text = $(this).find('.tabledit-span').text(); + // Set input/select value with span text. + if ($input.is('select')) { + $input.find('option').filter(function() { + return $.trim($(this).text()) === text; + }).attr('selected', true); + } else { + $input.val(text); + } + // Change to view mode. + Mode.view(this); + }); + }, + submit: function(td) { + // Send AJAX request to server. + var ajaxResult = ajax(settings.buttons.edit.action); + + if (ajaxResult === false) { + return; + } + + $(td).each(function() { + // Get input element. + var $input = $(this).find('.tabledit-input'); + // Set span text with input/select new value. + if ($input.is('select')) { + $(this).find('.tabledit-span').text($input.find('option:selected').text()); + } else { + $(this).find('.tabledit-span').text($input.val()); + } + // Change to view mode. + Mode.view(this); + }); + + // Set last edited column and row. + $lastEditedRow = $(td).parent('tr'); + } + }; + + /** + * Available actions for delete function, with button as parameter. + * + * @type object + */ + var Delete = { + reset: function(td) { + // Reset delete button to initial status. + $table.find('.tabledit-confirm-button').hide(); + // Remove "active" class in delete button. + $table.find('.tabledit-delete-button').removeClass('active').blur(); + }, + submit: function(td) { + Delete.reset(td); + // Enable identifier hidden input. + $(td).parent('tr').find('input.tabledit-identifier').attr('disabled', false); + // Send AJAX request to server. + var ajaxResult = ajax(settings.buttons.delete.action); + // Disable identifier hidden input. + $(td).parents('tr').find('input.tabledit-identifier').attr('disabled', true); + + if (ajaxResult === false) { + return; + } + + // Add class "deleted" to row. + $(td).parent('tr').addClass('tabledit-deleted-row'); + // Hide table row. + $(td).parent('tr').addClass(settings.mutedClass).find('.tabledit-toolbar button:not(.tabledit-restore-button)').attr('disabled', true); + // Show restore button. + $(td).find('.tabledit-restore-button').show(); + // Set last deleted row. + $lastDeletedRow = $(td).parent('tr'); + }, + confirm: function(td) { + // Reset all cells in edit mode. + $table.find('td.tabledit-edit-mode').each(function() { + Edit.reset(this); + }); + // Add "active" class in delete button. + $(td).find('.tabledit-delete-button').addClass('active'); + // Show confirm button. + $(td).find('.tabledit-confirm-button').show(); + }, + restore: function(td) { + // Enable identifier hidden input. + $(td).parent('tr').find('input.tabledit-identifier').attr('disabled', false); + // Send AJAX request to server. + var ajaxResult = ajax(settings.buttons.restore.action); + // Disable identifier hidden input. + $(td).parents('tr').find('input.tabledit-identifier').attr('disabled', true); + + if (ajaxResult === false) { + return; + } + + // Remove class "deleted" to row. + $(td).parent('tr').removeClass('tabledit-deleted-row'); + // Hide table row. + $(td).parent('tr').removeClass(settings.mutedClass).find('.tabledit-toolbar button').attr('disabled', false); + // Hide restore button. + $(td).find('.tabledit-restore-button').hide(); + // Set last restored row. + $lastRestoredRow = $(td).parent('tr'); + } + }; + + /** + * Send AJAX request to server. + * + * @param {string} action + */ + function ajax(action) + { + var serialize = $table.find('.tabledit-input').serialize() + + if (!serialize) { + return false; + } + + serialize += '&action=' + action; + + var result = settings.onAjax(action, serialize); + + if (result === false) { + return false; + } + + var jqXHR = $.post(settings.url, serialize, function(data, textStatus, jqXHR) { + if (action === settings.buttons.edit.action) { + $lastEditedRow.removeClass(settings.dangerClass).addClass(settings.warningClass); + setTimeout(function() { + //$lastEditedRow.removeClass(settings.warningClass); + $table.find('tr.' + settings.warningClass).removeClass(settings.warningClass); + }, 1400); + } + + settings.onSuccess(data, textStatus, jqXHR); + }, 'json'); + + jqXHR.fail(function(jqXHR, textStatus, errorThrown) { + if (action === settings.buttons.delete.action) { + $lastDeletedRow.removeClass(settings.mutedClass).addClass(settings.dangerClass); + $lastDeletedRow.find('.tabledit-toolbar button').attr('disabled', false); + $lastDeletedRow.find('.tabledit-toolbar .tabledit-restore-button').hide(); + } else if (action === settings.buttons.edit.action) { + $lastEditedRow.addClass(settings.dangerClass); + } + + settings.onFail(jqXHR, textStatus, errorThrown); + }); + + jqXHR.always(function() { + settings.onAlways(); + }); + + return jqXHR; + } + + Draw.columns.identifier(); + Draw.columns.editable(); + Draw.columns.toolbar(); + + settings.onDraw(); + + if (settings.deleteButton) { + /** + * Delete one row. + * + * @param {object} event + */ + $table.on('click', 'button.tabledit-delete-button', function(event) { + if (event.handled !== true) { + event.preventDefault(); + + // Get current state before reset to view mode. + var activated = $(this).hasClass('active'); + + var $td = $(this).parents('td'); + + Delete.reset($td); + + if (!activated) { + Delete.confirm($td); + } + + event.handled = true; + } + }); + + /** + * Delete one row (confirm). + * + * @param {object} event + */ + $table.on('click', 'button.tabledit-confirm-button', function(event) { + if (event.handled !== true) { + event.preventDefault(); + + var $td = $(this).parents('td'); + + Delete.submit($td); + + event.handled = true; + } + }); + } + + if (settings.restoreButton) { + /** + * Restore one row. + * + * @param {object} event + */ + $table.on('click', 'button.tabledit-restore-button', function(event) { + if (event.handled !== true) { + event.preventDefault(); + + Delete.restore($(this).parents('td')); + + event.handled = true; + } + }); + } + + if (settings.editButton) { + /** + * Activate edit mode on all columns. + * + * @param {object} event + */ + $table.on('click', 'button.tabledit-edit-button', function(event) { + if (event.handled !== true) { + event.preventDefault(); + + var $button = $(this); + + // Get current state before reset to view mode. + var activated = $button.hasClass('active'); + + // Change to view mode columns that are in edit mode. + Edit.reset($table.find('td.tabledit-edit-mode')); + + if (!activated) { + // Change to edit mode for all columns in reverse way. + $($button.parents('tr').find('td.tabledit-view-mode').get().reverse()).each(function() { + Mode.edit(this); + }); + } + + event.handled = true; + } + }); + + /** + * Save edited row. + * + * @param {object} event + */ + $table.on('click', 'button.tabledit-save-button', function(event) { + if (event.handled !== true) { + event.preventDefault(); + + // Submit and update all columns. + Edit.submit($(this).parents('tr').find('td.tabledit-edit-mode')); + + event.handled = true; + } + }); + } else { + /** + * Change to edit mode on table td element. + * + * @param {object} event + */ + $table.on(settings.eventType, 'tr:not(.tabledit-deleted-row) td.tabledit-view-mode', function(event) { + if (event.handled !== true) { + event.preventDefault(); + + // Reset all td's in edit mode. + Edit.reset($table.find('td.tabledit-edit-mode')); + + // Change to edit mode. + Mode.edit(this); + + event.handled = true; + } + }); + + /** + * Change event when input is a select element. + */ + $table.on('change', 'select.tabledit-input:visible', function(event) { + if (event.handled !== true) { + // Submit and update the column. + Edit.submit($(this).parent('td')); + + event.handled = true; + } + }); + + /** + * Click event on document element. + * + * @param {object} event + */ + $(document).on('click', function(event) { + var $editMode = $table.find('.tabledit-edit-mode'); + // Reset visible edit mode column. + if (!$editMode.is(event.target) && $editMode.has(event.target).length === 0) { + Edit.reset($table.find('.tabledit-input:visible').parent('td')); + } + }); + } + + /** + * Keyup event on table element. + * + * @param {object} event + */ + $table.on('keyup', function(event) { + // Get input element with focus or confirmation button. + var $input = $table.find('.tabledit-input:visible'); + var $button = $table.find('.tabledit-confirm-button'); + + if ($input.length > 0) { + var $td = $input.parents('td'); + } else if ($button.length > 0) { + var $td = $button.parents('td'); + } else { + return; + } + + // Key? + switch (event.keyCode) { + case 9: // Tab. + if (!settings.editButton) { + Edit.submit($td); + Mode.edit($td.closest('td').next()); + } + break; + case 13: // Enter. + Edit.submit($td); + break; + case 27: // Escape. + Edit.reset($td); + Delete.reset($td); + break; + } + }); + + return this; + }; +}(jQuery)); + diff --git a/app/assets/javascripts/livres.coffee b/app/assets/javascripts/livres.coffee index 24f83d1..5f1d18f 100644 --- a/app/assets/javascripts/livres.coffee +++ b/app/assets/javascripts/livres.coffee @@ -1,3 +1,37 @@ # 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://coffeescript.org/ + +$('#livres').Tabledit({ + url: '/livres/index', + editButton: true, + buttons: { + edit: { + class: 'btn btn-sm btn-default', + html: '', + action: 'edit' + }, + delete: { + class: 'btn btn-sm btn-default', + html: '', + action: 'delete' + }, + save: { + class: 'btn btn-sm btn-success', + html: 'Save' + }, + restore: { + class: 'btn btn-sm btn-warning', + html: 'Restore', + action: 'restore' + }, + confirm: { + class: 'btn btn-sm btn-danger', + html: 'Confirm' + } + }, + columns: { + identifier: [0, 'id'], + editable: [[1, 'titre'], [2, 'auteur'], [3, 'synopsis'], [4, 'style'], [5, 'isbn']] + } +}); diff --git a/app/assets/stylesheets/_mixin.sass b/app/assets/stylesheets/_mixin.sass new file mode 100644 index 0000000..15bdbc7 --- /dev/null +++ b/app/assets/stylesheets/_mixin.sass @@ -0,0 +1,3 @@ +$main-background: #AF6D36 + +$link-color: #AF6D36 diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css deleted file mode 100644 index d05ea0f..0000000 --- a/app/assets/stylesheets/application.css +++ /dev/null @@ -1,15 +0,0 @@ -/* - * This is a manifest file that'll be compiled into application.css, which will include all the files - * listed below. - * - * Any CSS and SCSS file within this directory, lib/assets/stylesheets, or any plugin's - * vendor/assets/stylesheets directory can be referenced here using a relative path. - * - * You're free to add application-wide styles to this file and they'll appear at the bottom of the - * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS - * files in this directory. Styles in this file should be added after the last require_* statement. - * It is generally better to create a new file per style scope. - * - *= require_tree . - *= require_self - */ diff --git a/app/assets/stylesheets/application.sass b/app/assets/stylesheets/application.sass new file mode 100644 index 0000000..0828ece --- /dev/null +++ b/app/assets/stylesheets/application.sass @@ -0,0 +1,7 @@ +/* + *= require_tree . + *= require_self + */ + +@import 'mixin' +@import 'bootstrap' diff --git a/app/controllers/livres_controller.rb b/app/controllers/livres_controller.rb index 0fcf46d..3327d6a 100644 --- a/app/controllers/livres_controller.rb +++ b/app/controllers/livres_controller.rb @@ -1,5 +1,54 @@ class LivresController < ApplicationController + before_action :set_livre, only: [:show, :edit, :update, :destroy] + def index @livres = Livre.all end + + def new + @livre = Livre.new + end + + def edit + @livre = Livre.find(params[:id]) + end + + def create + @livre = Livre.new(livre_params) + if @livre.save + redirect_to @livre, success: 'livre créé' + else + render new_livre_path + end + end + + def update + if @livre.update(livre_params) + redirect_to @livre, success: 'livre mis à jour' + else + render edit_livre_path(@livre) + end + end + + def destroy + @livre.destroy + redirect_to livres_url, success: 'livre supprimé' + end + + private + # Use callbacks to share common setup or constraints between actions. + def set_livre + @livre = Livre.find(params[:id]) + end + + # Never trust parameters from the scary internet, only allow the white list through. + def livre_params + params.require(:livre).permit( + :titre, + :auteur, + :synopsis, + :style, + :isbn + ) + end end diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 5f2c503..cbf8168 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -5,11 +5,30 @@ <%= csrf_meta_tags %> <%= csp_meta_tag %> - <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> - <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %> + <%= stylesheet_link_tag 'application', media: 'all' %> + <%= javascript_include_tag 'application' %> - <%= yield %> +
+ +
+ +
+ + <%= yield %> + +
diff --git a/app/views/livres/_form.html.erb b/app/views/livres/_form.html.erb new file mode 100644 index 0000000..ea84844 --- /dev/null +++ b/app/views/livres/_form.html.erb @@ -0,0 +1,33 @@ +<%= form_with(model: livre, local: true, remote: true, class: "mts") do |form| %> + <% if livre.errors.any? %> +
+
+ <%= pluralize(livre.errors.count, "error") %> prohibited this livre from being saved: +
+
+
    + <% livre.errors.full_messages.each do |message| %> +
  • <%= message %>
  • + <% end %> +
+
+
+ <% end %> + + <%= form.label :titre %> + <%= form.text_field :titre %> + + <%= form.label :auteur %> + <%= form.text_field :auteur %> + + <%= form.label :synopsis %> + <%= form.textarea_field :synopsis %> + + <%= form.label :style %> + <%= form.text_field :style %> + + <%= form.label :isbn %> + <%= form.text_field :isbn %> + + <%= form.submit :submit %> +<% end %> diff --git a/app/views/livres/edit.html.erb b/app/views/livres/edit.html.erb new file mode 100644 index 0000000..954c148 --- /dev/null +++ b/app/views/livres/edit.html.erb @@ -0,0 +1,3 @@ +

<%= @livre.titre %>

+ +<%= render 'form', livre: @livre %> diff --git a/app/views/livres/index.html.erb b/app/views/livres/index.html.erb index 77ef2f6..0384340 100644 --- a/app/views/livres/index.html.erb +++ b/app/views/livres/index.html.erb @@ -2,28 +2,34 @@ <% if @livres.size > 0 %> - - +
+ + + <% @livres.each do |livre| %> + + <% end %>
# Titre Auteur Synopsis Style ISBNAction
<%= livre.id %> <%= livre.titre %> <%= livre.auteur %> <%= livre.synopsis[0..120] %> <%= livre.style %> <%= livre.isbn %><%= link_to 'Edit', edit_livre_path(livre) %>
<% end %> + +<%= link_to 'Nouveau livre', new_livre_path %> diff --git a/app/views/livres/new.html.erb b/app/views/livres/new.html.erb new file mode 100644 index 0000000..096c132 --- /dev/null +++ b/app/views/livres/new.html.erb @@ -0,0 +1,3 @@ +

Nouveau livre

+ +<%= render 'form', livre: @livre %> diff --git a/config/routes.rb b/config/routes.rb index 70a5f0a..b479fc4 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,4 +1,6 @@ Rails.application.routes.draw do get 'livres/index' # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html + resources :livres + end