From e30d200371bb5455cd78eb45d88d9ac9e0a9f1a8 Mon Sep 17 00:00:00 2001 From: Jasder <2053003901@@qq.com> Date: Fri, 27 Dec 2019 16:29:53 +0800 Subject: [PATCH 1/5] FIX change some columns default value --- ...13202_change_forked_count_default_from_projects.rb | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 db/migrate/20191227013202_change_forked_count_default_from_projects.rb diff --git a/db/migrate/20191227013202_change_forked_count_default_from_projects.rb b/db/migrate/20191227013202_change_forked_count_default_from_projects.rb new file mode 100644 index 000000000..99a102878 --- /dev/null +++ b/db/migrate/20191227013202_change_forked_count_default_from_projects.rb @@ -0,0 +1,11 @@ +class ChangeForkedCountDefaultFromProjects < ActiveRecord::Migration[5.2] + def change + change_column_default :projects, :forked_count, { from: nil, to: 0 } + change_column_default :projects, :project_type, { from: nil, to: 0 } + + Project.find_each do |project| + project.update_column('forked_count', 0) if project.forked_count.nil? + project.update_column('project_type', 0) if project.project_type.nil? + end + end +end From 285705b935f6dcfca4066e3e7ba1f67760c8fb62 Mon Sep 17 00:00:00 2001 From: Jasder <2053003901@@qq.com> Date: Fri, 27 Dec 2019 16:32:52 +0800 Subject: [PATCH 2/5] FIX api --- .../project_categories_controller.rb | 6 +++++ app/controllers/projects_controller.rb | 9 ++++++-- app/helpers/application_helper.rb | 6 +++-- app/helpers/projects_helper.rb | 7 ++++++ app/models/concerns/matchable.rb | 13 +++++++++++ app/models/concerns/publicable.rb | 4 +--- app/models/project.rb | 5 ++++ app/models/repository.rb | 2 +- app/queries/projects/list_query.rb | 21 +++++++++++++++++ app/services/projects/migrate_service.rb | 3 ++- app/services/repositories/create_service.rb | 10 +++++--- .../group_list.json.jbuilder | 5 ++++ app/views/projects/_project.json.jbuilder | 8 +++++++ .../projects/group_type_list.json.jbuilder | 5 ++++ app/views/projects/index.json.jbuilder | 23 ++++++++++++++++++- config/routes.rb | 6 ++++- 16 files changed, 119 insertions(+), 14 deletions(-) create mode 100644 app/models/concerns/matchable.rb create mode 100644 app/queries/projects/list_query.rb create mode 100644 app/views/project_categories/group_list.json.jbuilder create mode 100644 app/views/projects/_project.json.jbuilder create mode 100644 app/views/projects/group_type_list.json.jbuilder diff --git a/app/controllers/project_categories_controller.rb b/app/controllers/project_categories_controller.rb index 273f73c95..a515e45b6 100644 --- a/app/controllers/project_categories_controller.rb +++ b/app/controllers/project_categories_controller.rb @@ -2,4 +2,10 @@ class ProjectCategoriesController < ApplicationController def index @project_categories = ProjectCategory.search(params[:name]).without_content end + + def group_list + @category_group_list = + Project.visible.joins(:project_category).group(:project_category_id) + .select("project_category_id, count(*) AS projects_count, project_categories.name") + end end diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index a3bcf65cb..cbefd8d1f 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -1,9 +1,10 @@ class ProjectsController < ApplicationController - before_action :require_login + before_action :require_login, except: %i[index branches group_type_list] before_action :find_project, only: %i[branches] def index - + scope = Projects::ListQuery.call(params) + @projects = paginate(scope) end def create @@ -30,6 +31,10 @@ class ProjectsController < ApplicationController @branches = Gitea::Repository::BranchesService.new(current_user, @project.identifier).call end + def group_type_list + @project_group_list = Project.visible.group(:project_type).select('project_type, count(*) AS projects_count') + end + private def find_project @project = Project.find_by_identifier! params[:id] diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index cabf8d244..9f8d52d61 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -422,6 +422,8 @@ module ApplicationHelper when 3 then 'text-secondary' end end -end - + def render_unix_time(date) + date.to_time.to_i + end +end diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index db5c5ce1a..8a860eca8 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -1,2 +1,9 @@ module ProjectsHelper + + def render_zh_project_type(project_type) + case project_type + when 'common' then "开源托管项目" + when 'mirror' then "开源镜像项目" + end + end end diff --git a/app/models/concerns/matchable.rb b/app/models/concerns/matchable.rb new file mode 100644 index 000000000..cd7b7e256 --- /dev/null +++ b/app/models/concerns/matchable.rb @@ -0,0 +1,13 @@ +module Matchable + extend ActiveSupport::Concern + + included do + scope :like, lambda { |keywords| + where("name LIKE ?", "%#{keywords.split(" ").join('|')}%") unless keywords.blank? + } + scope :with_project_category, ->(category_id) { where(project_category_id: category_id) unless category_id.blank? } + scope :with_project_language, ->(language_id) { where(project_language_id: language_id) unless language_id.blank? } + scope :with_project_type, ->(project_type) { where(project_type: project_type) if Project.project_types.include?(project_type) } + end + +end diff --git a/app/models/concerns/publicable.rb b/app/models/concerns/publicable.rb index a9c8cb41f..6a06d27db 100644 --- a/app/models/concerns/publicable.rb +++ b/app/models/concerns/publicable.rb @@ -2,8 +2,6 @@ module Publicable extend ActiveSupport::Concern included do - alias_attribute :public, :is_public - enum public: { publiced: 1, hidden: 0 } + scope :visible, -> { where(is_public: true) } end - end diff --git a/app/models/project.rb b/app/models/project.rb index 9aecb1feb..0b02cd4e2 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -1,4 +1,9 @@ class Project < ApplicationRecord + include Matchable + include Publicable + + enum project_type: { mirror: 1, common: 0 } # common:开源托管项目, mirror:开源镜像项目 + belongs_to :ignore, optional: true belongs_to :license, optional: true belongs_to :owner, class_name: 'User', foreign_key: :user_id diff --git a/app/models/repository.rb b/app/models/repository.rb index fdfbad582..d21761af2 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -1,6 +1,6 @@ class Repository < ApplicationRecord self.inheritance_column = nil # FIX The single-table inheritance mechanism failed - belongs_to :project + belongs_to :project, :touch => true belongs_to :user validates :identifier, presence: true, uniqueness: true diff --git a/app/queries/projects/list_query.rb b/app/queries/projects/list_query.rb new file mode 100644 index 000000000..88a8f42ed --- /dev/null +++ b/app/queries/projects/list_query.rb @@ -0,0 +1,21 @@ +class Projects::ListQuery < ApplicationQuery + include CustomSortable + + attr_reader :params + + sort_columns :updated_on, :created_on, :forked_count, :praises_count, default_by: :updated_on, default_direction: :desc + + def initialize(params) + @params = params + end + + def call + scope = Project.like(params[:search]) + .with_project_type(params[:project_type]) + .with_project_category(params[:category_id]) + .with_project_language(params[:language_id]) + .includes(:project_category, :project_language, :repository, :owner) + + custom_sort(scope, params[:sort_by], params[:sort_direction]) + end +end diff --git a/app/services/projects/migrate_service.rb b/app/services/projects/migrate_service.rb index a3c6b131e..c29d58a8e 100644 --- a/app/services/projects/migrate_service.rb +++ b/app/services/projects/migrate_service.rb @@ -30,7 +30,8 @@ class Projects::MigrateService < ApplicationService description: params[:description], project_category_id: params[:project_category_id], project_language_id: params[:project_language_id], - is_public: get_is_public + is_public: get_is_public, + project_type: Project.project_types[:mirror] } end diff --git a/app/services/repositories/create_service.rb b/app/services/repositories/create_service.rb index 70dc84799..6fe5a4a6a 100644 --- a/app/services/repositories/create_service.rb +++ b/app/services/repositories/create_service.rb @@ -25,12 +25,16 @@ class Repositories::CreateService < ApplicationService private def sync_project(repository, gitea_repository) - project.update_column('identifier', repository.identifier) - project.update_columns(gpid: gitea_repository["id"]) if gitea_repository + if gitea_repository + project.update_columns( + gpid: gitea_repository["id"], + identifier: repository.identifier, + forked_count: gitea_repository["forks_count"]) + end end def sync_repository(repository, gitea_repository) - repository.update_columns(url: remote_repository_url) if gitea_repository + repository.update_columns(url: remote_repository_url,) if gitea_repository end def remote_repository_url diff --git a/app/views/project_categories/group_list.json.jbuilder b/app/views/project_categories/group_list.json.jbuilder new file mode 100644 index 000000000..58e6a6c40 --- /dev/null +++ b/app/views/project_categories/group_list.json.jbuilder @@ -0,0 +1,5 @@ +json.array! @category_group_list do |category| + json.id category.project_category_id + json.name category.name + json.projects_count category.projects_count +end diff --git a/app/views/projects/_project.json.jbuilder b/app/views/projects/_project.json.jbuilder new file mode 100644 index 000000000..b3f6c752a --- /dev/null +++ b/app/views/projects/_project.json.jbuilder @@ -0,0 +1,8 @@ +json.id project.identifier +json.name project.name +json.description project.description +json.visits project.visits +json.forked_count project.forked_count +json.is_public project.is_public +json.mirror_url project.repository&.mirror_url +json.last_update_time render_unix_time(project.updated_on) diff --git a/app/views/projects/group_type_list.json.jbuilder b/app/views/projects/group_type_list.json.jbuilder new file mode 100644 index 000000000..218db18a1 --- /dev/null +++ b/app/views/projects/group_type_list.json.jbuilder @@ -0,0 +1,5 @@ +json.array! @project_group_list do |group| + json.project_type group.project_type + json.name render_zh_project_type(group.project_type) + json.projects_count group.projects_count +end diff --git a/app/views/projects/index.json.jbuilder b/app/views/projects/index.json.jbuilder index f4f2b0b91..07170e1e0 100644 --- a/app/views/projects/index.json.jbuilder +++ b/app/views/projects/index.json.jbuilder @@ -1 +1,22 @@ -json.projects [] +json.array! @projects do |project| + json.partial! 'project', project: project + json.author do + json.name project.owner.login + end + json.category do + if project.project_category.blank? + json.nil! + else + json.id project.project_category.id + json.name project.project_category.name + end + end + json.language do + if project.project_language.blank? + json.nil! + else + json.id project.project_language.id + json.name project.project_language.name + end + end +end diff --git a/config/routes.rb b/config/routes.rb index 65c2476ff..bf13a81a9 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -27,7 +27,9 @@ Rails.application.routes.draw do put 'commons/unhidden', to: 'commons#unhidden' delete 'commons/delete', to: 'commons#delete' - resources :project_categories, only: [:index, :show] + resources :project_categories, only: [:index, :show] do + get :group_list, on: :collection + end resources :project_languages, only: [:index, :show] resources :ignores, only: [:index, :show] resources :licenses, only: [:index, :show] @@ -42,6 +44,7 @@ Rails.application.routes.draw do end collection do post :migrate + get :group_type_list end member do get :branches @@ -118,6 +121,7 @@ Rails.application.routes.draw do member do get :homepage_info end + get 'me', on: :collection get :question_banks, on: :collection, to: 'users/question_banks#index' From 6acb2fc6c01a9121e0e40f644b2a8edb95583ca5 Mon Sep 17 00:00:00 2001 From: Jasder <2053003901@@qq.com> Date: Fri, 27 Dec 2019 16:39:03 +0800 Subject: [PATCH 3/5] Update READE.md --- README.md | 333 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 313 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 688dda462..caa4f754f 100644 --- a/README.md +++ b/README.md @@ -379,49 +379,342 @@ http://localhost:3000/api/projects/migrate | jq ``` --- +#### 项目类别列表(用于项目列表左侧导航中的项目类别列表) +``` +GET api/project_categories/group_list +``` +*示例* +``` +curl -X GET http://localhost:3000/api/project_categories/group_list | jq +``` + +*返回参数说明:* + +|参数名|类型|说明| +-|-|- +|id |int |项目分类id | +|name |string|项目分类名称| +|projects_count |int |项目数量| + + +返回值 +``` +[ + { + "id": 1, + "name": "大数据", + "projects_count": 30 + }, + { + "id": 2, + "name": "机器学习", + "projects_count": 1 + }, + { + "id": 3, + "name": "深度学习", + "projects_count": 1 + } +] +``` +--- + +#### 项目类型列表(用于项目列表左侧导航上方中的项目类型列表) +``` +GET api/projects/group_type_list +``` +*示例* +``` +curl -X GET http://localhost:3000/api/projects/group_type_list | jq +``` + +*返回参数说明:* + +|参数名|类型|说明| +-|-|- +|project_type |string|项目类型 | +|name |string|项目类型名称| +|projects_count |int |项目数量| + + +返回值 +``` +[ + { + "project_type": "common", + "name": "开源托管项目", + "projects_count": 2106 + }, + { + "project_type": "mirror", + "name": "开源镜像项目", + "projects_count": 1 + } +] +``` +--- + #### 项目列表 ``` GET api/projects ``` *示例* ``` -curl -X POST \ --d "user_id=36401" \ --d "clone_addr=https://gitea.com/CasperVector/slew.git" \ --d "name=ni项目" \ --d "description=my first project" \ --d "repository_name=mirror_demo" \ --d "project_category_id=1" \ --d "project_language_id=2" \ -http://localhost:3000/api/projects/migrate | jq +curl -X GET \ +-d "page=1" \ +-d "limit=5" \ +http://localhost:3000/api/projects | jq ``` *请求参数说明:* |参数名|必选|类型|说明| -|-|-|- -|user_id |是|int |用户id或者组织id | -|name |是|string |项目名称 | -|clone_addr |是|string |镜像项目clone地址 | -|description |否|string |项目描述 | -|repository_name |是|string |仓库名称, 只含有数字、字母、下划线不能以下划线开头和结尾,且唯一 | -|project_category_id|是|int |项目类别id | -|project_language_id|是|int |项目语言id | -|private |否|boolean|项目是否私有, true:为私有,false: 非私有,默认为公开 | +|page |否|string |页数,第几页 | +|limit |否|string |每页多少条数据,默认15条 | +|sort_by |否|string |排序类型 | +|sort_direction|否|string |排序方式,取值为: desc \| asc; desc: 降序排序, asc: 升序排序, 默认为:desc | +|name |否|string |项目名称, 按照项目名称搜索 | +|category_id |否|int |项目类别id | +|language_id |否|int |项目语言id | +|project_type |否|string |项目类型, 取值为:common \| mirror; common:开源托管项目, mirror:开源镜像项目 | *返回参数说明:* |参数名|类型|说明| -|-|- -|id |int |id | +|id |string |项目标识 | |name |string|项目名称| +|description |string|项目简介| +|visits |int|流量数| +|forked_count |int|被fork的数量| +|is_public |boolean|是否公开, true:公开,false:未公开| +|mirror_url |string|镜像url| +|last_update_time |int|最后更新时间,为UNIX格式的时间戳| +|author |object|项目创建者| +|-- name |string|用户名,也是用户标识| +|category |object|项目类别| +|-- id |int|项目类型id| +|-- name |string|项目类型名称| +|language |object|项目语言| +|-- id |int|项目语言id| +|-- name |string|项目语言名称| + + + +返回值 +``` +[ + { + "id": "tongjj", + "name": "统计局", + "description": "my first project", + "visits": 0, + "forked_count": 0, + "is_public": true, + "mirror_url": null, + "last_update_time": 1577415173, + "author": { + "name": "18816895620" + }, + "category": { + "id": 1, + "name": "大数据" + }, + "language": { + "id": 2, + "name": "C" + } + }, + { + "id": null, + "name": "开源同名", + "description": "my first project", + "visits": 0, + "forked_count": 0, + "is_public": false, + "mirror_url": "https://gitea.com/CasperVector/slew.git", + "last_update_time": 1577346228, + "author": { + "name": "18816895620" + }, + "category": { + "id": 1, + "name": "大数据" + }, + "language": { + "id": 2, + "name": "C" + } + }, + { + "id": "mvp_demo", + "name": "开源支持", + "description": "my first project", + "visits": 0, + "forked_count": 0, + "is_public": true, + "mirror_url": null, + "last_update_time": 1577341572, + "author": { + "name": "18816895620" + }, + "category": { + "id": 1, + "name": "大数据" + }, + "language": { + "id": 2, + "name": "C" + } + }, + { + "id": null, + "name": "ni项目1", + "description": "my first project", + "visits": 0, + "forked_count": 0, + "is_public": true, + "mirror_url": "https://gitea.com/CasperVector/slew.git", + "last_update_time": 1577092908, + "author": { + "name": "18816895620" + }, + "category": { + "id": 1, + "name": "大数据" + }, + "language": { + "id": 2, + "name": "C" + } + }, + { + "id": "mirror_demo", + "name": "ni项目", + "description": "my first project", + "visits": 0, + "forked_count": 0, + "is_public": false, + "mirror_url": "https://gitea.com/CasperVector/slew.git", + "last_update_time": 1577085412, + "author": { + "name": "18816895620" + }, + "category": { + "id": 1, + "name": "大数据" + }, + "language": { + "id": 2, + "name": "C" + } + } +] +``` +--- + +### 获取分支列表 +``` +GET /api/projects/:identifier/branches +``` +*示例* +``` +curl -X GET http://localhost:3000/api/projects/mirror_demo/branches | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +-|-|-|- +|identifier |是|string |项目标识 | + + +*返回参数说明:* + +|参数名|类型|说明| +-|-|- +|name |string|分支名称| + + +返回值 +``` +[ + { + "name": "develop" + }, + { + "name": "master" + } +] +``` +--- + +### 点赞 +``` +POST /api/praise_tread/like +``` +*示例* +``` +curl -X POST \ +-d 'object_id=1' \ +-d 'object_type=project' \ +http://localhost:3000/api/praise_tread/like | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +-|-|-|- +|object_id |是 |int |项目id | +|object_type |否 |string | 点赞类型,默认为project| + + +*返回参数说明:* + +|参数名|类型|说明| +-|-|- +|status |int|0:点赞成功,-1:操作失败,2:表示已经点过赞了| 返回值 ``` { - "id": 3263, - "name": "ni项目" + "status": 0, + "message": "响应成功" +} +``` +--- + +### 取消点赞 +``` +DELETE /api/praise_tread/unlike +``` +*示例* +``` +curl -X DELETE \ +-d 'object_id=1' \ +-d 'object_type=project' \ +http://localhost:3000/api/praise_tread/unlike | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +-|-|-|- +|object_id |是 |string |点赞对象的唯一标识,如项目的identifier字段 | +|object_type |是 |string | 点赞类型,默认为project| + + +*返回参数说明:* + +|参数名|类型|说明| +-|-|- +|status |int|0:点赞成功,-1:操作失败,2:表示还未点赞| + + +返回值 +``` +{ + "status": 0, + "message": "响应成功" } ``` --- From 6fc74b06f0a9f7859e010bd4f000ceca5eee8cd7 Mon Sep 17 00:00:00 2001 From: Jasder <2053003901@@qq.com> Date: Fri, 27 Dec 2019 16:49:09 +0800 Subject: [PATCH 4/5] Update READE.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index caa4f754f..156d66f1a 100644 --- a/README.md +++ b/README.md @@ -471,7 +471,7 @@ http://localhost:3000/api/projects | jq -|-|-|- |page |否|string |页数,第几页 | |limit |否|string |每页多少条数据,默认15条 | -|sort_by |否|string |排序类型 | +|sort_by |否|string |排序类型, 取值:updated_on \| created_on \| forked_count \| praises_count, updated_on: 更新时间排序,created_on: 创建时间排序,forked_count: fork数据排序,praises_count: 点赞数量排序,默认为updated_on更新时间排序 | |sort_direction|否|string |排序方式,取值为: desc \| asc; desc: 降序排序, asc: 升序排序, 默认为:desc | |name |否|string |项目名称, 按照项目名称搜索 | |category_id |否|int |项目类别id | From d5b55851683ae02f887b9ae1dd38900b74a33b91 Mon Sep 17 00:00:00 2001 From: Jasder <2053003901@@qq.com> Date: Fri, 27 Dec 2019 17:24:06 +0800 Subject: [PATCH 5/5] FIX update api document " --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 156d66f1a..86dbefd0f 100644 --- a/README.md +++ b/README.md @@ -713,8 +713,8 @@ http://localhost:3000/api/praise_tread/unlike | jq 返回值 ``` { - "status": 0, - "message": "响应成功" + "status": 0, + "message": "响应成功" } ``` ---