| @@ -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. | |||||
| @@ -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/ | |||||
| @@ -0,0 +1,23 @@ | |||||
| class Admins::OrganizationsController < Admins::BaseController | |||||
| before_action :finder_org, except: [:index] | |||||
| def index | |||||
| @orgs = paginate Organization.all | |||||
| 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 | |||||
| @@ -0,0 +1,2 @@ | |||||
| module Admins::OrganizationsHelper | |||||
| end | |||||
| @@ -144,6 +144,57 @@ class Organization < Owner | |||||
| end | end | ||||
| end | end | ||||
| def projects_count | |||||
| Project.where( user_id: self.id).count | |||||
| end | |||||
| # 用户账号状态 | |||||
| def active? | |||||
| status == User::STATUS_ACTIVE | |||||
| end | |||||
| def registered? | |||||
| status == User::STATUS_REGISTERED | |||||
| end | |||||
| def locked? | |||||
| status == User::STATUS_LOCKED | |||||
| end | |||||
| def need_edit_info? | |||||
| status == User::STATUS_EDIT_INFO | |||||
| end | |||||
| def activate | |||||
| self.status = User::STATUS_ACTIVE | |||||
| end | |||||
| def register | |||||
| self.status = User::STATUS_REGISTERED | |||||
| end | |||||
| def lock | |||||
| self.status = User::STATUS_LOCKED | |||||
| end | |||||
| def need_edit_info | |||||
| self.status = User::STATUS_EDIT_INFO | |||||
| end | |||||
| def activate! | |||||
| update_attribute(:status, STATUS_ACTIVE) | |||||
| prohibit_gitea_user_login!(false) | |||||
| end | |||||
| def register! | |||||
| update_attribute(:status, STATUS_REGISTERED) | |||||
| end | |||||
| def lock! | |||||
| update_attribute(:status, STATUS_LOCKED) | |||||
| prohibit_gitea_user_login! | |||||
| end | |||||
| def real_name | def real_name | ||||
| name = lastname + firstname | name = lastname + firstname | ||||
| name = name.blank? ? (nickname.blank? ? login : nickname) : name | name = name.blank? ? (nickname.blank? ? login : nickname) : name | ||||
| @@ -0,0 +1,28 @@ | |||||
| class Admins::DeleteOrganizationService < Gitea::ClientService | |||||
| attr_reader :token, :name | |||||
| def initialize(name) | |||||
| @name = name | |||||
| end | |||||
| def call | |||||
| response = delete(url, params) | |||||
| render_status(response) | |||||
| end | |||||
| private | |||||
| def params | |||||
| Hash.new.merge(token: token) | |||||
| end | |||||
| def url | |||||
| "/orgs/#{name}".freeze | |||||
| end | |||||
| def token | |||||
| { | |||||
| username: GiteaService.gitea_config[:access_key_id], | |||||
| password: GiteaService.gitea_config[:access_key_secret] | |||||
| } | |||||
| end | |||||
| end | |||||
| @@ -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> | |||||
| @@ -0,0 +1,8 @@ | |||||
| <% define_admin_breadcrumbs do %> | |||||
| <% add_admin_breadcrumb('组织管理', admins_organizations_path) %> | |||||
| <% end %> | |||||
| <div class="box admin-list-container organizations-list-container"> | |||||
| <%= render partial: 'admins/organizations/shared/org_list', locals: { organizations: @orgs } %> | |||||
| </div> | |||||
| @@ -0,0 +1 @@ | |||||
| $('.users-list-container').html("<%= j( render partial: 'admins/organizations/shared/org_list', locals: { organizations: @orgs } ) %>"); | |||||
| @@ -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 | |||||
| @@ -0,0 +1,45 @@ | |||||
| <table class="table table-hover users-list-table"> | |||||
| <thead class="thead-light"> | |||||
| <tr> | |||||
| <th width="4%">序号</th> | |||||
| <th width="8%" class="text-left">login</th> | |||||
| <th width="8%" class="text-left">昵称</th> | |||||
| <th width="10%"><%= sort_tag('创建于', name: 'created_on', path: admins_organizations_path) %></th> | |||||
| <th width="10%"><%= sort_tag('最后登录', name: 'last_login_on', path: admins_organizations_path) %></th> | |||||
| <th width="12%">项目数</th> | |||||
| <th width="14%">操作</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><%= display_text(org.last_login_on&.strftime('%Y-%m-%d %H:%M')) %></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 } %> | |||||
| @@ -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> | |||||
| @@ -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> | |||||
| @@ -15,14 +15,15 @@ | |||||
| <ul class="list-unstyled components"> | <ul class="list-unstyled components"> | ||||
| <li><%= sidebar_item(admins_path, '概览', icon: 'dashboard', controller: 'admins-dashboards') %></li> | <li><%= sidebar_item(admins_path, '概览', icon: 'dashboard', controller: 'admins-dashboards') %></li> | ||||
| <li> | <li> | ||||
| <%= sidebar_item_group('#user-submenu', '排行榜', icon: 'user') do %> | |||||
| <%= sidebar_item_group('#rank-submenu', '排行榜', icon: 'calendar') do %> | |||||
| <li><%= sidebar_item(admins_users_rank_index_path, '用户排行榜', icon: 'user', controller: 'admins-users_rank') %></li> | <li><%= sidebar_item(admins_users_rank_index_path, '用户排行榜', icon: 'user', controller: 'admins-users_rank') %></li> | ||||
| <li><%= sidebar_item(admins_projects_rank_index_path, '项目排行榜', icon: 'user', controller: 'admins-projects_rank') %></li> | |||||
| <li><%= sidebar_item(admins_projects_rank_index_path, '项目排行榜', icon: 'database', controller: 'admins-projects_rank') %></li> | |||||
| <% end %> | <% end %> | ||||
| </li> | </li> | ||||
| <li> | <li> | ||||
| <%= sidebar_item_group('#user-submenu', '用户', icon: 'user') do %> | <%= sidebar_item_group('#user-submenu', '用户', icon: 'user') do %> | ||||
| <li><%= sidebar_item(admins_users_path, '用户列表', icon: 'user', controller: 'admins-users') %></li> | <li><%= sidebar_item(admins_users_path, '用户列表', icon: 'user', controller: 'admins-users') %></li> | ||||
| <li><%= sidebar_item(admins_organizations_path, '组织列表', icon: 'user', controller: 'admins-organizations') %></li> | |||||
| <% end %> | <% end %> | ||||
| </li> | </li> | ||||
| <li> | <li> | ||||
| @@ -816,7 +816,7 @@ Rails.application.routes.draw do | |||||
| resources :school_statistics, only: [:index] do | resources :school_statistics, only: [:index] do | ||||
| get :contrast, on: :collection | get :contrast, on: :collection | ||||
| end | end | ||||
| resources :organizations, only: [:index, :edit, :show, :destroy] | |||||
| resources :users, only: [:index, :edit, :update, :destroy] do | resources :users, only: [:index, :edit, :update, :destroy] do | ||||
| member do | member do | ||||
| post :reward_grade | post :reward_grade | ||||
| @@ -0,0 +1,5 @@ | |||||
| require 'rails_helper' | |||||
| RSpec.describe Admins::OrganizationsController, type: :controller do | |||||
| end | |||||
| @@ -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 | |||||