Browse Source

Merge pull request '用户版块增加组织列表' (#25) from KingChan/forgeplus:chenjing into standalone_develop

pull/342/head
xxq250 3 years ago
parent
commit
84029bf49a
18 changed files with 311 additions and 1 deletions
  1. +2
    -0
      app/assets/javascripts/admins/organizations.js
  2. +3
    -0
      app/assets/stylesheets/admins/organizations.scss
  3. +27
    -0
      app/controllers/admins/organizations_controller.rb
  4. +2
    -0
      app/helpers/admins/organizations_helper.rb
  5. +12
    -0
      app/models/organization.rb
  6. +21
    -0
      app/queries/admins/organization_query.rb
  7. +19
    -0
      app/services/admins/delete_organization_service.rb
  8. +41
    -0
      app/views/admins/organizations/edit.html.erb
  9. +17
    -0
      app/views/admins/organizations/index.html.erb
  10. +1
    -0
      app/views/admins/organizations/index.js.erb
  11. +6
    -0
      app/views/admins/organizations/index.json.jbuilder
  12. +47
    -0
      app/views/admins/organizations/shared/_org_list.html.erb
  13. +53
    -0
      app/views/admins/organizations/shared/_project_list.html.erb
  14. +38
    -0
      app/views/admins/organizations/show.html.erb
  15. +1
    -0
      app/views/admins/shared/_sidebar.html.erb
  16. +1
    -1
      config/routes.rb
  17. +5
    -0
      spec/controllers/admins/organizations_controller_spec.rb
  18. +15
    -0
      spec/helpers/admins/organizations_helper_spec.rb

+ 2
- 0
app/assets/javascripts/admins/organizations.js View File

@@ -0,0 +1,2 @@
// Place all the behaviors and hooks related to the matching controller here.
// All this logic will automatically be available in application.js.

+ 3
- 0
app/assets/stylesheets/admins/organizations.scss View File

@@ -0,0 +1,3 @@
// Place all the styles related to the admins/organizations controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/

+ 27
- 0
app/controllers/admins/organizations_controller.rb View File

@@ -0,0 +1,27 @@
class Admins::OrganizationsController < Admins::BaseController
before_action :finder_org, except: [:index]

def index
params[:sort_by] = params[:sort_by].presence || 'created_on'
params[:sort_direction] = params[:sort_direction].presence || 'desc'

orgs = Admins::OrganizationQuery.call(params)
@orgs = paginate orgs
end

def show
end

def destroy
@org.destroy!
Admins::DeleteOrganizationService.call(@org.login)
render_delete_success
end

private

def finder_org
@org = Organization.find(params[:id])
end
end

+ 2
- 0
app/helpers/admins/organizations_helper.rb View File

@@ -0,0 +1,2 @@
module Admins::OrganizationsHelper
end

+ 12
- 0
app/models/organization.rb View File

@@ -144,6 +144,18 @@ class Organization < Owner
end
end

def projects_count
Project.where( user_id: self.id).count
end

def teams_count
teams.count
end

def organization_users_count
organization_users.count
end

def real_name
name = lastname + firstname
name = name.blank? ? (nickname.blank? ? login : nickname) : name


+ 21
- 0
app/queries/admins/organization_query.rb View File

@@ -0,0 +1,21 @@
class Admins::OrganizationQuery < ApplicationQuery
include CustomSortable
attr_reader :params
sort_columns :created_on, :last_login_on, :experience, :grade, default_by: :created_on, default_direction: :desc

def initialize(params)
@params = params
end

def call
orgs = Organization.all
# 关键字检索
keyword = params[:keyword].to_s.strip.presence
if keyword
sql = 'nickname LIKE :keyword OR login LIKE :keyword'
orgs = orgs.where(sql, keyword: "%#{keyword}%")
end
custom_sort(orgs, params[:sort_by], params[:sort_direction])
end
end

+ 19
- 0
app/services/admins/delete_organization_service.rb View File

@@ -0,0 +1,19 @@
class Admins::DeleteOrganizationService < Gitea::ClientService
attr_reader :token, :name
def initialize(name)
@name = name
end

def call
Gitea::Organization::DeleteService.call(token,name)
end
private
def token
{
username: GiteaService.gitea_config[:access_key_id],
password: GiteaService.gitea_config[:access_key_secret]
}
end
end

+ 41
- 0
app/views/admins/organizations/edit.html.erb View File

@@ -0,0 +1,41 @@
<%
define_admin_breadcrumbs do
add_admin_breadcrumb('组织管理', admins_organizations_path)
add_admin_breadcrumb('组织详情')
end
%>

<div class="box user-edit-container">
<div class="user-info mb-4 row">
<%= link_to "/#{@org.login}", class: 'user-info-avatar col-md-1', target: '_blank', data: { toggle: 'tooltip', title: '个人中心' } do %>
<img src="/<%= url_to_avatar(@org) %>" class="rounded-circle" width="80" height="80" />
<% end %>
<div class="d-flex flex-column justify-content-between col-md-3 user-info-content">
<div class="user-info-name flex"><%= @org.nickname %> | <%= @org.id %> | <%= @org.login %></div>

<div class="user-info-last-login">最近登录:<%= @org.last_login_on&.strftime('%Y-%m-%d %H:%M') %></div>
</div>
</div>

<%= simple_form_for(@org, url: admins_organization_path(@org)) do |f| %>

<div><h6>基本信息</h6></div>
<div class="form-group px-2">
<div class="form-row">
<%= f.input :login, label: '登录名', wrapper_html: { class: 'col-md-3' }, input_html: { readonly: true, class: 'col-md-11', value: @org.login } %>
</div>

<div class="form-row">
<%= f.input :lastname, label: '姓名', wrapper_html: { class: 'col-md-3' }, input_html: { class: 'col-md-11', value: @org.real_name } %>
</div>

</div>

<div class="form-row mt-4">
<%= f.button :submit, value: '保存', class: 'btn-primary mr-3 px-4' %>
<%= link_to '取消', admins_organizations_path, class: 'btn btn-secondary px-4' %>
</div>
<% end %>
</div>

+ 17
- 0
app/views/admins/organizations/index.html.erb View File

@@ -0,0 +1,17 @@
<% define_admin_breadcrumbs do %>
<% add_admin_breadcrumb('组织管理', admins_organizations_path) %>
<% end %>
<div class="box search-form-container user-list-form">
<%= form_tag(admins_organizations_path, method: :get, class: 'form-inline search-form flex-1', remote: true) do %>

<%= text_field_tag(:keyword, params[:keyword], class: 'form-control col-sm-2 ml-3', placeholder: 'login/昵称') %>
<%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %>
<% end %>
</div>

<div class="box admin-list-container organizations-list-container">
<%= render partial: 'admins/organizations/shared/org_list', locals: { organizations: @orgs } %>
</div>


+ 1
- 0
app/views/admins/organizations/index.js.erb View File

@@ -0,0 +1 @@
$('.organizations-list-container').html("<%= j( render partial: 'admins/organizations/shared/org_list', locals: { organizations: @orgs } ) %>");

+ 6
- 0
app/views/admins/organizations/index.json.jbuilder View File

@@ -0,0 +1,6 @@
json.count @orgs.total_count
json.orgs do
json.array! @orgs.each do |org|
json.extract! org, :id, :login, :nickname
end
end

+ 47
- 0
app/views/admins/organizations/shared/_org_list.html.erb View File

@@ -0,0 +1,47 @@
<table class="table table-hover users-list-table">
<thead class="thead-light">
<tr>
<th width="5%">序号</th>
<th width="8%" class="text-left">login</th>
<th width="10%" class="text-left">昵称</th>
<th width="15%"><%= sort_tag('创建于', name: 'created_on', path: admins_organizations_path) %></th>
<th width="8%" >团队</th>
<th width="8%" >成员</th>
<th width="8%">项目数</th>
<th width="10%">操作</th>
</tr>
</thead>
<tbody>
<% if organizations.present? %>
<% organizations.each_with_index do |org, index| %>
<tr class="org-item-<%= org.id %>">
<td><%= list_index_no((params[:page] || 1).to_i, index) %></td>
<td class="text-left">
<%= link_to "/#{org.login}", target: '_blank' do %>
<%= overflow_hidden_span org.login, width: 100 %>
<% end %>
</td>
<td><%= org.nickname %> </td>
<td><%= display_text(org.created_on&.strftime('%Y-%m-%d %H:%M')) %></td>
<td><%= link_to org.teams_count, "/#{org.login}", target: "_blank" %></td>
<td><%= link_to org.organization_users_count, "/#{org.login}", target: "_blank" %></td>
<td><%= link_to org.projects_count, "/#{org.login}", target: "_blank" %></td>
<td class="action-container">
<%= link_to '查看', admins_organization_path(org), class: 'action' %>
<div class="d-inline">
<%= javascript_void_link('更多', class: 'action dropdown-toggle', 'data-toggle': 'dropdown', 'aria-haspopup': true, 'aria-expanded': false) %>
<div class="dropdown-menu more-action-dropdown">

<%= delete_link '删除', admins_organization_path(org, element: ".user-item-#{org.id}"), class: 'dropdown-item delete-user-action' %>
</div>
</div>
</td>
</tr>
<% end %>
<% else %>
<%= render 'admins/shared/no_data_for_table' %>
<% end %>
</tbody>
</table>

<%= render partial: 'admins/shared/paginate', locals: { objects: organizations } %>

+ 53
- 0
app/views/admins/organizations/shared/_project_list.html.erb View File

@@ -0,0 +1,53 @@
<table class="table table-hover text-center subject-list-table">
<thead class="thead-light">
<tr>
<th width="5%">序号</th>
<th width="6%">ID</th>
<th width="20%" class="text-left">项目名称</th>
<th width="5%">公开</th>
<th width="5%">推荐</th>
<th width="5%">Issues</th>
<th width="5%">资源</th>
<th width="5%">Pulls</th>
<th width="6%">里程碑</th>
<th width="5%">成员</th>
<th width="12%">管理员</th>
<th width="15%"><%= sort_tag('创建时间', name: 'created_on', path: admins_projects_path) %></th>
<th width="15%">操作</th>
</tr>
</thead>
<tbody>
<% if projects.present? %>
<% projects.each_with_index do |project, index| %>
<tr class="project-item-<%= project.id %>">
<td><%= list_index_no((params[:page] || 1).to_i, index) %></td>
<td><%= project.id %></td>
<td class="text-left">
<%= link_to(project.name, "/#{project&.owner&.login}/#{project.identifier}", target: '_blank') %>
</td>
<td><%= project.is_public ? '√' : '' %></td>
<td><%= project.recommend ? '√' : '' %></td>
<td><%= project.issues.size %></td>
<td><%= project.attachments.size %></td>
<td><%= project&.pull_requests_count %></td>
<td><%= project.versions.size %></td>
<td><%= project.members.size %></td>
<td>
<%= link_to_project(project) %>
</td>
<td><%= project.created_on&.strftime('%Y-%m-%d %H:%M') %></td>
<td class="action-container">
<% if project.is_public %>
<%= javascript_void_link '推荐', class: 'action recommend-action', data: { id: project.id }, style: project.recommend ? 'display: none;' : '' %>
<%= javascript_void_link '取消推荐', class: 'action unrecommend-action', data: { id: project.id }, style: project.recommend ? '' : 'display: none;' %>
<%= link_to "设置推荐等级", edit_admins_project_path(project.id), remote: true, class: "action edit-recommend-action", style: project.recommend ? '' : 'display: none;' %>
<% end %>
<%= link_to "删除", admins_project_path(project.id), method: :delete, data:{confirm: "确认删除的吗?"}, class: "delete-project-action" %>
</td>
</tr>
<% end %>
<% else %>
<%= render 'admins/shared/no_data_for_table' %>
<% end %>
</tbody>
</table>

+ 38
- 0
app/views/admins/organizations/show.html.erb View File

@@ -0,0 +1,38 @@
<%
define_admin_breadcrumbs do
add_admin_breadcrumb('组织管理', admins_organizations_path)
add_admin_breadcrumb('组织详情')
end
%>

<div class="box user-edit-container">
<div class="user-info mb-4 row">
<%= link_to "/#{@org.login}", class: 'user-info-avatar col-md-1', target: '_blank', data: { toggle: 'tooltip', title: '个人中心' } do %>
<img src="/<%= url_to_avatar(@org) %>" class="rounded-circle" width="80" height="80" />
<% end %>
<div class="d-flex flex-column justify-content-between col-md-3 user-info-content">
<div class="user-info-name flex"><%= @org.nickname %> | <%= @org.id %> | <%= @org.login %></div>
<div class="user-info-last-login">最近登录:<%= @org.last_login_on&.strftime('%Y-%m-%d %H:%M') %></div>
</div>
</div>

<%= simple_form_for(@org, url: admins_organization_path(@org)) do |f| %>

<div><h6>基本信息</h6></div>
<div class="form-group px-2">
<div class="form-row">
<%= f.input :login, label: '登录名', wrapper_html: { class: 'col-md-3' }, input_html: { readonly: true, class: 'col-md-11', value: @org.login } %>
</div>

<div class="form-row">
<%= f.input :lastname, label: '姓名', wrapper_html: { class: 'col-md-3' }, input_html: { readonly: true, class: 'col-md-11', value: @org.real_name } %>
</div>

</div>
<% end %>
<h3> 组织项目 </h3>
<%= render partial: 'admins/organizations/shared/project_list', locals: { projects: @org.projects } %>

</div>

+ 1
- 0
app/views/admins/shared/_sidebar.html.erb View File

@@ -23,6 +23,7 @@
<li>
<%= sidebar_item_group('#user-submenu', '用户', icon: 'user') do %>
<li><%= sidebar_item(admins_users_path, '用户列表', icon: 'user', controller: 'admins-users') %></li>
<li><%= sidebar_item(admins_organizations_path, '组织列表', icon: 'user', controller: 'admins-organization') %></li>
<% end %>
</li>
<li>


+ 1
- 1
config/routes.rb View File

@@ -816,7 +816,7 @@ Rails.application.routes.draw do
resources :school_statistics, only: [:index] do
get :contrast, on: :collection
end
resources :organizations, only: [:index, :edit, :show, :destroy]
resources :users, only: [:index, :edit, :update, :destroy] do
member do
post :reward_grade


+ 5
- 0
spec/controllers/admins/organizations_controller_spec.rb View File

@@ -0,0 +1,5 @@
require 'rails_helper'

RSpec.describe Admins::OrganizationsController, type: :controller do

end

+ 15
- 0
spec/helpers/admins/organizations_helper_spec.rb View File

@@ -0,0 +1,15 @@
require 'rails_helper'

# Specs in this file have access to a helper object that includes
# the Admins::OrganizationsHelper. For example:
#
# describe Admins::OrganizationsHelper do
# describe "string concat" do
# it "concats two strings with spaces" do
# expect(helper.concat_strings("this","that")).to eq("this that")
# end
# end
# end
RSpec.describe Admins::OrganizationsHelper, type: :helper do
pending "add some examples to (or delete) #{__FILE__}"
end

Loading…
Cancel
Save