From a7ef724d359d61e046ad7afe92596376bae2bf8f Mon Sep 17 00:00:00 2001 From: huylc Date: Mon, 26 Aug 2019 16:54:38 +0700 Subject: [PATCH] 209: edit and destroy member --- app/assets/javascripts/manager/custom.js | 5 +- app/assets/stylesheets/manager/custom.scss | 25 +++++-- app/controllers/manager/admins_controller.rb | 51 ++++++++------- app/controllers/manager/members_controller.rb | 56 ++++++++++++++-- app/models/admin.rb | 1 + app/models/member.rb | 1 + app/models/user.rb | 27 +++++++- app/views/layouts/_flashmessages.html.slim | 2 + app/views/manager/admins/_admin.html.slim | 13 +++- app/views/manager/admins/create.js.slim | 4 +- app/views/manager/admins/index.html.slim | 4 +- app/views/manager/admins/update.js.slim | 10 ++- app/views/manager/members/_edit.html.slim | 3 + app/views/manager/members/_form.html.slim | 65 ++++++++++--------- app/views/manager/members/_member.html.slim | 14 +++- .../members/{new.html.slim => _new.html.slim} | 0 app/views/manager/members/create.js.slim | 10 +++ app/views/manager/members/edit.js.slim | 11 ++++ app/views/manager/members/index.html.slim | 7 +- app/views/manager/members/new.js.slim | 6 ++ app/views/manager/members/update.js.slim | 14 ++++ app/views/shared/manager/_top.html.slim | 2 +- config/locales/en.yml | 16 +++++ config/locales/manager/en.yml | 19 +++++- config/routes.rb | 2 +- config/settings.yml | 3 + 26 files changed, 286 insertions(+), 85 deletions(-) create mode 100644 app/views/manager/members/_edit.html.slim rename app/views/manager/members/{new.html.slim => _new.html.slim} (100%) create mode 100644 app/views/manager/members/create.js.slim create mode 100644 app/views/manager/members/edit.js.slim create mode 100644 app/views/manager/members/new.js.slim create mode 100644 app/views/manager/members/update.js.slim diff --git a/app/assets/javascripts/manager/custom.js b/app/assets/javascripts/manager/custom.js index a676deb..ddf7354 100644 --- a/app/assets/javascripts/manager/custom.js +++ b/app/assets/javascripts/manager/custom.js @@ -13,6 +13,7 @@ $(document).ready(function(){ $('#admin_table').DataTable({ scrollY: 500, "pageLength": 25, + "aaSorting": [], "columnDefs": [ { "orderable": false, "targets": [5] }, ] @@ -21,6 +22,7 @@ $(document).ready(function(){ $('#member_table').DataTable({ scrollY: 500, "pageLength": 25, + "aaSorting": [], "columnDefs": [ { "orderable": false, "targets": [5] }, ] @@ -42,10 +44,9 @@ $(document).ready(function(){ $('#admin-prices').DataTable({ scrollY: 500, - "order": [[ 0, 'DESC' ]], "pageLength": 25, "columnDefs": [ - { "orderable": false, "targets": [5] }, + { "orderable": false, "targets": [4] }, ] }); diff --git a/app/assets/stylesheets/manager/custom.scss b/app/assets/stylesheets/manager/custom.scss index fc643b5..502f8a2 100644 --- a/app/assets/stylesheets/manager/custom.scss +++ b/app/assets/stylesheets/manager/custom.scss @@ -200,9 +200,9 @@ i.fa.fa-caret-down { } .avatar-default-member { - height: 160px; - width: 160px; - margin-left: 16%; + height: 90px; + width: 90px; + border-radius: 50%; } .custom-dropdown { @@ -224,7 +224,7 @@ i.fa.fa-caret-down { border-radius: 6px; } -.custom-dropdown li a { +.custom-dropdown li a { color: #555555; display: block; font-family: arial; @@ -301,6 +301,23 @@ a.account:hover { text-decoration: none; } +#member_avatar { + margin-top: 27px; + padding: 3px; +} + +.show-avatar-index { + height: 15px; + width: 15px; + border-radius: 50%; + margin-right: 10px; + margin-top: -4px; +} + +.align-btn{ + padding: 0.1rem .75rem !important; +} + .new-price { float: right; } diff --git a/app/controllers/manager/admins_controller.rb b/app/controllers/manager/admins_controller.rb index 549d2fb..0feb619 100644 --- a/app/controllers/manager/admins_controller.rb +++ b/app/controllers/manager/admins_controller.rb @@ -3,11 +3,10 @@ module Manager class AdminsController < BaseController before_action :check_default_admin + before_action :all_admin, only: %i[index create update] before_action :load_admin, only: %i[edit update destroy] - def index - @admins = Admin.all - end + def index; end def new @admin = Admin.new @@ -15,33 +14,26 @@ def new def create @admin = Admin.new admin_params + @admin.avatar = params[:admin][:avatar] if @admin.save - flash[:success] = t "messages.success.admins.create" + flash.now[:success] = t "messages.success.admins.create" else - flash[:danger] = t "messages.failed.admins.create" - end - respond_to do |format| - format.js + @admin.avatar.purge_later + flash.now[:danger] = t "messages.failed.admins.create" end end - def edit; end - def update - support_update(@admin) + support_update @admin if @admin.changed? || !params[:admin][:avatar].blank? update_admin @admin else - flash[:notice] = t("messages.notice.admins.not_edit", id: @admin.id.to_s) + flash.now[:notice] = t("messages.notice.admins.not_edit", id: @admin.id) end end def destroy - if !@admin.flag? && @admin.destroy - flash[:success] = t("messages.success.admins.delete", id: @admin.id.to_s) - else - flash[:danger] = t("messages.failed.admins.delete", id: @admin.id.to_s) - end + destroy_admin @admin redirect_to manager_admins_path end @@ -53,16 +45,16 @@ def load_admin def admin_params params.require(:admin).permit :email, :name, :address, - :password, :password_confirmation, :avatar + :password, :password_confirmation end def update_admin(admin) - if admin.save - flash[:success] = t("messages.success.admins.update", id: admin.id.to_s) + if admin.save && admin.update_avatar(params[:admin][:avatar]) + flash.now[:success] = + t("messages.success.admins.update", id: admin.id) else - respond_to do |format| - format.js { flash[:danger] = t("messages.failed.admins.update", id: admin.id.to_s) } - end + flash.now[:danger] = + t("messages.failed.admins.update", id: admin.id) end end @@ -76,5 +68,18 @@ def support_update(admin) admin.not_update_password = true if admin_params[:password].blank? && admin_params[:password_confirmation].blank? admin.assign_attributes admin_params end + + def destroy_admin(admin) + if !admin.flag? && admin.destroy + admin.avatar.purge_later + flash[:success] = t("messages.success.admins.delete", id: admin.id) + else + flash[:danger] = t("messages.failed.admins.delete", id: admin.id) + end + end + + def all_admin + @admins = Admin.newest + end end end diff --git a/app/controllers/manager/members_controller.rb b/app/controllers/manager/members_controller.rb index 70877a8..390544c 100644 --- a/app/controllers/manager/members_controller.rb +++ b/app/controllers/manager/members_controller.rb @@ -2,9 +2,10 @@ module Manager class MembersController < BaseController - def index - @members = Member.all - end + before_action :all_member, only: %i[index create update] + before_action :load_member, only: %i[edit update destroy] + + def index; end def new @member = Member.new @@ -12,20 +13,61 @@ def new def create @member = Member.new member_params + @member.avatar = params[:member][:avatar] if @member.save - flash[:success] = t "messages.success.members.create" - redirect_to manager_members_path + flash.now[:success] = t "messages.success.members.create" else + @member.avatar.purge_later flash.now[:danger] = t "messages.failed.members.create" - render :new end end + def update + support_update @member + if @member.changed? || !params[:member][:avatar].blank? + update_member @member + else + flash.now[:notice] = t("messages.notice.members.not_edit", id: @member.id) + end + end + + def destroy + if @member.destroy + @member.avatar.purge_later + flash[:success] = t("messages.success.members.delete", id: @member.id) + else + flash[:danger] = t("messages.failed.members.delete", id: @member.id) + end + redirect_to manager_members_path + end + private def member_params params.require(:member).permit :email, :name, :address, - :password, :password_confirmation, :avatar + :password, :password_confirmation + end + + def load_member + @member = Member.find(params[:id]) + end + + def update_member(member) + if member.save && member.update_avatar(params[:member][:avatar]) + flash.now[:success] = t("messages.success.members.update", id: member.id) + else + flash.now[:danger] = t("messages.failed.members.update", id: member.id) + end + end + + def support_update(member) + member.not_update_password = true if member_params[:password] + .blank? && member_params[:password_confirmation].blank? + member.assign_attributes member_params + end + + def all_member + @members = Member.newest end end end diff --git a/app/models/admin.rb b/app/models/admin.rb index 6d19386..abd3b1a 100644 --- a/app/models/admin.rb +++ b/app/models/admin.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true class Admin < User + scope :newest, -> { order updated_at: :desc } end diff --git a/app/models/member.rb b/app/models/member.rb index 003ffab..a8a2dc5 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true class Member < User + scope :newest, -> { order updated_at: :desc } end diff --git a/app/models/user.rb b/app/models/user.rb index 32eec9f..3b9cb7d 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -9,10 +9,35 @@ class User < ApplicationRecord validates :name, presence: true, length: { maximum: 45 } validates :address, presence: true, length: { maximum: 255 } validates :type, presence: true + validate :avatar_validate, if: -> { avatar.attached? } + has_one_attached :avatar def timeout_in - 30.minutes + Settings.time_out.minutes + end + + def avatar_validate + return if avatar.blob.content_type.starts_with?(Settings.file_path) && avatar.blob.byte_size < Settings.max_size + + avatar.purge + errors.add(:avatar, :not_valid) + end + + def update_avatar(value) + return true unless value.present? + + if value.size > Settings.max_size + errors.add(:avatar, :size) + false + elsif !value.content_type.starts_with?(Settings.file_path) + errors.add(:avatar, :format) + false + else + avatar.purge_later + update_attribute(:avatar, value) + true + end end protected diff --git a/app/views/layouts/_flashmessages.html.slim b/app/views/layouts/_flashmessages.html.slim index 29f2fb4..490ae45 100644 --- a/app/views/layouts/_flashmessages.html.slim +++ b/app/views/layouts/_flashmessages.html.slim @@ -10,6 +10,8 @@ - type = "warning" - when "warning" - type = "warning" + - when "timedout" + -type = "" - else - type = 'success' javascript: diff --git a/app/views/manager/admins/_admin.html.slim b/app/views/manager/admins/_admin.html.slim index 9d68ccc..a646758 100644 --- a/app/views/manager/admins/_admin.html.slim +++ b/app/views/manager/admins/_admin.html.slim @@ -2,15 +2,22 @@ tr.data-user td = admin.id td + - if admin.avatar.attached? + = image_tag admin.avatar, class: "show-avatar-index" + - else + = image_tag "defaultavatar.jpeg", class: "show-avatar-index" = admin.name td = admin.email td = admin.address td - = admin.type + - if admin.created_at < admin.updated_at + = t(".updated", time: time_ago_in_words(admin.updated_at)) + - else + = t(".created", time: time_ago_in_words(admin.created_at)) td id="admin-#{admin.id}" - = link_to t(".edit"), edit_manager_admin_path(admin), remote: true, class: "btn info" + = link_to t(".edit"), edit_manager_admin_path(admin), remote: true, class: "btn info align-btn" - unless admin.flag? = link_to t(".delete"), manager_admin_path(admin), method: :delete, \ - data: { confirm: "You sure?" }, class: "btn danger" + data: { confirm: "You sure?" }, class: "btn danger align-btn" diff --git a/app/views/manager/admins/create.js.slim b/app/views/manager/admins/create.js.slim index da6ceda..f903009 100644 --- a/app/views/manager/admins/create.js.slim +++ b/app/views/manager/admins/create.js.slim @@ -5,4 +5,6 @@ $(".modal").animate({scrollTop : 0},500); - else | - location.reload(); + $("#admin-modal").modal("hide") + $(".data-admin").html("#{j(render @admins)}") + toastr.success("#{flash[:success]}"); diff --git a/app/views/manager/admins/index.html.slim b/app/views/manager/admins/index.html.slim index cc49d8d..1eee71d 100644 --- a/app/views/manager/admins/index.html.slim +++ b/app/views/manager/admins/index.html.slim @@ -7,8 +7,8 @@ table#admin_table.table.table-striped.table-bordered style=("width: 100%") th = t(".name") th = t(".email") th = t(".address") - th = t(".type") + th = t(".access") th = t(".action") - tbody + tbody.data-admin = render @admins #admin-modal.modal.fade diff --git a/app/views/manager/admins/update.js.slim b/app/views/manager/admins/update.js.slim index da6ceda..b4ff71f 100644 --- a/app/views/manager/admins/update.js.slim +++ b/app/views/manager/admins/update.js.slim @@ -3,6 +3,12 @@ $("#message_errors").html("#{j(render 'shared/manager/error_messages', object: @admin)}"); toastr.error("#{flash[:danger]}"); $(".modal").animate({scrollTop : 0},500); -- else +- elsif flash[:notice] | - location.reload(); + $("#admin-modal").modal("hide") + toastr.info("#{flash[:notice]}"); +- elsif flash[:success] + | + $("#admin-modal").modal("hide") + $(".data-admin").html("#{j(render @admins)}") + toastr.success("#{flash[:success]}"); diff --git a/app/views/manager/members/_edit.html.slim b/app/views/manager/members/_edit.html.slim new file mode 100644 index 0000000..5ff05e1 --- /dev/null +++ b/app/views/manager/members/_edit.html.slim @@ -0,0 +1,3 @@ +- provide(:title, t(".edit_member")) +- provide(:btn_name, t(".update")) += render "form", member: @member diff --git a/app/views/manager/members/_form.html.slim b/app/views/manager/members/_form.html.slim index 011ca3a..46e03ec 100644 --- a/app/views/manager/members/_form.html.slim +++ b/app/views/manager/members/_form.html.slim @@ -1,29 +1,36 @@ -= form_for [:manager, member], html: { style: "display:inline;" } do |f| - h3 style="text-align: center" = yield(:title) - - if member.errors.any? - #error_explanation - = render "shared/manager/error_messages", object: member - hr - .form-group.row - .col-md-3 - = avatar_member member - - = f.file_field :avatar, class: "form-control preview_member col-md-8", id: "custom_field_file" - .form_group - = f.label :name, class: "control-label" - = f.text_field :name, class: "form-control", required: true - .form_group - = f.label :email, class: "control-label" - = f.email_field :email, class: "form-control", required: true, presence: true - .form_group - = f.label :address, class: "control-label" - = f.text_area :address, class: "form-control", required: true, size: "5x5" - .form_group - = f.label :password, class: "control-label" - = f.password_field :password, class: "form-control" - .form_group - = f.label :password_confirmation, class: "control-label" - = f.password_field :password_confirmation, class: "form-control" - .align-button - = f.submit yield(:btn_name), class: "btn btn-primary", style: "margin: 10px" - = link_to t(".cancel"), request.referer, class: "btn btn-danger" +.modal-dialog + .modal-content + = form_for [:manager, member], remote: true, html: { style: "display:inline;" } do |f| + .modal-body + h3 style="text-align: center" = yield(:title) + #message_member_errors + hr + .form-group.row[style="padding: 25px"] + .col-sm-3 + - if member.avatar.attached? + = image_tag member.avatar, class: "avatar-default-member", id: "img_member_prev" + - else + = image_tag "defaultavatar.jpeg", class: "avatar-default-member", id: "img_member_prev" + .prev.col-sm-9 + = f.file_field :avatar, class: "form-control preview_member" + .form-group + = f.label :name, class: "control-label" + = f.text_field :name, class: "form-control", required: true + .form-group + = f.label :email, class: "control-label" + = f.text_field :email, class: "form-control", required: true, presence: true + .form-group + = f.label :address, class: "control-label" + = f.text_field :address, class: "form-control", required: true + .toggle + .form-group + = f.label :password, class: "control-label" + = f.password_field :password, class: "form-control" + .form-group + = f.label :password_confirmation, class: "control-label" + = f.password_field :password_confirmation, class: "form-control" + .modal-footer + - unless member.new_record? + button.show.btn.btn-link type="button" style="color: inherit;" More + = f.submit yield(:btn_name), class: "btn btn-primary" + = link_to t(".cancel"), "#", class: "btn btn-danger", data: {dismiss: "modal"} diff --git a/app/views/manager/members/_member.html.slim b/app/views/manager/members/_member.html.slim index d2b3608..8d8bde1 100644 --- a/app/views/manager/members/_member.html.slim +++ b/app/views/manager/members/_member.html.slim @@ -2,13 +2,21 @@ tr.data-user td = member.id td + - if member.avatar.attached? + = image_tag member.avatar, class: "show-avatar-index" + - else + = image_tag "defaultavatar.jpeg", class: "show-avatar-index" = member.name td = member.email td = member.address td - = member.type + - if member.created_at < member.updated_at + = t(".updated", time: time_ago_in_words(member.updated_at)) + - else + = t(".created", time: time_ago_in_words(member.created_at)) td - = link_to t(".edit"), "#", class: "btn info" - = link_to t(".delete"), "#" , class: "btn danger" + = link_to t(".edit"), edit_manager_member_path(member), remote: true, class: "btn info align-btn" + = link_to t(".delete"), manager_member_path(member), method: :delete, \ + data: { confirm: "You sure?" }, class: "btn danger align-btn" diff --git a/app/views/manager/members/new.html.slim b/app/views/manager/members/_new.html.slim similarity index 100% rename from app/views/manager/members/new.html.slim rename to app/views/manager/members/_new.html.slim diff --git a/app/views/manager/members/create.js.slim b/app/views/manager/members/create.js.slim new file mode 100644 index 0000000..30c7d9c --- /dev/null +++ b/app/views/manager/members/create.js.slim @@ -0,0 +1,10 @@ +- if @member.errors.present? + | + $("#message_member_errors").html("#{j(render 'shared/manager/error_messages', object: @member)}"); + toastr.error("#{flash[:danger]}"); + $(".modal").animate({scrollTop : 0},500); +- else + | + $("#member-modal").modal("hide") + $(".data-member").html("#{j(render @members)}") + toastr.success("#{flash[:success]}"); diff --git a/app/views/manager/members/edit.js.slim b/app/views/manager/members/edit.js.slim new file mode 100644 index 0000000..f801554 --- /dev/null +++ b/app/views/manager/members/edit.js.slim @@ -0,0 +1,11 @@ +| + $("#member-modal").html("#{j(render 'edit')}"); + $("#member-modal").modal("show") + $(".preview_member").change(function() { + readURL(this, '#img_member_prev'); + }); + $(".toggle").css('display', 'none'); + $(".show").on('click', function(){ + $(".toggle").toggle(); + $(this).text( $(this).text() == 'More' ? "Hide" : "More"); + }); diff --git a/app/views/manager/members/index.html.slim b/app/views/manager/members/index.html.slim index 8857a5b..75a9a0f 100644 --- a/app/views/manager/members/index.html.slim +++ b/app/views/manager/members/index.html.slim @@ -1,4 +1,4 @@ -= link_to t(".create"), new_manager_member_path, class: "btn-primary create_user" += link_to t(".create"), new_manager_member_path, remote:true, class: "btn-primary create_user" h2#title-user = t ".all_member" table#member_table.table.table-striped.table-bordered style=("width: 100%") @@ -8,7 +8,8 @@ table#member_table.table.table-striped.table-bordered style=("width: 100%") th = t(".name") th = t(".email") th = t(".address") - th = t(".type") + th = t(".access") th = t(".action") - tbody + tbody.data-member = render @members +#member-modal.modal.fade diff --git a/app/views/manager/members/new.js.slim b/app/views/manager/members/new.js.slim new file mode 100644 index 0000000..7589702 --- /dev/null +++ b/app/views/manager/members/new.js.slim @@ -0,0 +1,6 @@ +| + $("#member-modal").html("#{j(render 'new')}"); + $("#member-modal").modal("show") + $(".preview_member").change(function() { + readURL(this, '#img_member_prev'); + }); diff --git a/app/views/manager/members/update.js.slim b/app/views/manager/members/update.js.slim new file mode 100644 index 0000000..d4f33b0 --- /dev/null +++ b/app/views/manager/members/update.js.slim @@ -0,0 +1,14 @@ +- if @member.errors.present? + | + $("#message_member_errors").html("#{j(render 'shared/manager/error_messages', object: @member)}"); + toastr.error("#{flash[:danger]}"); + $(".modal").animate({scrollTop : 0},500); +- elsif flash[:notice] + | + $("#member-modal").modal("hide") + toastr.info("#{flash[:notice]}"); +- elsif flash[:success] + | + $("#member-modal").modal("hide") + $(".data-member").html("#{j(render @members)}") + toastr.success("#{flash[:success]}"); diff --git a/app/views/shared/manager/_top.html.slim b/app/views/shared/manager/_top.html.slim index 1676804..18e3889 100644 --- a/app/views/shared/manager/_top.html.slim +++ b/app/views/shared/manager/_top.html.slim @@ -6,7 +6,7 @@ nav.navbar.navbar-expand.navbar-light.bg-white.topbar.mb-4.static-top.shadow button.btn.btn-primary type="button" i.fa.fa-search.fa-sm .custom-dropdown - = link_to("#", class: "account", title: "#{current_admin.name}", "data-toggle": "tooltip") do + = link_to("#", class: "account", title: "#{current_admin.name}", "data-toggle": "tooltip", "data-placement": "left") do span = truncate(current_admin.name, length: 10) - if current_admin.avatar.attached? = image_tag current_admin.avatar, class: "profile-circle" diff --git a/config/locales/en.yml b/config/locales/en.yml index f1183d1..adb806a 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -35,3 +35,19 @@ en: logout: "Logout" settings: "Settings" profile: "Profile" + hello: "Hello world" + activerecord: + errors: + models: + admin: + attributes: + avatar: + not_valid: "wrong format or size is too big" + format: "wrong format" + size: "is too big" + member: + attributes: + avatar: + not_valid: "wrong format or size is too big" + format: "wrong format" + size: "is too big" diff --git a/config/locales/manager/en.yml b/config/locales/manager/en.yml index 78b4d5e..7d97fb3 100644 --- a/config/locales/manager/en.yml +++ b/config/locales/manager/en.yml @@ -80,6 +80,8 @@ en: admin: edit: "Edit" delete: "Delete" + updated: "Edited %{time}" + created: "Created %{time}" edit: edit_admin: "Edit Admin" update: "Update" @@ -95,7 +97,7 @@ en: name: "Name" email: "Email" address: "Address" - type: "Type" + access: "Access" action: "Action" areas: create: @@ -119,6 +121,8 @@ en: member: edit: "Edit" delete: "Delete" + updated: "Edited %{time}" + created: "Created %{time}" index: create: "Create" all_member: "All members" @@ -126,19 +130,24 @@ en: name: "Name" email: "Email" address: "Address" - type: "Type" + access: "Access" action: "Action" new: create: "Create" new_member: "New Member" + edit: + update: "Update" + edit_member: "Edit Member" messages: success: admins: create: "Create succeeded!" - update: "Updated admin %{id} succeeded" + update: "Update admin %{id} succeeded" delete: "Delete admin %{id} succeeded" members: create: "Create succeeded!" + delete: "Delete member %{id} succeeded" + update: "Update member %{id} succeeded" failed: admins: create: "Create failed!" @@ -146,7 +155,11 @@ en: delete: "Delete admin %{id} failed" members: create: "Create failed!" + delete: "Delete member %{id} failed" + update: "Update member %{id} failed" notice: admins: not_edit: "Not edit admin %{id}" not_default_admin: "You can not delete default admin!" + members: + not_edit: "Not edit member %{id}" diff --git a/config/routes.rb b/config/routes.rb index e62950e..87cc9ee 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -4,7 +4,7 @@ devise_for :admins, controllers: { sessions: "manager/sessions" } namespace :manager do - root "admins#index" + root "members#index" resources :favorite_spaces resources :rooms resources :admins diff --git a/config/settings.yml b/config/settings.yml index 8232292..552f04f 100644 --- a/config/settings.yml +++ b/config/settings.yml @@ -1 +1,4 @@ location_per: 10 +max_size: 5_242_880 +file_path: image/ +time_out: 30