| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -168,6 +168,55 @@ Remember — a happy kitten is an authenticated kitten! | |||
| </aside> | |||
| ## 项目导航 | |||
| 获取项目导航信息 | |||
| > 示例: | |||
| ```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! | |||
| </aside> | |||
| ## 项目模块信息 | |||
| 项目模块信息 | |||
| > 示例: | |||
| ```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" | |||
| } | |||
| ``` | |||
| ## 创建项目 | |||
| 创建项目 | |||
| @@ -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. | |||
| </aside> | |||
| ## 获取仓库所有文件 | |||
| 获取仓库所有文件 | |||
| > 示例: | |||
| ```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" | |||
| } | |||
| ] | |||
| ``` | |||
| ## 获取仓库代码目录 | |||
| 获取仓库代码目录 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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) | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -0,0 +1,3 @@ | |||
| json.array! @project_units do |unit| | |||
| json.type unit.unit_type | |||
| end | |||
| @@ -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 | |||
| @@ -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] | |||
| @@ -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 | |||
| @@ -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', | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -0,0 +1,5 @@ | |||
| require 'rails_helper' | |||
| RSpec.describe ProjectUnit, type: :model do | |||
| pending "add some examples to (or delete) #{__FILE__}" | |||
| end | |||