mirror of
https://github.com/Growstuff/growstuff.git
synced 2025-12-24 01:57:46 -05:00
Add revert functionality to admin crops page (#4346)
* feat(admin): add revert functionality to crops page This change adds a "Revert" button to the admin crops page, allowing crop wranglers to revert changes to a previous version. It introduces a new `Admin::VersionsController` with a `revert` action that uses `paper_trail`'s `reify` method to restore a previous version of a `Crop` object. The view is updated to include a "Revert" button, which is guarded by a `can?(:wrangle, Crop)` check to ensure only authorized users can see it. The controller also includes an authorization check to prevent unauthorized users from accessing the revert action directly. A feature spec is added to test the new functionality, including the authorization logic. * Consistent UX * Specs --------- Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com> Co-authored-by: Daniel O'Connor <daniel.oconnor@gmail.com>
This commit is contained in:
committed by
GitHub
parent
13a8276313
commit
460daf36f9
@@ -8,6 +8,7 @@ class Admin::CropsController < ApplicationController
|
||||
@versions = PaperTrail::Version.where(item_type: 'Crop').order(created_at: :desc).limit(100)
|
||||
member_ids = @versions.map(&:whodunnit).compact.map(&:to_i)
|
||||
@members = Member.where(id: member_ids).index_by(&:id)
|
||||
@crop_wranglers = Role.crop_wranglers
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
24
app/controllers/admin/versions_controller.rb
Normal file
24
app/controllers/admin/versions_controller.rb
Normal file
@@ -0,0 +1,24 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Admin
|
||||
class VersionsController < ApplicationController
|
||||
before_action :authenticate_member!
|
||||
before_action :authorize_admin!
|
||||
|
||||
def revert
|
||||
@version = PaperTrail::Version.find(params[:id])
|
||||
@object = @version.reify
|
||||
if @object.save
|
||||
redirect_to admin_crops_path, notice: "Reverted to version from #{@version.created_at.strftime('%B %d, %Y')}"
|
||||
else
|
||||
redirect_to admin_crops_path, alert: "Could not revert to version from #{@version.created_at.strftime('%B %d, %Y')}. Errors: #{@object.errors.full_messages.to_sentence}"
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def authorize_admin!
|
||||
authorize! :wrangle, Crop
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,41 +1,56 @@
|
||||
- content_for :title, "Crop Wrangler Admin"
|
||||
- content_for :breadcrumbs do
|
||||
%li.breadcrumb-item= link_to 'Admin', '#'
|
||||
%li.breadcrumb-item.active Crop Wrangler
|
||||
- content_for :title, "Crop Wrangling"
|
||||
|
||||
%h1 Crop Wrangler Admin
|
||||
%h1 Crop Wrangling
|
||||
|
||||
%ul#myTab.nav.nav-tabs{role: "tablist"}
|
||||
%li.nav-item
|
||||
%a#home-tab.nav-link{ href: admin_crops_path, role: "tab", class: 'active'}
|
||||
Recently edited
|
||||
%li.nav-item
|
||||
%a#home-tab.nav-link{ href: wrangle_crops_path, role: "tab"}
|
||||
Recently added
|
||||
%li.nav-item
|
||||
%a#profile-tab.nav-link{ href: wrangle_crops_path(approval_status: "pending"), role: "tab"}
|
||||
Pending approval
|
||||
%li.nav-item
|
||||
%a#contact-tab.nav-link{ href: wrangle_crops_path(approval_status: "rejected"), role: "tab"}
|
||||
Rejected
|
||||
%nav.nav
|
||||
= link_to "Full crop hierarchy", hierarchy_crops_path, class: 'nav-link'
|
||||
= link_to "Add Crop", new_crop_path, class: 'btn'
|
||||
|
||||
.card
|
||||
%ul.list-group.list-group-flush
|
||||
- @versions.each do |version|
|
||||
- crop = version.item || version.reify
|
||||
- if crop
|
||||
%li.list-group-item
|
||||
.d-flex.w-100.justify-content-between
|
||||
%h5.mb-1
|
||||
- if version.event == "destroy"
|
||||
= crop.name
|
||||
- else
|
||||
= link_to crop.name, crop
|
||||
%small.text-muted= "was #{version.event}d"
|
||||
%small= time_ago_in_words(version.created_at) + " ago"
|
||||
- member = @members[version.whodunnit.to_i]
|
||||
- if member
|
||||
%p.mb-1
|
||||
Made by
|
||||
= link_to member.name, member
|
||||
= render 'shared/version_changeset', version: version
|
||||
%section.crop_wranglers
|
||||
%h2 Crop Wranglers
|
||||
- @crop_wranglers.each do |crop_wrangler|
|
||||
= render 'members/tiny', member: crop_wrangler
|
||||
|
||||
%hr/
|
||||
|
||||
%section
|
||||
%h2 Crops
|
||||
|
||||
|
||||
%ul#myTab.nav.nav-tabs{role: "tablist"}
|
||||
%li.nav-item
|
||||
%a#home-tab.nav-link{ href: admin_crops_path, role: "tab", class: 'active'}
|
||||
Recently edited
|
||||
%li.nav-item
|
||||
%a#home-tab.nav-link{ href: wrangle_crops_path, role: "tab"}
|
||||
Recently added
|
||||
%li.nav-item
|
||||
%a#profile-tab.nav-link{ href: wrangle_crops_path(approval_status: "pending"), role: "tab"}
|
||||
Pending approval
|
||||
%li.nav-item
|
||||
%a#contact-tab.nav-link{ href: wrangle_crops_path(approval_status: "rejected"), role: "tab"}
|
||||
Rejected
|
||||
|
||||
.card
|
||||
%ul.list-group.list-group-flush
|
||||
- @versions.each do |version|
|
||||
- crop = version.item || version.reify
|
||||
- if crop
|
||||
%li.list-group-item
|
||||
.d-flex.w-100.justify-content-between
|
||||
%h5.mb-1
|
||||
- if version.event == "destroy"
|
||||
= crop.name
|
||||
- else
|
||||
= link_to crop.name, crop
|
||||
%small.text-muted= "was #{version.event}d"
|
||||
.d-inline-block
|
||||
%small.mr-2= time_ago_in_words(version.created_at) + " ago"
|
||||
- if can?(:wrangle, Crop)
|
||||
= link_to "Revert", revert_admin_version_path(version), method: :post, class: "btn btn-sm btn-outline-danger"
|
||||
- member = @members[version.whodunnit.to_i]
|
||||
- if member
|
||||
%p.mb-1
|
||||
Made by
|
||||
= link_to member.name, member
|
||||
= render 'shared/version_changeset', version: version
|
||||
|
||||
@@ -94,6 +94,9 @@ Rails.application.routes.draw do
|
||||
|
||||
namespace :admin do
|
||||
resources :crops, only: [:index]
|
||||
resources :versions, only: [] do
|
||||
post :revert, on: :member, as: :revert
|
||||
end
|
||||
end
|
||||
|
||||
resources :comments
|
||||
|
||||
38
spec/features/admin/reverting_crops_spec.rb
Normal file
38
spec/features/admin/reverting_crops_spec.rb
Normal file
@@ -0,0 +1,38 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.feature 'Reverting crops' do
|
||||
let(:wrangler) { create(:crop_wrangling_member) }
|
||||
let(:member) { create(:member) }
|
||||
let!(:crop) { create(:crop, name: 'Initial Name') }
|
||||
|
||||
before do
|
||||
crop.update(name: 'Updated Name')
|
||||
end
|
||||
|
||||
context 'when logged in as an wrangler' do
|
||||
before do
|
||||
login_as(wrangler, scope: :member)
|
||||
end
|
||||
|
||||
scenario 'Admin reverts a crop' do
|
||||
visit admin_crops_path
|
||||
click_link 'Revert', match: :first
|
||||
expect(page).to have_content('Reverted to version from')
|
||||
crop.reload
|
||||
expect(crop.name).to eq('Initial Name')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when logged in as a regular member' do
|
||||
before do
|
||||
login_as(member, scope: :member)
|
||||
end
|
||||
|
||||
scenario 'Member cannot revert a crop' do
|
||||
visit admin_crops_path
|
||||
expect(page).not_to have_link('Revert')
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user