Add link to investments from the admin budget page

Since managing investments is a very common action, with this link
administrators won't have to go back to the index page to manage
investments; they can access it from either the budgets index page or
the budget page.

Since now the links we've got on the budget page are similar to the ones
we've got in the index page table, we're styling them in a similar way.

We're also fixing a small typo en the investments path; it works exactly
the same way as it used to, but passing `budget` instead of `budget_id:
budget.id` is shorter and more consistent with what we do in other
places.
This commit is contained in:
Javi Martín
2021-08-30 23:12:13 +02:00
parent 51a0bce58c
commit 8bb55f0d45
7 changed files with 149 additions and 137 deletions

View File

@@ -1,5 +1,6 @@
.admin .groups-and-headings { .admin .groups-and-headings {
$gap: rem-calc(map-get($grid-column-gutter, medium)); $gap: rem-calc(map-get($grid-column-gutter, medium));
@include admin-action-icons;
> section + section { > section + section {
margin-top: $line-height * 1.5; margin-top: $line-height * 1.5;
@@ -51,15 +52,6 @@
@include icon-on-top; @include icon-on-top;
} }
.edit-link {
@include has-fa-icon(edit, regular);
}
.destroy-link {
@include has-fa-icon(trash-alt, regular);
color: darken($alert-color, 5%);
}
.new-link { .new-link {
@include hollow-button; @include hollow-button;
flex-shrink: 0; flex-shrink: 0;

View File

@@ -1,40 +1,32 @@
.admin .budgets-links { .admin .budgets-links {
$gap: $line-height; $vertical-gap: $line-height;
@include flex-with-gap($gap); @include admin-action-icons;
align-items: baseline; @include flex-with-gap;
align-items: flex-start;
flex-wrap: wrap; flex-wrap: wrap;
margin-top: -$gap; margin-top: -$vertical-gap;
> * { > * {
margin-top: $gap; $min-width: $sdg-icon-min-width;
margin-top: $vertical-gap;
min-width: $min-width;
@supports (max-width: max-content) {
flex-basis: $min-width;
flex-grow: 1;
max-width: max-content;
}
} }
+ * { + * {
margin-top: $line-height; margin-top: $line-height;
} }
.preview-link { a {
@include has-fa-icon(eye, regular); @include icon-on-top;
@include hollow-button;
}
.edit-link {
@include has-fa-icon(edit, regular);
@include hollow-button;
} }
.results-link { .results-link {
@include hollow-button; @include has-fa-icon(poll, solid);
}
.edit-link,
.preview-link,
.results-link {
margin-left: $gap;
margin-top: $gap;
&::before {
margin-#{$global-right}: $font-icon-margin;
}
} }
} }

View File

@@ -1,4 +1,5 @@
.admin .table-actions { .admin .table-actions {
@include admin-action-icons;
@include flex-with-gap(1.6em); @include flex-with-gap(1.6em);
align-items: flex-start; align-items: flex-start;
padding: 0 0.5em; padding: 0 0.5em;
@@ -11,106 +12,4 @@
button { button {
cursor: pointer; cursor: pointer;
} }
.edit-link {
@include has-fa-icon(edit, regular);
}
.destroy-link {
@include has-fa-icon(trash-alt, regular);
}
.destroy-link,
.destroy-role-link,
.destroy-officer-link,
.reject-link,
.confirm-hide-link {
color: darken($alert-color, 5%);
}
.show-link,
.preview-link {
@include has-fa-icon(eye, regular);
}
.new-link,
.assign-booth-link {
@include has-fa-icon(plus-circle, solid);
color: $color-success;
}
.create-role-link,
.create-officer-link {
@include has-fa-icon(user-plus, solid);
color: $color-success;
}
.destroy-role-link,
.destroy-officer-link,
.reject-link {
@include has-fa-icon(user-times, solid);
}
.restore-link {
@include has-fa-icon(undo, solid);
}
.restore-link,
.investments-link {
color: darken($warning-color, 20%);
&:not(:hover, :focus)::before {
color: $warning-color;
}
}
.confirm-hide-link {
@include has-fa-icon(flag, regular);
}
.verify-link {
@include has-fa-icon(user-check, solid);
color: $color-success;
}
.preview-pending-link {
@include has-fa-icon(search, solid);
}
.send-pending-link {
@include has-fa-icon(share-square, regular);
color: $color-success;
}
.configure-link,
.answers-link {
@include has-fa-icon(tools, solid);
}
.download-link {
@include has-fa-icon(download, solid);
}
.shifts-link {
@include has-fa-icon(clock, regular);
}
.investments-link {
@include has-fa-icon(coins, solid);
}
.headings-link {
@include has-fa-icon(chart-pie, solid);
color: $color-success;
}
.manage-link,
.ballots-link {
@include has-fa-icon(archive, solid);
color: $link;
}
.cards-link {
@include has-fa-icon(images, regular);
}
} }

View File

@@ -1524,3 +1524,107 @@ $font-awesome-icons: (
font-size: 1.6em; font-size: 1.6em;
} }
} }
@mixin admin-action-icons {
.edit-link {
@include has-fa-icon(edit, regular);
}
.destroy-link {
@include has-fa-icon(trash-alt, regular);
}
.destroy-link,
.destroy-role-link,
.destroy-officer-link,
.reject-link,
.confirm-hide-link {
color: darken($alert-color, 5%);
}
.show-link,
.preview-link {
@include has-fa-icon(eye, regular);
}
.new-link,
.assign-booth-link {
@include has-fa-icon(plus-circle, solid);
color: $color-success;
}
.create-role-link,
.create-officer-link {
@include has-fa-icon(user-plus, solid);
color: $color-success;
}
.destroy-role-link,
.destroy-officer-link,
.reject-link {
@include has-fa-icon(user-times, solid);
}
.restore-link {
@include has-fa-icon(undo, solid);
}
.restore-link,
.investments-link {
color: darken($warning-color, 20%);
&:not(:hover, :focus)::before {
color: $warning-color;
}
}
.confirm-hide-link {
@include has-fa-icon(flag, regular);
}
.verify-link {
@include has-fa-icon(user-check, solid);
color: $color-success;
}
.preview-pending-link {
@include has-fa-icon(search, solid);
}
.send-pending-link {
@include has-fa-icon(share-square, regular);
color: $color-success;
}
.configure-link,
.answers-link {
@include has-fa-icon(tools, solid);
}
.download-link {
@include has-fa-icon(download, solid);
}
.shifts-link {
@include has-fa-icon(clock, regular);
}
.investments-link {
@include has-fa-icon(coins, solid);
}
.headings-link {
@include has-fa-icon(chart-pie, solid);
color: $color-success;
}
.manage-link,
.ballots-link {
@include has-fa-icon(archive, solid);
color: $link;
}
.cards-link {
@include has-fa-icon(images, regular);
}
}

View File

@@ -1,4 +1,10 @@
<div class="budgets-links"> <div class="budgets-links">
<% if budget.investments.any? %>
<%= action(:investments,
text: t("admin.budgets.index.budget_investments"),
path: admin_budget_budget_investments_path(budget)) %>
<% end %>
<% if can?(:read_results, budget) %> <% if can?(:read_results, budget) %>
<%= action(:results, text: results_text, path: budget_results_path(budget)) %> <%= action(:results, text: results_text, path: budget_results_path(budget)) %>
<% else %> <% else %>

View File

@@ -1,7 +1,7 @@
<%= render actions_component do |actions| %> <%= render actions_component do |actions| %>
<%= actions.action(:investments, <%= actions.action(:investments,
text: t("admin.budgets.index.budget_investments"), text: t("admin.budgets.index.budget_investments"),
path: admin_budget_budget_investments_path(budget_id: budget.id)) %> path: admin_budget_budget_investments_path(budget)) %>
<% if budget.poll.present? %> <% if budget.poll.present? %>
<%= actions.action(:ballots, <%= actions.action(:ballots,
text: t("admin.budgets.index.admin_ballots"), text: t("admin.budgets.index.admin_ballots"),

View File

@@ -78,4 +78,23 @@ describe Admin::Budgets::LinksComponent, controller: Admin::BaseController do
expect(page).not_to have_link "Preview" expect(page).not_to have_link "Preview"
end end
end end
describe "investments link" do
let(:budget) { create(:budget) }
let(:component) { Admin::Budgets::LinksComponent.new(budget) }
it "is shown for budgets with investments" do
create(:budget_investment, budget: budget)
render_inline component
expect(page).to have_link "Investment projects"
end
it "is not shown for budgets without investments" do
render_inline component
expect(page).not_to have_link "Investment projects"
end
end
end end