Skip to content

Commit

Permalink
Add organization gems and organization edit/update
Browse files Browse the repository at this point in the history
  • Loading branch information
martinemde committed Nov 11, 2024
1 parent 5102ba0 commit 8521bc3
Show file tree
Hide file tree
Showing 11 changed files with 207 additions and 8 deletions.
21 changes: 21 additions & 0 deletions app/controllers/organizations/gems_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
class Organizations::GemsController < ApplicationController
before_action :redirect_to_signin, unless: :signed_in?
before_action :redirect_to_new_mfa, if: :mfa_required_not_yet_enabled?
before_action :redirect_to_settings_strong_mfa_required, if: :mfa_required_weak_level_enabled?

before_action :find_organization, only: %i[index]

layout "subject"

# GET /organizations/:handle/gems

def index
@gems = @organization.rubygems.with_versions.by_downloads.preload(:most_recent_version, :gem_download).load_async

Check warning on line 13 in app/controllers/organizations/gems_controller.rb

View check run for this annotation

Codecov / codecov/patch

app/controllers/organizations/gems_controller.rb#L13

Added line #L13 was not covered by tests
end

private

def find_organization
@organization = Organization.find_by_handle!(params[:organization_handle])

Check warning on line 19 in app/controllers/organizations/gems_controller.rb

View check run for this annotation

Codecov / codecov/patch

app/controllers/organizations/gems_controller.rb#L19

Added line #L19 was not covered by tests
end
end
23 changes: 22 additions & 1 deletion app/controllers/organizations_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ class OrganizationsController < ApplicationController
before_action :redirect_to_new_mfa, only: :index, if: :mfa_required_not_yet_enabled?
before_action :redirect_to_settings_strong_mfa_required, only: :index, if: :mfa_required_weak_level_enabled?

before_action :find_organization, only: %i[show]
before_action :find_organization, only: %i[show edit update]

layout "subject"

Expand All @@ -26,9 +26,30 @@ def show
@memberships_count = @organization.memberships.count

Check warning on line 26 in app/controllers/organizations_controller.rb

View check run for this annotation

Codecov / codecov/patch

app/controllers/organizations_controller.rb#L24-L26

Added lines #L24 - L26 were not covered by tests
end

def edit
add_breadcrumb t("breadcrumbs.org_name", name: @organization.handle), organization_path(@organization)
add_breadcrumb t("breadcrumbs.settings")

Check warning on line 31 in app/controllers/organizations_controller.rb

View check run for this annotation

Codecov / codecov/patch

app/controllers/organizations_controller.rb#L30-L31

Added lines #L30 - L31 were not covered by tests

authorize @organization

Check warning on line 33 in app/controllers/organizations_controller.rb

View check run for this annotation

Codecov / codecov/patch

app/controllers/organizations_controller.rb#L33

Added line #L33 was not covered by tests
end

def update
authorize @organization

Check warning on line 37 in app/controllers/organizations_controller.rb

View check run for this annotation

Codecov / codecov/patch

app/controllers/organizations_controller.rb#L37

Added line #L37 was not covered by tests

if @organization.update(organization_params)
redirect_to organization_path(@organization)

Check warning on line 40 in app/controllers/organizations_controller.rb

View check run for this annotation

Codecov / codecov/patch

app/controllers/organizations_controller.rb#L39-L40

Added lines #L39 - L40 were not covered by tests
else
render :edit

Check warning on line 42 in app/controllers/organizations_controller.rb

View check run for this annotation

Codecov / codecov/patch

app/controllers/organizations_controller.rb#L42

Added line #L42 was not covered by tests
end
end

private

def find_organization
@organization = Organization.find_by_handle!(params[:handle])

Check warning on line 49 in app/controllers/organizations_controller.rb

View check run for this annotation

Codecov / codecov/patch

app/controllers/organizations_controller.rb#L49

Added line #L49 was not covered by tests
end

def organization_params
params.permit(organization: [:name]).require(:organization)

Check warning on line 53 in app/controllers/organizations_controller.rb

View check run for this annotation

Codecov / codecov/patch

app/controllers/organizations_controller.rb#L53

Added line #L53 was not covered by tests
end
end
2 changes: 2 additions & 0 deletions app/policies/organization_policy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ def update?
organization_member_with_role?(user, minimum_required_role: Access::OWNER)
end

alias edit? update?

Check warning on line 13 in app/policies/organization_policy.rb

View check run for this annotation

Codecov / codecov/patch

app/policies/organization_policy.rb#L13

Added line #L13 was not covered by tests

def create?
true
end
Expand Down
12 changes: 7 additions & 5 deletions app/views/organizations/_subject.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@
<hr class="hidden lg:block lg:mb-6 border-neutral-400 dark:border-neutral-600" />

<%= render Subject::NavComponent.new(current:) do |nav| %>
<%= nav.link t("layouts.application.header.dashboard"), dashboard_path, name: :dashboard, icon: "space-dashboard" %>
<%= nav.link t("organizations.show.history"), subscriptions_path, name: :subscriptions, icon: "notifications" %>
<%= nav.link t("organizations.show.gems"), organizations_path, name: :gems, icon: "gems" %>
<%= nav.link t("organizations.show.members"), organizations_path, name: :organizations, icon: "organizations" %>
<%= nav.link t("layouts.application.header.settings"), edit_settings_path, name: :settings, icon: "settings" %>
<%= nav.link t("layouts.application.header.dashboard"), organization_path(@organization), name: :dashboard, icon: "space-dashboard" %>
<%= nav.link t("organizations.show.history"), organization_path(@organization), name: :subscriptions, icon: "notifications" %>
<%= nav.link t("organizations.show.gems"), organization_gems_path(@organization), name: :gems, icon: "gems" %>
<%= nav.link t("organizations.show.members"), organization_path(@organization), name: :organizations, icon: "organizations" %>
<% if policy(@organization).edit? %>
<%= nav.link t("layouts.application.header.settings"), edit_organization_path(@organization), name: :settings, icon: "settings" %>
<% end %>
<% end %>
26 changes: 26 additions & 0 deletions app/views/organizations/edit.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<% content_for :subject do %>
<%= render "organizations/subject", organization: @organization, current: :settings %>
<% end %>

<h1 class="text-h2 mb-10"><%= t("layouts.application.header.settings") %></h1>

<%= render CardComponent.new do |c| %>
<%= c.head do %>
<%= c.title t("layouts.application.header.settings"), icon: "settings" %>
<% end %>
<%= form_with model: @organization, url: organization_path(@organization), method: :patch do |form| %>
<div>
<%= form.label :name, "Display Name", class: "block text-b2 font-semibold mb-2" %>
<%= form.text_field(
:name,
class: "w-full text-b2 rounded-lg dark:bg-neutral-950 focus:ring-inset focus:ring-1 focus:ring-orange-500",
required: true,
autocomplete: "organization",
) %>
</div>

<div class="flex mt-10">
<%= render ButtonComponent.new("Update", type: :submit, style: :outline) %>
</div>
<% end %>
<% end %>
36 changes: 36 additions & 0 deletions app/views/organizations/gems/index.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<% content_for :subject do %>
<%= render "organizations/subject", organization: @organization, current: :gems %>
<% end %>

<h1 class="text-h2 mb-10"><%= t("organizations.show.gems") %></h1>

<%= render CardComponent.new do |c| %>
<%= c.head do %>
<%= c.title t("organizations.show.gems"), icon: "gems", count: @gems_count %>
<% end %>
<% if @gems.empty? %>
<%= prose do %>
<i><%= t('organizations.show.no_gems') %></i>
<% end %>
<% else %>
<%= c.divided_list do %>
<% @gems.each do |rubygem| %>
<%= c.list_item_to(
rubygem_path(rubygem.slug),
title: short_info(rubygem.most_recent_version),
) do %>
<div class="flex flex-col w-full justify-between">
<div class="flex flex-row w-full items-center justify-between">
<h4 class="text-b1 flex"><%= rubygem.name %></h4>
<%= version_number(rubygem.most_recent_version) %>
</div>
<div class="flex flex-row w-full items-center justify-between">
<%= download_count_component(rubygem, class: "flex") %>
<div class="flex text-neutral-600"><%= version_date_component(rubygem.most_recent_version) %></div>
</div>
</div>
<% end %>
<% end %>
<% end %>
<% end %>
<% end %>
2 changes: 1 addition & 1 deletion app/views/organizations/show.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
<% end %>
<% if @gems.empty? %>
<%= prose do %>
<i><%= t('.no_gems', :creating_link => link_to(t('.creating_link_text'), "https://guides.rubygems.org/make-your-own-gem/")) %></i>
<i><%= t('.no_gems') %></i>
<% end %>
<% else %>
<%= c.divided_list do %>
Expand Down
1 change: 1 addition & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,7 @@ en:
index:
title: Organizations
show:
organization: Organization
gems: Gems
history: History
members: Members
Expand Down
4 changes: 3 additions & 1 deletion config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,9 @@

get '/sign_up' => 'users#new', as: 'sign_up' if Clearance.configuration.allow_sign_up?

resources :organizations, only: [:index, :show], param: :handle, constraints: { handle: Patterns::ROUTE_PATTERN }
resources :organizations, only: %i[index show edit update], param: :handle, constraints: { handle: Patterns::ROUTE_PATTERN } do
resources :gems, only: :index
end
namespace :organizations, as: :organization do
resource :onboarding, only: %i[index destroy], controller: "onboarding"
namespace :onboarding do
Expand Down
25 changes: 25 additions & 0 deletions test/integration/organizations/gems_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
require "test_helper"

class Organizations::GemsTest < ActionDispatch::IntegrationTest
setup do
@user = create(:user, remember_token_expires_at: Gemcutter::REMEMBER_FOR.from_now)
post session_path(session: { who: @user.handle, password: PasswordHelpers::SECURE_TEST_PASSWORD })
end

test "should get index" do
@organization = create(:organization, owners: [@user])
@organization.rubygems << create(:rubygem, name: "arrakis", number: "1.0.0")

get "/organizations/#{@organization.to_param}/gems"

assert page.has_content? "arrakis"
end

test "should get index with no gems" do
@organization = create(:organization, owners: [@user])

get "/organizations/#{@organization.to_param}/gems"

assert page.has_content? "No gems yet"
end
end
63 changes: 63 additions & 0 deletions test/integration/organizations_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
require "test_helper"

class OrganizationsTest < ActionDispatch::IntegrationTest
setup do
@user = create(:user, remember_token_expires_at: Gemcutter::REMEMBER_FOR.from_now)
post session_path(session: { who: @user.handle, password: PasswordHelpers::SECURE_TEST_PASSWORD })
end

test "should show an organization" do
@organization = create(:organization, owners: [@user])
@organization.rubygems << create(:rubygem, name: "arrakis", number: "1.0.0")

get "/organizations/#{@organization.to_param}"

assert_response :success
assert page.has_content? "arrakis"
end

test "should render not found when an organization doesn't exist" do
get "/organizations/notfound"

assert_response :not_found
end


test "should list no organization for a user with none" do
get "/organizations"

assert_response :success
end

test "should list organizations for a user" do
@organization = create(:organization, owners: [@user])

get "/organizations"

assert_response :success
assert page.has_content? @organization.name
end

test "should render organization edit form" do
@organization = create(:organization, owners: [@user])

get "/organizations/#{@organization.to_param}/edit"

assert_response :success
assert_select "form[action=?]", organization_path(@organization)
assert_select "input[name=?]", "organization[name]"
end

test "should update an organization display name" do
@organization = create(:organization, owners: [@user])

patch "/organizations/#{@organization.to_param}", params: {
organization: { name: "New Name" }
}

assert_redirected_to organization_path(@organization)
follow_redirect!

assert page.has_content? "New Name"
end
end

0 comments on commit 8521bc3

Please sign in to comment.