diff --git a/app/controllers/projects/project_units_controller.rb b/app/controllers/projects/project_units_controller.rb new file mode 100644 index 00000000..90bc64a7 --- /dev/null +++ b/app/controllers/projects/project_units_controller.rb @@ -0,0 +1,24 @@ +class Projects::ProjectUnitsController < Projects::BaseController + def index + @project_units = @project.project_units + end + + def create + if current_user.admin? || @project.owner?(current_user) + ActiveRecord::Base.transaction do + ProjectUnit.update_by_unit_types!(@project, unit_types) + render_ok + end + else + render_forbidden('你没有权限操作') + end + rescue Exception => e + uid_logger_error(e.message) + tip_exception(e.message) + end + + private + def unit_types + params.fetch(:unit_types, []) + end +end \ No newline at end of file diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index c8f3027d..573dbba8 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -2,11 +2,26 @@ class ProjectsController < ApplicationController include ApplicationHelper include OperateProjectAbilityAble include ProjectsHelper - before_action :require_login, except: %i[index branches group_type_list simple show fork_users praise_users watch_users recommend about] + before_action :require_login, except: %i[index branches group_type_list simple show fork_users praise_users watch_users recommend about menu_list] before_action :load_project, except: %i[index group_type_list migrate create recommend] before_action :authorizate_user_can_edit_project!, only: %i[update] before_action :project_public?, only: %i[fork_users praise_users watch_users] + def menu_list + menu = [] + + menu.append(menu_hash_by_name("home")) + menu.append(menu_hash_by_name("code")) if @project.has_menu_permission("code") + menu.append(menu_hash_by_name("issues")) if @project.has_menu_permission("issues") + menu.append(menu_hash_by_name("pulls")) if @project.has_menu_permission("pulls") + menu.append(menu_hash_by_name("devops")) if @project.has_menu_permission("devops") + menu.append(menu_hash_by_name("versions")) if @project.has_menu_permission("versions") + menu.append(menu_hash_by_name("activity")) + menu.append(menu_hash_by_name("setting")) if current_user.admin? || @project.owner?(current_user) + + render json: menu + end + def index scope = Projects::ListQuery.call(params) @@ -73,7 +88,8 @@ class ProjectsController < ApplicationController private = params[:private] gitea_params = { private: private, - default_branch: params[:default_branch] + default_branch: params[:default_branch], + website: params[:website] } if [true, false].include? private new_project_params = project_params.except(:private).merge(is_public: !private) @@ -162,7 +178,7 @@ class ProjectsController < ApplicationController private def project_params - params.permit(:user_id, :name, :description, :repository_name, + params.permit(:user_id, :name, :description, :repository_name, :website, :project_category_id, :project_language_id, :license_id, :ignore_id, :private) end diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb index 6683dde4..cd07803d 100644 --- a/app/controllers/repositories_controller.rb +++ b/app/controllers/repositories_controller.rb @@ -7,10 +7,29 @@ class RepositoriesController < ApplicationController before_action :load_repository before_action :authorizate!, except: [:sync_mirror, :tags, :commit] before_action :authorizate_user_can_edit_repo!, only: %i[sync_mirror] - before_action :get_ref, only: %i[entries sub_entries top_counts] + before_action :get_ref, only: %i[entries sub_entries top_counts file] before_action :get_latest_commit, only: %i[entries sub_entries top_counts] before_action :get_statistics, only: %i[top_counts] + def files + result = @project.educoder? ? nil : Gitea::Repository::Files::GetService.call(@owner, @project.identifier, @ref, params[:search], @owner.gitea_token) + render json: result + end + + # 新版项目详情 + def detail + @user = current_user + @result = Repositories::DetailService.call(@owner, @repository, @user) + @project_fork_id = @project.try(:forked_from_project_id) + if @project_fork_id.present? + @fork_project = Project.find_by(id: @project_fork_id) + @fork_project_user = @fork_project.owner + end + rescue Exception => e + uid_logger_error(e.message) + tip_exception(e.message) + end + def show @user = current_user @repo = @project.repository @@ -87,6 +106,10 @@ class RepositoriesController < ApplicationController @tags = Gitea::Repository::Tags::ListService.call(current_user&.gitea_token, @owner.login, @project.identifier, {page: params[:page], limit: params[:limit]}) end + def contributors + @contributors = Gitea::Repository::Contributors::GetService.call(@owner, @repository.identifier) + end + def edit return render_forbidden if !@project.manager?(current_user) && !current_user.admin? end @@ -187,7 +210,7 @@ class RepositoriesController < ApplicationController end def get_ref - @ref = params[:ref] || "master" + @ref = params[:ref] || @project.default_branch end def get_latest_commit diff --git a/app/docs/slate/source/includes/_projects.md b/app/docs/slate/source/includes/_projects.md index 1fbbd0da..0a46d8cc 100644 --- a/app/docs/slate/source/includes/_projects.md +++ b/app/docs/slate/source/includes/_projects.md @@ -168,6 +168,55 @@ Remember — a happy kitten is an authenticated kitten! +## 项目导航 +获取项目导航信息 + +> 示例: + +```shell +curl -X GET \ +http://localhost:3000/api/yystopf/ceshi/menu_list | jq +``` + +```javascript +await octokit.request('GET /api/yystopf/ceshi/menu_list') +``` + +### HTTP 请求 +`GET api/:owner/:repo/menu_list` + +### 请求参数 +参数 | 必选 | 默认 | 类型 | 字段说明 +--------- | ------- | ------- | -------- | ---------- +owner |是| |string |用户登录名 +repo |是| |string |项目标识identifier + +### 返回字段说明 +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +menu_name |string|导航名称, home:主页,code:代码库,issues:易修,pulls:合并请求,devops:工作流,versions:里程碑,activity:动态,setting:仓库设置 + + +> 返回的JSON示例: + +```json +[ + { + "menu_name": "home" + }, + { + "menu_name": "code" + }, + { + "menu_name": "pulls" + }, + { + "menu_name": "activity" + } +] +``` + + ## 项目主页 获取项目主页信息 @@ -212,6 +261,84 @@ attachments |array|附件 Remember — a happy kitten is an authenticated kitten! +## 项目模块信息 +项目模块信息 + +> 示例: + +```shell +curl -X GET \ +http://localhost:3000/api/yystopf/ceshi/project_units.json +``` + +```javascript +await octokit.request('GET /api/yystopf/ceshi/project_units') +``` + +### HTTP 请求 +`GET /api/yystopf/ceshi/project_units` + +### 返回字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|type |string|模块名称 | + +> 返回的JSON示例: + +```json +[ + { + "type": "code" + }, + { + "type": "pulls" + }, + { + "type": "issues" + } +] +``` + +## 更改项目模块展示 +更改项目模块展示 + +> 示例: + +```shell +curl -X POST \ +-H "accept: application/json" \ +-H "Content-Type: application/json" \ +-d "{ \"unit_typs\": [\"code\", \"pulls\"]}" \ +http://localhost:3000/api/yystopf/ceshi/project_units.json +``` + +```javascript +await octokit.request('POST /api/yystopf/ceshi/project_units') +``` + +### HTTP 请求 +`POST /api/yystopf/ceshi/project_units` + +### 请求参数 +参数 | 必选 | 默认 | 类型 | 字段说明 +--------- | ------- | ------- | -------- | ---------- +|unit_types |是| |array | 项目模块内容, 支持以下参数:code:代码库,issues:易修,pulls:合并请求,devops:工作流,versions:里程碑 | + + +### 返回字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|status |int|返回状态, 0: 表示操作成功 | +|message |string|返回信息说明| + +> 返回的JSON示例: + +```json +{ + "status": 0, + "message": "success" +} +``` ## 创建项目 创建项目 diff --git a/app/docs/slate/source/includes/_repositories.md b/app/docs/slate/source/includes/_repositories.md index b57df90f..40d3ba2f 100644 --- a/app/docs/slate/source/includes/_repositories.md +++ b/app/docs/slate/source/includes/_repositories.md @@ -97,6 +97,182 @@ await octokit.request('GET /api/jasder/jasder_test/simple.json') } ``` +## 仓库详情(新版) +仓库详情 + +> 示例: + +```shell +curl -X GET http://localhost:3000/api/yystopf/ceshi/detail.json +``` + +```javascript +await octokit.request('GET /api/yystopf/ceshi/detail.json') +``` + +### HTTP 请求 +`GET /api/:owner/:repo/detail` + +### 请求参数: +参数 | 必选 | 默认 | 类型 | 字段说明 +--------- | ------- | ------- | -------- | ---------- +|owner |是| |string |用户登录名 | +|repo |是| |string |项目标识identifier | + + +### 返回字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|content |string |仓库简介 | +|website |string |仓库网址 | +|readme |string |readme文件| +|identifier |string |项目标识 | +|name |string |项目名称 | +|issues_count |int |项目issue数量| +|pull_requests_count |int |项目合并请求数量| +|project_identifier |int |项目标识| +|praises_count |int |项目点赞数量| +|forked_count |int |项目复刻数量| +|watchers_count |int |项目关注数量| +|versions_count |int |项目里程碑数量| +|version_releases_count |int |项目发行版数量| +|version_releasesed_count |int |项目发行版已发行数量| +|permission |string |项目权限| +|mirror_url |string |镜像地址| +|mirror |bool |是否为镜像项目| +|type |int |项目类型 0 普通项目 1 普通镜像项目 2 同步镜像项目| +|open_devops |int |是否开启devops| +|watched |bool |是否关注| +|praised |bool |是否点赞| +|status |int |项目状态| +|forked_from_project_id |int |fork项目id| +|fork_info |object |fork项目信息| +|size |string |仓库大小| +|ssh_url |string |项目ssh地址| +|clone_url |string |项目克隆地址| +|default_branch |string |仓库默认分支| +|empty |bool |仓库是否为空| +|full_name |string |仓库全称| +|private |bool |仓库是否为私有项目| +|license_name |string |许可证名称| +|release_versions.list.name |string |项目issue数量| +|release_versions.list.tag_name |string |发行版标签名称| +|release_versions.list.created_at |string |发行版创建时间| +|release_versions.total_count |int |发行版数量| +|branches.list.name |string |分支名称| +|branches.total_count |int |分支数量| +|tags.list.name |string |标签名称| +|tags.total_count |int |标签数量| +|contributors.list.contributions|int |贡献数量| +|contributors.list.login |string |贡献者登录名| +|contributors.list.name |string |贡献者用户名称| +|contributors.list.image_url |string |贡献者头像| +|languages |object |项目语言占比| + +> 返回的JSON示例: + +```json +{ + "content": "仓库简介", + "website": "仓库网址", + "readme": { + "type": "file", + "encoding": "base64", + "size": 9, + "name": "README.md", + "path": "README.md", + "content": "# ceshi\n\n", + "sha": "" + }, + "identifier": "ceshi", + "name": "测试项目", + "project_id": 2, + "repo_id": 2, + "issues_count": 0, + "pull_requests_count": 0, + "project_identifier": "ceshi", + "praises_count": 0, + "forked_count": 0, + "watchers_count": 0, + "versions_count": 0, + "version_releases_count": 0, + "version_releasesed_count": 0, + "permission": "Reporter", + "mirror_url": null, + "mirror": false, + "type": 0, + "open_devops": false, + "watched": false, + "praised": false, + "status": 1, + "forked_from_project_id": 1, + "fork_info": { + "fork_form_name": "测试项目", + "fork_project_user_login": "ceshi_org", + "fork_project_identifier": "ceshi", + "fork_project_user_name": "ceshi_org" + }, + "size": "25.0 KB", + "ssh_url": "virus@localhost:yystopf/ceshi.git", + "clone_url": "http://localhost:10080/yystopf/ceshi.git", + "default_branch": "master", + "empty": false, + "full_name": "yystopf/ceshi", + "private": false, + "license_name": "gnu-javamail-exception", + "release_versions": { + "list": [ + { + "id": 2, + "name": "vvvv", + "tag_name": "v1.1", + "created_at": "2019-07-18 10:16" + } + ], + "total_count": 1 + }, + "branches": { + "list": [ + { + "name": "master" + } + ], + "total_count": 1 + }, + "tags": { + "list": [ + { + "name": "v1.1" + }, + { + "name": "v1.0" + } + ], + "total_count": 2 + }, + "contributors": { + "list": [ + { + "contributions": 1, + "gid": 2, + "login": "yystopf", + "type": "User", + "name": "yystopf", + "image_url": "avatars/User/b" + } + ], + "total_count": 1 + }, + "languages": { + "HTML": "50.9%", + "Ruby": "25.6%", + "JavaScript": "21.4%", + "CSS": "1.3%", + "CoffeeScript": "0.7%", + "Shell": "0.1%" + } +} +``` ## 编辑仓库信息 编辑仓库信息 @@ -463,6 +639,78 @@ await octokit.request('GET /api/jasder/jasder_test/collaborators.json') Success Data. +## 获取仓库所有文件 +获取仓库所有文件 + +> 示例: + +```shell +curl -X GET \ +-d "ref=develop" \ +http://localhost:3000/api/yystopf/ceshi/files.json +``` + +```javascript +await octokit.request('GET /api/yystopf/ceshi/files.json') +``` + +### HTTP 请求 +`GET /api/:owner/:repo/files` + +### 请求参数: +参数 | 必选 | 默认 | 类型 | 字段说明 +--------- | ------- | ------- | -------- | ---------- +|owner |是| |string |用户登录名 | +|repo |是| |string |项目标识identifier | +|search |否| |string |文件搜索关键词 | +|ref |是| |string |分支名,默认为仓库默认分支 | + + +### 返回字段说明: +参数 | 类型 | 字段说明 +--------- | ----------- | ----------- +|name |string |文件名称| +|path |string |文件路径| +|sha |string |文件标识| +|type |string |文件类型| +|size |int |文件大小| +|url |string |文件地址| + + +> 返回的JSON示例: + +```json +[ + { + "name": ".gitignore", + "path": ".gitignore", + "sha": "f83922d01ae60f6e637a1a2b9f08871b4f87dfc8", + "type": "file", + "size": 63, + "url": "http://localhost:10080/api/v1/repos/yystopf/ceshi/contents/.gitignore?ref=master", + "html_url": "http://localhost:10080/yystopf/ceshi/src/branch/master/.gitignore" + }, + { + "name": "LICENSE", + "path": "LICENSE", + "sha": "8f3b9ab0d08afd3a624d822e3971a2f42b3bc2b9", + "type": "file", + "size": 341, + "url": "http://localhost:10080/api/v1/repos/yystopf/ceshi/contents/LICENSE?ref=master", + "html_url": "http://localhost:10080/yystopf/ceshi/src/branch/master/LICENSE" + }, + { + "name": "README.md", + "path": "README.md", + "sha": "1bc8a60ac6ddc876ebc4b60fc68991435bfad93e", + "type": "file", + "size": 9, + "url": "http://localhost:10080/api/v1/repos/yystopf/ceshi/contents/README.md?ref=master", + "html_url": "http://localhost:10080/yystopf/ceshi/src/branch/master/README.md" + } +] +``` + ## 获取仓库代码目录 获取仓库代码目录 diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 6fbc22eb..b212b50e 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -1,4 +1,9 @@ module ProjectsHelper + def menu_hash_by_name(name) + { + menu_name: name + } + end def render_zh_project_type(project_type) case project_type diff --git a/app/models/concerns/project_operable.rb b/app/models/concerns/project_operable.rb index 5e8bf43d..e151613d 100644 --- a/app/models/concerns/project_operable.rb +++ b/app/models/concerns/project_operable.rb @@ -89,4 +89,7 @@ module ProjectOperable member.member_roles.create!(role: role) end + def has_menu_permission(unit_type) + self.project_units.where(unit_type: unit_type).exists? + end end diff --git a/app/models/project.rb b/app/models/project.rb index a5beb448..cde2f101 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -1,73 +1,76 @@ -# == Schema Information -# -# Table name: projects -# -# id :integer not null, primary key -# name :string(255) default(""), not null -# description :text(4294967295) -# homepage :string(255) default("") -# is_public :boolean default("1"), not null -# parent_id :integer -# created_on :datetime -# updated_on :datetime -# identifier :string(255) -# status :integer default("1"), not null -# lft :integer -# rgt :integer -# inherit_members :boolean default("0"), not null -# project_type :integer default("0") -# hidden_repo :boolean default("0"), not null -# attachmenttype :integer default("1") -# user_id :integer -# dts_test :integer default("0") -# enterprise_name :string(255) -# organization_id :integer -# project_new_type :integer -# gpid :integer -# forked_from_project_id :integer -# forked_count :integer default("0") -# publish_resource :integer default("0") -# visits :integer default("0") -# hot :integer default("0") -# invite_code :string(255) -# qrcode :string(255) -# qrcode_expiretime :integer default("0") -# script :text(65535) -# training_status :integer default("0") -# rep_identifier :string(255) -# project_category_id :integer -# project_language_id :integer -# license_id :integer -# ignore_id :integer -# praises_count :integer default("0") -# watchers_count :integer default("0") -# issues_count :integer default("0") -# pull_requests_count :integer default("0") -# language :string(255) -# versions_count :integer default("0") -# issue_tags_count :integer default("0") -# closed_issues_count :integer default("0") -# open_devops :boolean default("0") -# gitea_webhook_id :integer -# open_devops_count :integer default("0") -# recommend :boolean default("0") -# platform :integer default("0") -# -# Indexes -# -# index_projects_on_forked_from_project_id (forked_from_project_id) -# index_projects_on_identifier (identifier) -# index_projects_on_is_public (is_public) -# index_projects_on_lft (lft) -# index_projects_on_name (name) -# index_projects_on_platform (platform) -# index_projects_on_project_type (project_type) -# index_projects_on_recommend (recommend) -# index_projects_on_rgt (rgt) -# index_projects_on_status (status) -# index_projects_on_updated_on (updated_on) -# - +# == Schema Information +# +# Table name: projects +# +# id :integer not null, primary key +# name :string(255) default(""), not null +# description :text(4294967295) +# homepage :string(255) default("") +# is_public :boolean default("1"), not null +# parent_id :integer +# created_on :datetime +# updated_on :datetime +# identifier :string(255) +# status :integer default("1"), not null +# lft :integer +# rgt :integer +# inherit_members :boolean default("0"), not null +# project_type :integer default("0") +# hidden_repo :boolean default("0"), not null +# attachmenttype :integer default("1") +# user_id :integer +# dts_test :integer default("0") +# enterprise_name :string(255) +# organization_id :integer +# project_new_type :integer +# gpid :integer +# forked_from_project_id :integer +# forked_count :integer default("0") +# publish_resource :integer default("0") +# visits :integer default("0") +# hot :integer default("0") +# invite_code :string(255) +# qrcode :string(255) +# qrcode_expiretime :integer default("0") +# script :text(65535) +# training_status :integer default("0") +# rep_identifier :string(255) +# project_category_id :integer +# project_language_id :integer +# license_id :integer +# ignore_id :integer +# praises_count :integer default("0") +# watchers_count :integer default("0") +# issues_count :integer default("0") +# pull_requests_count :integer default("0") +# language :string(255) +# versions_count :integer default("0") +# issue_tags_count :integer default("0") +# closed_issues_count :integer default("0") +# open_devops :boolean default("0") +# gitea_webhook_id :integer +# open_devops_count :integer default("0") +# recommend :boolean default("0") +# platform :integer default("0") +# default_branch :string(255) default("master") +# website :string(255) +# +# Indexes +# +# index_projects_on_forked_from_project_id (forked_from_project_id) +# index_projects_on_identifier (identifier) +# index_projects_on_is_public (is_public) +# index_projects_on_lft (lft) +# index_projects_on_name (name) +# index_projects_on_platform (platform) +# index_projects_on_project_type (project_type) +# index_projects_on_recommend (recommend) +# index_projects_on_rgt (rgt) +# index_projects_on_status (status) +# index_projects_on_updated_on (updated_on) +# + + class Project < ApplicationRecord @@ -110,12 +113,15 @@ class Project < ApplicationRecord has_and_belongs_to_many :trackers, :order => "#{Tracker.table_name}.position" has_one :project_detail, dependent: :destroy has_many :team_projects, dependent: :destroy + has_many :project_units, dependent: :destroy after_save :check_project_members scope :project_statics_select, -> {select(:id,:name, :is_public, :identifier, :status, :project_type, :user_id, :forked_count, :visits, :project_category_id, :project_language_id, :license_id, :ignore_id, :watchers_count, :created_on)} scope :no_anomory_projects, -> {where("projects.user_id is not null and projects.user_id != ?", 2)} scope :recommend, -> { visible.project_statics_select.where(recommend: true) } + delegate :content, to: :project_detail, allow_nil: true + delegate :name, to: :license, prefix: true, allow_nil: true def self.search_project(search) diff --git a/app/models/project_unit.rb b/app/models/project_unit.rb new file mode 100644 index 00000000..b5b4fe29 --- /dev/null +++ b/app/models/project_unit.rb @@ -0,0 +1,35 @@ +# == Schema Information +# +# Table name: project_units +# +# id :integer not null, primary key +# project_id :integer +# unit_type :integer +# created_at :datetime not null +# updated_at :datetime not null +# +# Indexes +# +# index_project_units_on_project_id (project_id) +# + +class ProjectUnit < ApplicationRecord + belongs_to :project + + enum unit_type: {code: 1, issues: 2, pulls: 3, devops: 4, versions: 5} + + validates :unit_type, uniqueness: { scope: :project_id} + + def self.init_types(project_id) + ProjectUnit::unit_types.each do |_, v| + self.create!(project_id: project_id, unit_type: v) + end + end + + def self.update_by_unit_types!(project, types) + project.project_units.where.not(unit_type: types).each(&:destroy!) + types.each do |type| + project.project_units.find_or_create_by!(unit_type: type) + end + end +end diff --git a/app/models/repository.rb b/app/models/repository.rb index 934eaa0e..b6d2321f 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -41,6 +41,8 @@ class Repository < ApplicationRecord validates :identifier, presence: true + delegate :default_branch, to: :project, allow_nil: true + def to_param self.identifier.parameterize end diff --git a/app/services/gitea/repository/contributors/get_service.rb b/app/services/gitea/repository/contributors/get_service.rb new file mode 100644 index 00000000..1ee1c395 --- /dev/null +++ b/app/services/gitea/repository/contributors/get_service.rb @@ -0,0 +1,22 @@ +class Gitea::Repository::Contributors::GetService < Gitea::ClientService + attr_reader :owner, :repo_name + + def initialize(owner, repo_name) + @owner = owner + @repo_name = repo_name + end + + def call + response = get(url, params) + render_status(response) + end + + private + def params + Hash.new.merge(token: owner.gitea_token) + end + + def url + "/repos/#{owner.login}/#{repo_name}/contributors" + end +end \ No newline at end of file diff --git a/app/services/gitea/repository/files/get_service.rb b/app/services/gitea/repository/files/get_service.rb new file mode 100644 index 00000000..e5b96e7b --- /dev/null +++ b/app/services/gitea/repository/files/get_service.rb @@ -0,0 +1,25 @@ +class Gitea::Repository::Files::GetService < Gitea::ClientService + attr_reader :owner, :repo_name, :ref, :q, :token + + def initialize(owner, repo_name, ref, q=nil, token=nil) + @owner = owner + @repo_name = repo_name + @ref = ref + @q = q + @token = token + end + + def call + response = get(url, params) + render_status(response) + end + + private + def params + Hash.new.merge(token: token, ref: ref, q: q) + end + + def url + "/repos/#{owner.login}/#{repo_name}/find" + end +end \ No newline at end of file diff --git a/app/services/gitea/versions/create_service.rb b/app/services/gitea/versions/create_service.rb index de21ad97..04fed00f 100644 --- a/app/services/gitea/versions/create_service.rb +++ b/app/services/gitea/versions/create_service.rb @@ -18,7 +18,8 @@ class Gitea::Versions::CreateService < Gitea::ClientService end def call - post(url, request_params) + response = post(url, request_params) + render_status(response) end private diff --git a/app/services/projects/create_service.rb b/app/services/projects/create_service.rb index dc14d10d..c6e5b213 100644 --- a/app/services/projects/create_service.rb +++ b/app/services/projects/create_service.rb @@ -13,6 +13,7 @@ class Projects::CreateService < ApplicationService ActiveRecord::Base.transaction do if @project.save! Project.update_common_projects_count! + ProjectUnit.init_types(@project.id) Repositories::CreateService.new(user, @project, repository_params).call else Rails.logger.info("#############___________create_project_erros______###########{@project.errors.messages}") @@ -36,6 +37,7 @@ class Projects::CreateService < ApplicationService is_public: repo_is_public, ignore_id: params[:ignore_id], license_id: params[:license_id], + website: params[:website], identifier: params[:repository_name] #新增,hs } end @@ -44,6 +46,7 @@ class Projects::CreateService < ApplicationService { hidden: !repo_is_public, user_id: params[:user_id], + website: params[:website], identifier: params[:repository_name] } end diff --git a/app/services/repositories/create_service.rb b/app/services/repositories/create_service.rb index 4c5519f2..18e72644 100644 --- a/app/services/repositories/create_service.rb +++ b/app/services/repositories/create_service.rb @@ -62,6 +62,7 @@ class Repositories::CreateService < ApplicationService project.update_columns( gpid: gitea_repository["id"], identifier: repository.identifier, + default_branch: gitea_repository["default_branch"], forked_count: gitea_repository["forks_count"]) end end diff --git a/app/services/repositories/detail_service.rb b/app/services/repositories/detail_service.rb new file mode 100644 index 00000000..58b286ec --- /dev/null +++ b/app/services/repositories/detail_service.rb @@ -0,0 +1,64 @@ +class Repositories::DetailService < ApplicationService + include Repository::LanguagesPercentagable + attr_reader :owner, :repo, :user + def initialize(owner, repo, user) + @owner = owner + @repo = repo + @user = user + end + + def call + if @repo.project.educoder? + return { + repo: {}, + release: [], + branch: [], + tag: [], + contributor: [], + language: {}, + readme: {} + } + else + return { + repo: repo_suitable, + release: release_suitable, + branch: branch_suitable, + tag: tag_suitable, + contributor: contributor_suitable, + language: language_suitable, + readme: readme_suitable + } + end + end + + private + def repo_suitable + Gitea::Repository::GetService.call(@owner, @repo.identifier) + end + + def release_suitable + Gitea::Versions::ListService.call(@owner.gitea_token, @owner.try(:login), @repo.try(:identifier)) + end + + def branch_suitable + Gitea::Repository::Branches::ListService.call(@owner, @repo.identifier) + end + + def tag_suitable + Gitea::Repository::Tags::ListService.call(@owner&.gitea_token, @owner.login, @repo.identifier) + end + + def contributor_suitable + Gitea::Repository::Contributors::GetService.call(@owner, @repo.identifier) + end + + def language_suitable + result = Gitea::Repository::Languages::ListService.call(@owner.login, @repo.identifier, @user&.gitea_token) + result[:status] === :success ? hash_transform_precentagable(result[:body]) : nil + end + + def readme_suitable + result = Gitea::Repository::Readme::GetService.call(@owner.login, @repo.identifier, @repo.default_branch, @owner.gitea_token) + result[:status] === :success ? result[:body] : nil + end +end \ No newline at end of file diff --git a/app/views/projects/project_units/index.json.jbuilder b/app/views/projects/project_units/index.json.jbuilder new file mode 100644 index 00000000..e8839387 --- /dev/null +++ b/app/views/projects/project_units/index.json.jbuilder @@ -0,0 +1,3 @@ +json.array! @project_units do |unit| + json.type unit.unit_type +end \ No newline at end of file diff --git a/app/views/repositories/contributors.json.jbuilder b/app/views/repositories/contributors.json.jbuilder new file mode 100644 index 00000000..a5edb37e --- /dev/null +++ b/app/views/repositories/contributors.json.jbuilder @@ -0,0 +1,17 @@ +total_count = @contributors.size +json.contributors @contributors.each do |contributor| + user = User.find_by(gitea_uid: contributor["id"]) + if contributor["login"] == "root" + total_count -= 1 + next + end + json.contributions contributor["contributions"] + json.gid contributor["id"] + json.login user.login + json.type user&.type + json.name user.real_name + json.image_url url_to_avatar(user) +end +json.total_count total_count + + diff --git a/app/views/repositories/detail.json.jbuilder b/app/views/repositories/detail.json.jbuilder new file mode 100644 index 00000000..6980d4b2 --- /dev/null +++ b/app/views/repositories/detail.json.jbuilder @@ -0,0 +1,90 @@ +json.content @project.content +json.website @project.website +json.readme @result[:readme].merge(content: readme_render_decode64_content(@result[:readme]["content"], nil)) +json.identifier render_identifier(@project) +json.name @project.name +json.project_id @project.id +json.repo_id @repository.id +json.issues_count @project.issues_count.to_i - @project.pull_requests_count.to_i +json.pull_requests_count @project.pull_requests_count +json.project_identifier render_identifier(@project) +json.praises_count @project.praises_count.to_i +json.forked_count @project.forked_count.to_i +json.watchers_count @project.watchers_count.to_i +json.versions_count @project.versions_count #里程碑数量 +json.version_releases_count @project.releases_size(@user.try(:id), "all") +json.version_releasesed_count @project.releases_size(@user.try(:id), "released") #已发行的版本 +json.permission render_permission(@user, @project) +json.mirror_url @project&.repository.mirror_url +json.mirror @project&.repository.mirror_url.present? +json.type @project.numerical_for_project_type +json.open_devops @project.open_devops? + +unless @project.common? + json.mirror_status @repository.mirror_status + json.mirror_num @repository.mirror_num + json.first_sync @repository.first_sync? +end + +json.watched @project.watched_by? @user +json.praised @project.praised_by? @user +json.status @project.status +json.forked_from_project_id @project_fork_id +json.fork_info do + if @fork_project.present? + json.fork_form_name @fork_project.try(:name) + json.fork_project_user_login @fork_project_user.try(:login) + json.fork_project_identifier @fork_project.identifier + json.fork_project_user_name @fork_project_user.try(:show_real_name) + end +end +if @result[:repo] + json.size replace_bytes_to_b(number_to_human_size(@result[:repo]['size'].to_i*1024)) + json.ssh_url @result[:repo]['ssh_url'] + json.clone_url @result[:repo]['clone_url'] + json.default_branch @result[:repo]['default_branch'] + json.empty @result[:repo]['empty'] + json.full_name @result[:repo]['full_name'] + json.private @result[:repo]['private'] +end +json.license_name @project.license_name +json.release_versions do + json.list @result[:release].each do |release| + forge_version = VersionRelease.find_by(version_gid: release["id"]) + json.id forge_version&.id + json.name release["name"] + json.tag_name release["tag_name"] + json.created_at format_time(release["created_at"].to_time) + end + json.total_count @result[:release].size +end +json.branches do + json.list @result[:branch].each do |branch| + json.name branch["name"] + end + json.total_count @result[:branch].size +end +json.tags do + json.list @result[:tag].each do |tag| + json.name tag["name"] + end + json.total_count @result[:tag].size +end +json.contributors do + total_count = @result[:contributor].size + json.list @result[:contributor].each do |contributor| + user = User.find_by(gitea_uid: contributor["id"]) + if contributor["login"] == "root" + total_count -= 1 + next + end + json.contributions contributor["contributions"] + json.gid contributor["id"] + json.login user.login + json.type user&.type + json.name user.real_name + json.image_url url_to_avatar(user) + end + json.total_count total_count +end +json.languages @result[:language] diff --git a/app/views/repositories/entries.json.jbuilder b/app/views/repositories/entries.json.jbuilder index 9efa0c11..6964c1c5 100644 --- a/app/views/repositories/entries.json.jbuilder +++ b/app/views/repositories/entries.json.jbuilder @@ -41,7 +41,7 @@ if @project.forge? end #json.tags_count @tags_count #json.branches_count @branches_count - #json.commits_count @commits_count + json.commits_count @commits_count json.zip_url render_zip_url(@project, @ref) json.tar_url render_tar_url(@project, @ref) json.entries do diff --git a/config/routes.rb b/config/routes.rb index 228c546c..9e9e3d7a 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -369,6 +369,7 @@ Rails.application.routes.draw do resource :projects, path: '/', except: [:show, :edit] do member do + get :menu_list get :branches get :simple get :watchers, to: 'projects#watch_users' @@ -378,14 +379,17 @@ Rails.application.routes.draw do end end - resource :repositories, path: '/', only: [:show, :create, :edit] do + resource :repositories, path: '/', only: [:show, :create, :edit] do member do + get :files + get :detail get :archive get :top_counts get :entries match :sub_entries, :via => [:get, :put] get :commits get :tags + get :contributors post :create_file put :update_file delete :delete_file @@ -526,6 +530,7 @@ Rails.application.routes.draw do scope module: :projects do resources :teams, only: [:index, :create, :destroy] + resources :project_units, only: [:index, :create] scope do get( '/blob/*id/diff', diff --git a/db/migrate/20210315093350_add_website_to_projects.rb b/db/migrate/20210315093350_add_website_to_projects.rb new file mode 100644 index 00000000..a3918dda --- /dev/null +++ b/db/migrate/20210315093350_add_website_to_projects.rb @@ -0,0 +1,6 @@ +class AddWebsiteToProjects < ActiveRecord::Migration[5.2] + def change + add_column :projects, :default_branch, :string, default: 'master' + add_column :projects, :website, :string + end +end diff --git a/db/migrate/20210317012035_create_project_units.rb b/db/migrate/20210317012035_create_project_units.rb new file mode 100644 index 00000000..6b89154f --- /dev/null +++ b/db/migrate/20210317012035_create_project_units.rb @@ -0,0 +1,10 @@ +class CreateProjectUnits < ActiveRecord::Migration[5.2] + def change + create_table :project_units do |t| + t.references :project + t.integer :unit_type + + t.timestamps + end + end +end diff --git a/public/docs/api.html b/public/docs/api.html index c33cad0d..1b75a97a 100644 --- a/public/docs/api.html +++ b/public/docs/api.html @@ -342,9 +342,18 @@
获取项目主页信息
+获取项目导航信息
示例:
curl -X GET \
-http://localhost:3000/api/jasder/forgeplus/about | jq
-
await octokit.request('GET /api/jasder/forgeplus/about')
+http://localhost:3000/api/yystopf/ceshi/menu_list | jq
+
await octokit.request('GET /api/yystopf/ceshi/menu_list')
GET api/:owner/:repo/about
GET api/:owner/:repo/menu_list
menu_name | +string | +导航名称, home:主页,code:代码库,issues:易修,pulls:合并请求,devops:工作流,versions:里程碑,activity:动态,setting:仓库设置 | +
++返回的JSON示例:
+
[
+ {
+ "menu_name": "home"
+ },
+ {
+ "menu_name": "code"
+ },
+ {
+ "menu_name": "pulls"
+ },
+ {
+ "menu_name": "activity"
+ }
+]
+
获取项目主页信息
+ +++示例:
+
curl -X GET \
+http://localhost:3000/api/jasder/forgeplus/about | jq
+
await octokit.request('GET /api/jasder/forgeplus/about')
+
GET api/:owner/:repo/about
参数 | +必选 | +默认 | +类型 | +字段说明 | +
---|---|---|---|---|
owner | +是 | ++ | string | +用户登录名 | +
repo | +是 | ++ | string | +项目标识identifier | +
参数 | +类型 | +字段说明 | +|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
identifier | string | project's identifier | @@ -1039,7 +1122,106 @@ http://localhost:3000/api/jasder/forgeplus/about | jq -
参数 | +类型 | +字段说明 | +
---|---|---|
type | +string | +模块名称 | +
++返回的JSON示例:
+
[
+ {
+ "type": "code"
+ },
+ {
+ "type": "pulls"
+ },
+ {
+ "type": "issues"
+ }
+]
+
更改项目模块展示
+ +++示例:
+
curl -X POST \
+-H "accept: application/json" \
+-H "Content-Type: application/json" \
+-d "{ \"unit_typs\": [\"code\", \"pulls\"]}" \
+http://localhost:3000/api/yystopf/ceshi/project_units.json
+
await octokit.request('POST /api/yystopf/ceshi/project_units')
+
POST /api/yystopf/ceshi/project_units
参数 | +必选 | +默认 | +类型 | +字段说明 | +
---|---|---|---|---|
unit_types | +是 | ++ | array | +项目模块内容, 支持以下参数:code:代码库,issues:易修,pulls:合并请求,devops:工作流,versions:里程碑 | +
参数 | +类型 | +字段说明 | +
---|---|---|
status | +int | +返回状态, 0: 表示操作成功 | +
message | +string | +返回信息说明 | +
++返回的JSON示例:
+
{
+ "status": 0,
+ "message": "success"
+}
+
创建项目
@@ -1056,9 +1238,9 @@ Remember — a happy kitten is an authenticated kitten! -d "license_id=1" \ http://localhost:3000/api/projects.jsonawait octokit.request('GET /api/projects.json') -
HTTP 请求
+HTTP 请求
-
POST api/projects
请求参数
+请求参数
-
参数 @@ -1132,7 +1314,7 @@ http://localhost:3000/api/projects.json项目是否私有, true:为私有,false: 公开,默认为公开 返回字段说明
+返回字段说明
参数 @@ -1174,9 +1356,9 @@ http://localhost:3000/api/projects.json -d "project_language_id=2" \ http://localhost:3000/api/projects/migrate.jsonawait octokit.request('GET /api/projects/migrate.json') -
HTTP 请求
+HTTP 请求
-
POST api/projects/migrate.json
请求参数
+请求参数
-
参数 @@ -1264,7 +1446,7 @@ http://localhost:3000/api/projects/migrate.json项目是否私有, true:为私有,false: 非私有,默认为公开 返回字段说明
+返回字段说明
参数 @@ -1299,9 +1481,9 @@ http://localhost:3000/api/projects/migrate.jsoncurl -X POST http://localhost:3000/api/repositories/1244/sync_mirror.json
await octokit.request('POST /api/repositories/1244/sync_mirror.json') -
HTTP 请求
+HTTP 请求
-
POST api/repositories/:id/sync_mirror.json
请求参数
+请求参数
-
参数 @@ -1319,7 +1501,7 @@ http://localhost:3000/api/projects/migrate.json仓库id 返回字段说明
+返回字段说明
参数 @@ -1354,9 +1536,9 @@ http://localhost:3000/api/projects/migrate.jsoncurl -X POST http://localhost:3000/api/jasder/forgeplus/forks.json
await octokit.request('POST /api/jaser/jasder_test/forks.json') -
HTTP 请求
+HTTP 请求
-
POST api/:owner/:repo/forks.json
请求参数
+请求参数
-
参数 @@ -1381,7 +1563,7 @@ http://localhost:3000/api/projects/migrate.json项目标识identifier 返回字段说明
+返回字段说明
参数 @@ -1590,16 +1772,16 @@ http://localhost:3000/api/projects/migrate.json "repo_id": 75073, "repo_identifier": "mirror_demo" } -编辑仓库信息
-编辑仓库信息
+仓库详情(新版)
+仓库详情
-示例:
curl -X GET http://localhost:3000/api/jasder/jasder_test/edit.json -
await octokit.request('GET /api/jasder/jasder_test/edit.json') +
curl -X GET http://localhost:3000/api/yystopf/ceshi/detail.json +
await octokit.request('GET /api/yystopf/ceshi/detail.json')
HTTP 请求
-+
GET /api/:owner/:repo/edit.json
GET /api/:owner/:repo/detail
请求参数:
+ +
@@ -1634,6 +1816,379 @@ http://localhost:3000/api/projects/migrate.json + +content +string +仓库简介 ++ +website +string +仓库网址 ++ +readme +string +readme文件| ++ +identifier +string +项目标识 ++ +name +string +项目名称 ++ +issues_count +int +项目issue数量 ++ +pull_requests_count +int +项目合并请求数量 ++ +project_identifier +int +项目标识 ++ +praises_count +int +项目点赞数量 ++ +forked_count +int +项目复刻数量 ++ +watchers_count +int +项目关注数量 ++ +versions_count +int +项目里程碑数量 ++ +version_releases_count +int +项目发行版数量 ++ +version_releasesed_count +int +项目发行版已发行数量 ++ +permission +string +项目权限 ++ +mirror_url +string +镜像地址 ++ +mirror +bool +是否为镜像项目 ++ +type +int +项目类型 0 普通项目 1 普通镜像项目 2 同步镜像项目 ++ +open_devops +int +是否开启devops ++ +watched +bool +是否关注 ++ +praised +bool +是否点赞 ++ +status +int +项目状态 ++ +forked_from_project_id +int +fork项目id ++ +fork_info +object +fork项目信息 ++ +size +string +仓库大小 ++ +ssh_url +string +项目ssh地址 ++ +clone_url +string +项目克隆地址 ++ +default_branch +string +仓库默认分支 ++ +empty +bool +仓库是否为空 ++ +full_name +string +仓库全称 ++ +private +bool +仓库是否为私有项目 ++ +license_name +string +许可证名称 ++ +release_versions.list.name +string +项目issue数量 ++ +release_versions.list.tag_name +string +发行版标签名称 ++ +release_versions.list.created_at +string +发行版创建时间 ++ +release_versions.total_count +int +发行版数量 ++ +branches.list.name +string +分支名称 ++ +branches.total_count +int +分支数量 ++ +tags.list.name +string +标签名称 ++ +tags.total_count +int +标签数量 ++ +contributors.list.contributions +int +贡献数量 ++ +contributors.list.login +string +贡献者登录名 ++ +contributors.list.name +string +贡献者用户名称 ++ +contributors.list.image_url +string +贡献者头像 ++ +languages +object +项目语言占比 +++返回的JSON示例:
+{ + "content": "仓库简介", + "website": "仓库网址", + "readme": { + "type": "file", + "encoding": "base64", + "size": 9, + "name": "README.md", + "path": "README.md", + "content": "# ceshi\n\n", + "sha": "" + }, + "identifier": "ceshi", + "name": "测试项目", + "project_id": 2, + "repo_id": 2, + "issues_count": 0, + "pull_requests_count": 0, + "project_identifier": "ceshi", + "praises_count": 0, + "forked_count": 0, + "watchers_count": 0, + "versions_count": 0, + "version_releases_count": 0, + "version_releasesed_count": 0, + "permission": "Reporter", + "mirror_url": null, + "mirror": false, + "type": 0, + "open_devops": false, + "watched": false, + "praised": false, + "status": 1, + "forked_from_project_id": 1, + "fork_info": { + "fork_form_name": "测试项目", + "fork_project_user_login": "ceshi_org", + "fork_project_identifier": "ceshi", + "fork_project_user_name": "ceshi_org" + }, + "size": "25.0 KB", + "ssh_url": "virus@localhost:yystopf/ceshi.git", + "clone_url": "http://localhost:10080/yystopf/ceshi.git", + "default_branch": "master", + "empty": false, + "full_name": "yystopf/ceshi", + "private": false, + "license_name": "gnu-javamail-exception", + "release_versions": { + "list": [ + { + "id": 2, + "name": "vvvv", + "tag_name": "v1.1", + "created_at": "2019-07-18 10:16" + } + ], + "total_count": 1 + }, + "branches": { + "list": [ + { + "name": "master" + } + ], + "total_count": 1 + }, + "tags": { + "list": [ + { + "name": "v1.1" + }, + { + "name": "v1.0" + } + ], + "total_count": 2 + }, + "contributors": { + "list": [ + { + "contributions": 1, + "gid": 2, + "login": "yystopf", + "type": "User", + "name": "yystopf", + "image_url": "avatars/User/b" + } + ], + "total_count": 1 + }, + "languages": { + "HTML": "50.9%", + "Ruby": "25.6%", + "JavaScript": "21.4%", + "CSS": "1.3%", + "CoffeeScript": "0.7%", + "Shell": "0.1%" + } +} +
编辑仓库信息
+编辑仓库信息
+ +++示例:
+curl -X GET http://localhost:3000/api/jasder/jasder_test/edit.json +
await octokit.request('GET /api/jasder/jasder_test/edit.json') +
HTTP 请求
++
GET /api/:owner/:repo/edit.json
请求参数:
++
++ + +参数 +必选 +默认 +类型 +字段说明 ++ +owner +是 ++ string +用户登录名 ++ +repo +是 ++ string +项目标识identifier +返回字段说明:
++
+ + +参数 +类型 +字段说明 +identifier string 仓库标识 @@ -1702,9 +2257,9 @@ http://localhost:3000/api/projects/migrate.json -d "private=true" \ http://localhost:3000/api/jasder/jasder_test.jsonawait octokit.request('PATCH /api/jasder/jasder_test.json') -
HTTP 请求
+HTTP 请求
-
PATCH /api/:owner/:repo
请求参数:
+请求参数:
-
参数 @@ -1764,7 +2319,7 @@ http://localhost:3000/api/jasder/jasder_test.json项目是否私有, true:为私有,false: 公开,默认为公开 返回字段说明:
+返回字段说明:
参数 @@ -1829,9 +2384,9 @@ http://localhost:3000/api/jasder/jasder_test.jsoncurl -X DELETE http://localhost:3000/api/jasder/jasder_test.json
await octokit.request('DELETE /api/jasder/jasder_test.json') -
HTTP 请求
+HTTP 请求
-
PATCH /api/:owner/:repo
请求参数:
+请求参数:
-
参数 @@ -1856,7 +2411,7 @@ http://localhost:3000/api/jasder/jasder_test.json项目标识identifier 返回字段说明:
+返回字段说明:
参数 @@ -1897,83 +2452,8 @@ http://localhost:3000/api/jasder/jasder_test.json -d "user_id=12" \ http://localhost:3000/api/jasder/jasder_test/collaborators.jsonawait octokit.request('POST /api/jasder/jasder_test/collaborators.json') -
HTTP 请求
--
POST /api/:owner/:repo/collaborators.json
请求参数:
--
-- - -参数 -必选 -默认 -类型 -字段说明 -- -owner -是 -- string -用户登录名 -- -repo -是 -- string -项目标识identifier -- -user_id -是 -int -- 用户id -返回字段说明:
--
- -- - -参数 -类型 -字段说明 -- -status -int -返回状态, 0: 表示操作成功 -- -message -string -返回信息说明 ---返回的JSON示例:
-- -{ - "status": 0, - "message": "success" -} -
删除仓库成员
-仓库中删除成员操作
- ---示例:
-curl -X DELETE \ --d "user_id=12" \ -http://localhost:3000/api/jasder/jasder_test/collaborators.json -
await octokit.request('DELETE /api/jasder/jasder_test/collaborators.json')
HTTP 请求
-+
DELETE /api/:owner/:repo/collaborators.json
POST /api/:owner/:repo/collaborators.json
请求参数:
+
@@ -2026,6 +2506,81 @@ http://localhost:3000/api/jasder/jasder_test/collaborators.json ++返回的JSON示例:
++ +{ + "status": 0, + "message": "success" +} +
删除仓库成员
+仓库中删除成员操作
+ +++示例:
+curl -X DELETE \ +-d "user_id=12" \ +http://localhost:3000/api/jasder/jasder_test/collaborators.json +
await octokit.request('DELETE /api/jasder/jasder_test/collaborators.json') +
HTTP 请求
++
DELETE /api/:owner/:repo/collaborators.json
请求参数:
++
++ + +参数 +必选 +默认 +类型 +字段说明 ++ +owner +是 ++ string +用户登录名 ++ +repo +是 ++ string +项目标识identifier ++ +user_id +是 +int ++ 用户id +返回字段说明:
++
++ + +参数 +类型 +字段说明 ++ +status +int +返回状态, 0: 表示操作成功 ++ +message +string +返回信息说明 +@@ -2048,9 +2603,9 @@ http://localhost:3000/api/jasder/jasder_test/collaborators.json -d "role=Developer" \ http://localhost:3000/api/jasder/jasder_test/change_role.json返回的JSON示例:
await octokit.request('PUT /api/jasder/jasder_test/change_role.json') -
HTTP 请求
+HTTP 请求
-
PUT /api/:owner/:repo/change_role.json
请求参数:
+请求参数:
-
参数 @@ -2089,7 +2644,7 @@ http://localhost:3000/api/jasder/jasder_test/change_role.json取值范围:"Manager", "Developer", "Reporter";分别为项目管理人员(拥有所有操作权限)、项目开发人员(只拥有读写权限)、项目报告人员(只拥有读权限) 返回字段说明:
+返回字段说明:
参数 @@ -2131,9 +2686,9 @@ http://localhost:3000/api/jasder/jasder_test/change_role.json -d "limit=5" \ http://localhost:3000/api/jasder/jasder_test/collaborators.jsonawait octokit.request('GET /api/jasder/jasder_test/collaborators.json') -
HTTP 请求
+HTTP 请求
-
GET /api/:owner/:repo/collaborators.json
请求参数:
+请求参数:
-
参数 @@ -2172,7 +2727,7 @@ http://localhost:3000/api/jasder/jasder_test/collaborators.json每页多少条数据,默认15条 返回字段说明:
+返回字段说明:
参数 @@ -2250,7 +2805,130 @@ http://localhost:3000/api/jasder/jasder_test/collaborators.json -获取仓库代码目录
+获取仓库所有文件
+获取仓库所有文件
+ +++示例:
+curl -X GET \ +-d "ref=develop" \ +http://localhost:3000/api/yystopf/ceshi/files.json +
await octokit.request('GET /api/yystopf/ceshi/files.json') +
HTTP 请求
++
GET /api/:owner/:repo/files
请求参数:
++
++ + +参数 +必选 +默认 +类型 +字段说明 ++ +owner +是 ++ string +用户登录名 ++ +repo +是 ++ string +项目标识identifier ++ +search +否 ++ string +文件搜索关键词 ++ +ref +是 ++ string +分支名,默认为仓库默认分支 +返回字段说明:
++
+ ++ + +参数 +类型 +字段说明 ++ +name +string +文件名称 ++ +path +string +文件路径 ++ +sha +string +文件标识 ++ +type +string +文件类型 ++ +size +int +文件大小 ++ +url +string +文件地址 +++返回的JSON示例:
+[ + { + "name": ".gitignore", + "path": ".gitignore", + "sha": "f83922d01ae60f6e637a1a2b9f08871b4f87dfc8", + "type": "file", + "size": 63, + "url": "http://localhost:10080/api/v1/repos/yystopf/ceshi/contents/.gitignore?ref=master", + "html_url": "http://localhost:10080/yystopf/ceshi/src/branch/master/.gitignore" + }, + { + "name": "LICENSE", + "path": "LICENSE", + "sha": "8f3b9ab0d08afd3a624d822e3971a2f42b3bc2b9", + "type": "file", + "size": 341, + "url": "http://localhost:10080/api/v1/repos/yystopf/ceshi/contents/LICENSE?ref=master", + "html_url": "http://localhost:10080/yystopf/ceshi/src/branch/master/LICENSE" + }, + { + "name": "README.md", + "path": "README.md", + "sha": "1bc8a60ac6ddc876ebc4b60fc68991435bfad93e", + "type": "file", + "size": 9, + "url": "http://localhost:10080/api/v1/repos/yystopf/ceshi/contents/README.md?ref=master", + "html_url": "http://localhost:10080/yystopf/ceshi/src/branch/master/README.md" + } +] +
获取仓库代码目录
获取仓库代码目录
@@ -2260,9 +2938,9 @@ http://localhost:3000/api/jasder/jasder_test/collaborators.json -d "ref=develop" \ http://localhost:3000//api/jasder/jasder_test/entries.jsonawait octokit.request('GET /api/jasder/jasder_test/entries.json') -
HTTP 请求
+HTTP 请求
-
GET /api/:owner/:repo/entries.json
请求参数:
+请求参数:
-
参数 @@ -2294,7 +2972,7 @@ http://localhost:3000//api/jasder/jasder_test/entries.json分支名称、tag名称或是提交记录id,默认为master分支 返回字段说明:
+返回字段说明:
参数 @@ -2408,9 +3086,9 @@ http://localhost:3000//api/jasder/jasder_test/entries.json -d "filepath=file" \ http://localhost:3000//api/jasder/jasder_test/sub_entries.jsonawait octokit.request('GET /api/jasder/jasder_test/sub_entries.json') -
HTTP 请求
+HTTP 请求
-
GET /api/:owner/:repo/sub_entries.json
请求参数:
+请求参数:
-
参数 @@ -2449,7 +3127,7 @@ http://localhost:3000//api/jasder/jasder_test/sub_entries.json分支名称、tag名称或是提交记录id,默认为master分支 返回字段说明:
+返回字段说明:
参数 diff --git a/spec/models/project_unit_spec.rb b/spec/models/project_unit_spec.rb new file mode 100644 index 00000000..d95607ca --- /dev/null +++ b/spec/models/project_unit_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe ProjectUnit, type: :model do + pending "add some examples to (or delete) #{__FILE__}" +end