From ac2e3ae7307b76cd303de78b35675ad175625e84 Mon Sep 17 00:00:00 2001 From: "sylor_huang@126.com" Date: Thu, 14 May 2020 18:08:27 +0800 Subject: [PATCH] =?UTF-8?q?admins=20=E9=A1=B5=E9=9D=A2=E7=9A=84=E4=BF=AE?= =?UTF-8?q?=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/assets/stylesheets/admins/common.scss | 1 + .../admins/project_categories_controller.rb | 83 ++++++++++++ .../admins/project_ignores_controller.rb | 120 ++++++++++++++++++ .../admins/project_languages_controller.rb | 82 ++++++++++++ .../admins/project_licenses_controller.rb | 120 ++++++++++++++++++ app/controllers/admins/projects_controller.rb | 6 +- app/controllers/admins/users_controller.rb | 2 +- app/models/user.rb | 2 +- .../project_categories/_form_modal.html.erb | 21 +++ .../admins/project_categories/_list.html.erb | 33 +++++ .../admins/project_categories/edit.js.erb | 2 + .../admins/project_categories/index.html.erb | 18 +++ .../admins/project_categories/index.js.erb | 1 + .../admins/project_categories/new.js.erb | 2 + .../admins/project_ignores/_content.html.erb | 9 ++ .../admins/project_ignores/_form.html.erb | 38 ++++++ .../admins/project_ignores/_list.html.erb | 45 +++++++ app/views/admins/project_ignores/edit.js.erb | 1 + .../admins/project_ignores/index.html.erb | 18 +++ app/views/admins/project_ignores/index.js.erb | 1 + app/views/admins/project_ignores/new.js.erb | 1 + app/views/admins/project_ignores/show.js.erb | 1 + .../project_languages/_form_modal.html.erb | 21 +++ .../admins/project_languages/_list.html.erb | 33 +++++ .../admins/project_languages/edit.js.erb | 2 + .../admins/project_languages/index.html.erb | 18 +++ .../admins/project_languages/index.js.erb | 1 + app/views/admins/project_languages/new.js.erb | 2 + .../admins/project_licenses/_content.html.erb | 9 ++ .../admins/project_licenses/_form.html.erb | 38 ++++++ .../admins/project_licenses/_list.html.erb | 45 +++++++ app/views/admins/project_licenses/edit.js.erb | 1 + .../admins/project_licenses/index.html.erb | 18 +++ .../admins/project_licenses/index.js.erb | 1 + app/views/admins/project_licenses/new.js.erb | 1 + app/views/admins/project_licenses/show.js.erb | 1 + .../admins/projects/shared/_list.html.erb | 2 +- app/views/admins/shared/_sidebar.html.erb | 52 ++------ app/views/admins/users/index.html.erb | 12 +- .../admins/users/shared/_user_list.html.erb | 6 +- app/views/layouts/admin.html.erb | 2 +- config/routes.rb | 8 +- public/favicon.ico | Bin 67646 -> 10415 bytes 43 files changed, 822 insertions(+), 58 deletions(-) create mode 100644 app/controllers/admins/project_categories_controller.rb create mode 100644 app/controllers/admins/project_ignores_controller.rb create mode 100644 app/controllers/admins/project_languages_controller.rb create mode 100644 app/controllers/admins/project_licenses_controller.rb create mode 100644 app/views/admins/project_categories/_form_modal.html.erb create mode 100644 app/views/admins/project_categories/_list.html.erb create mode 100644 app/views/admins/project_categories/edit.js.erb create mode 100644 app/views/admins/project_categories/index.html.erb create mode 100644 app/views/admins/project_categories/index.js.erb create mode 100644 app/views/admins/project_categories/new.js.erb create mode 100644 app/views/admins/project_ignores/_content.html.erb create mode 100644 app/views/admins/project_ignores/_form.html.erb create mode 100644 app/views/admins/project_ignores/_list.html.erb create mode 100644 app/views/admins/project_ignores/edit.js.erb create mode 100644 app/views/admins/project_ignores/index.html.erb create mode 100644 app/views/admins/project_ignores/index.js.erb create mode 100644 app/views/admins/project_ignores/new.js.erb create mode 100644 app/views/admins/project_ignores/show.js.erb create mode 100644 app/views/admins/project_languages/_form_modal.html.erb create mode 100644 app/views/admins/project_languages/_list.html.erb create mode 100644 app/views/admins/project_languages/edit.js.erb create mode 100644 app/views/admins/project_languages/index.html.erb create mode 100644 app/views/admins/project_languages/index.js.erb create mode 100644 app/views/admins/project_languages/new.js.erb create mode 100644 app/views/admins/project_licenses/_content.html.erb create mode 100644 app/views/admins/project_licenses/_form.html.erb create mode 100644 app/views/admins/project_licenses/_list.html.erb create mode 100644 app/views/admins/project_licenses/edit.js.erb create mode 100644 app/views/admins/project_licenses/index.html.erb create mode 100644 app/views/admins/project_licenses/index.js.erb create mode 100644 app/views/admins/project_licenses/new.js.erb create mode 100644 app/views/admins/project_licenses/show.js.erb mode change 100755 => 100644 public/favicon.ico diff --git a/app/assets/stylesheets/admins/common.scss b/app/assets/stylesheets/admins/common.scss index 510e7f8f1..8d48a67ed 100644 --- a/app/assets/stylesheets/admins/common.scss +++ b/app/assets/stylesheets/admins/common.scss @@ -135,5 +135,6 @@ padding: 10px 20px 0; background: #fff; } + .mt-10{margin-top: 10px;} } diff --git a/app/controllers/admins/project_categories_controller.rb b/app/controllers/admins/project_categories_controller.rb new file mode 100644 index 000000000..944a2cf04 --- /dev/null +++ b/app/controllers/admins/project_categories_controller.rb @@ -0,0 +1,83 @@ +class Admins::ProjectCategoriesController < Admins::BaseController + before_action :get_category, only: [:edit,:update, :destroy] + before_action :validate_names, only: [:create, :update] + + def index + sort_by = params[:sort_by] ||= 'created_at' + sort_direction = params[:sort_direction] ||= 'desc' + q = ProjectCategory.ransack(name_cont: params[:name]) + project_categories = q.result(distinct: true).order("#{sort_by} #{sort_direction}") + @project_categories = paginate(project_categories) + + end + + def new + @project_category = ProjectCategory.new + end + + def edit + end + + def create + max_position_items = ProjectCategory.select(:id, :position).pluck(:position).reject!(&:blank?) + max_position = max_position_items.present? ? max_position_items.max.to_i : 0 + + @project_category = ProjectCategory.new(name: @name,position: max_position) + if @project_category.save + redirect_to admins_project_categories_path + flash[:success] = '创建成功' + else + redirect_to admins_project_categories_path + flash[:danger] = '创建失败' + end + end + + def update + if @project_category.update_attribute(:name, @name) + redirect_to admins_project_categories_path + flash[:success] = '更新成功' + else + redirect_to admins_project_categories_path + flash[:success] = '更新失败' + end + end + + def destroy + if @project_language.destroy + redirect_to admins_project_categories_path + flash[:success] = "删除成功" + else + redirect_to admins_project_categories_path + flash[:danger] = "删除失败" + end + end + + private + + def get_category + @project_category = ProjectCategory.find_by(id: params[:id]) + unless @project_category.present? + redirect_to admins_project_categories_path + flash[:danger] = "分类不存在" + end + end + + def check_language_present?(name) + return true if name.blank? + name_downcase = name.downcase + name_upcase = name.upcase + name_first_big = name.capitalize + ProjectCategory.exists?(name: name_downcase) || ProjectCategory.exists?(name: name_upcase) || ProjectCategory.exists?(name: name_first_big) + end + + def validate_names + @name = params[:project_category][:name].to_s.first(64) + if @name.blank? + redirect_to admins_project_categories_path + flash[:danger] = '名称不能为空' + elsif check_language_present?(@name) && @project_category.blank? + redirect_to admins_project_categories_path + flash[:danger] = '分类已存在' + end + end +end \ No newline at end of file diff --git a/app/controllers/admins/project_ignores_controller.rb b/app/controllers/admins/project_ignores_controller.rb new file mode 100644 index 000000000..427ee86b8 --- /dev/null +++ b/app/controllers/admins/project_ignores_controller.rb @@ -0,0 +1,120 @@ +class Admins::ProjectIgnoresController < Admins::BaseController + before_action :set_ignore, only: [:edit,:update, :destroy,:show] + before_action :validate_params, only: [:create, :update] + + def index + sort_by = params[:sort_by] ||= 'created_at' + sort_direction = params[:sort_direction] ||= 'desc' + q = Ignore.ransack(name_cont: params[:search]) + project_ignores = q.result(distinct: true).order("#{sort_by} #{sort_direction}") + @project_ignores = paginate(project_ignores) + end + + def new + @project_ignore = Ignore.new + end + + def show + end + + def create + # conditions = params[:license][:conditions_array].reject(&:blank?).join(",") if params[:license][:conditions_array].present? + # permissions = params[:license][:permissions_array].reject(&:blank?).join(",") if params[:license][:permissions_array].present? + # limitations = params[:license][:limitations_array].reject(&:blank?).join(",") if params[:license][:limitations_array].present? + # max_position_items = License.select(:id, :position).pluck(:position).reject!(&:blank?) + # max_position = max_position_items.present? ? max_position_items.max.to_i : 0 + # other_params = { + # conditions: conditions.to_s, + # permissions: permissions.to_s, + # limitations: limitations.to_s, + # position: max_position + # } + @project_ignore = Ignore.new(ignore_params) + + if @project_ignore.save! + redirect_to admins_project_ignores_path + flash[:success] = "创建成功" + else + render :new + flash[:danger] = "创建失败" + end + end + + def edit + + end + + def update + # conditions = params[:license][:conditions_array].reject(&:blank?).join(",") if params[:license][:conditions_array].present? + # permissions = params[:license][:permissions_array].reject(&:blank?).join(",") if params[:license][:permissions_array].present? + # limitations = params[:license][:limitations_array].reject(&:blank?).join(",") if params[:license][:limitations_array].present? + + # other_params = { + # conditions: conditions.to_s, + # permissions: permissions.to_s, + # limitations: limitations.to_s + # } + if @project_ignore.update_attributes(ignore_params) + redirect_to admins_project_ignores_path + flash[:success] = "更新成功" + else + render :edit + flash[:danger] = "更新失败" + end + end + + def destroy + if @project_ignore.present? + if @project_ignore.destroy + redirect_to admins_project_ignores_path + flash[:success] = "删除成功" + else + redirect_to admins_project_ignores_path + flash[:success] = "删除失败" + end + else + redirect_to admins_project_ignores_path + flash[:success] = "删除失败:许可证已被项目引用" + end + end + + # def move + # cate_opt = params[:opr] + # cate_position = @project_license.position.to_i + # move_status = up_and_down(cate_opt,@project_license,cate_position,"license") + # if move_status == 0 + # @c_msg = "移动成功" + # else + # @c_msg = "移动失败" + # end + # end + + private + def set_ignore + @project_ignore = Ignore.find_by_id(params[:id]) + end + + def ignore_params + params.require(:ignore).permit(:name,:content) + end + + def validate_params + name = params[:ignore][:name] + if name.blank? + flash[:danger] = "名称不允许为空" + redirect_to admins_project_ignores_path + elsif check_ignore_present?(name) && @project_ignore.blank? + flash[:danger] = "创建失败:名称已存在" + redirect_to admins_project_ignores_path + end + end + + def check_ignore_present?(name) + return true if name.blank? + name_downcase = name.downcase + name_upcase = name.upcase + name_first_big = name.capitalize + Ignore.exists?(name: name_downcase) || Ignore.exists?(name: name_upcase) || Ignore.exists?(name: name_first_big) + end + +end diff --git a/app/controllers/admins/project_languages_controller.rb b/app/controllers/admins/project_languages_controller.rb new file mode 100644 index 000000000..e188b75ef --- /dev/null +++ b/app/controllers/admins/project_languages_controller.rb @@ -0,0 +1,82 @@ +class Admins::ProjectLanguagesController < Admins::BaseController + before_action :get_language, only: [:edit,:update, :destroy] + before_action :validate_names, only: [:create, :update] + + def index + sort_by = params[:sort_by] ||= 'created_at' + sort_direction = params[:sort_direction] ||= 'desc' + q = ProjectLanguage.ransack(name_cont: params[:search]) + project_languages = q.result(distinct: true).order("#{sort_by} #{sort_direction}") + @project_languages = paginate(project_languages) + + end + + def new + @project_language = ProjectLanguage.new + end + + def edit + end + + def create + max_position_items = ProjectLanguage.select(:id, :position).pluck(:position).reject!(&:blank?) + max_position = max_position_items.present? ? max_position_items.max.to_i : 0 + @project_language = ProjectLanguage.new(name: @name,position:max_position) + if @project_language.save + redirect_to admins_project_languages_path + flash[:success] = '创建成功' + else + redirect_to admins_project_languages_path + flash[:danger] = '创建失败' + end + end + + def update + if @project_language.update_attribute(:name, @name) + redirect_to admins_project_languages_path + flash[:success] = '更新成功' + else + redirect_to admins_project_languages_path + flash[:success] = '更新失败' + end + end + + def destroy + if @project_language.destroy + redirect_to admins_project_languages_path + flash[:success] = "项目语言删除成功" + else + redirect_to admins_project_languages_path + flash[:danger] = "项目语言删除失败" + end + end + + private + + def get_language + @project_language = ProjectLanguage.find_by(id: params[:id]) + unless @project_language.present? + redirect_to admins_project_languages_path + flash[:danger] = "项目语言不存在" + end + end + + def check_language_present?(name) + return true if name.blank? + name_downcase = name.downcase + name_upcase = name.upcase + name_first_big = name.capitalize + ProjectLanguage.exists?(name: name_downcase) || ProjectLanguage.exists?(name: name_upcase) || ProjectLanguage.exists?(name: name_first_big) + end + + def validate_names + @name = params[:project_language][:name].to_s.first(64) + if @name.blank? + redirect_to admins_project_languages_path + flash[:danger] = '名称不能为空' + elsif check_language_present?(@name) && @project_language.blank? + redirect_to admins_project_languages_path + flash[:danger] = '项目语言已存在' + end + end +end \ No newline at end of file diff --git a/app/controllers/admins/project_licenses_controller.rb b/app/controllers/admins/project_licenses_controller.rb new file mode 100644 index 000000000..bc5789026 --- /dev/null +++ b/app/controllers/admins/project_licenses_controller.rb @@ -0,0 +1,120 @@ +class Admins::ProjectLicensesController < Admins::BaseController + before_action :set_license, only: [:edit,:update, :destroy,:show] + before_action :validate_params, only: [:create, :update] + + def index + sort_by = params[:sort_by] ||= 'created_at' + sort_direction = params[:sort_direction] ||= 'desc' + q = License.ransack(name_cont: params[:search]) + project_licenses = q.result(distinct: true).order("#{sort_by} #{sort_direction}") + @project_licenses = paginate(project_licenses) + end + + def new + @project_license = License.new + end + + def show + end + + def create + # conditions = params[:license][:conditions_array].reject(&:blank?).join(",") if params[:license][:conditions_array].present? + # permissions = params[:license][:permissions_array].reject(&:blank?).join(",") if params[:license][:permissions_array].present? + # limitations = params[:license][:limitations_array].reject(&:blank?).join(",") if params[:license][:limitations_array].present? + # max_position_items = License.select(:id, :position).pluck(:position).reject!(&:blank?) + # max_position = max_position_items.present? ? max_position_items.max.to_i : 0 + # other_params = { + # conditions: conditions.to_s, + # permissions: permissions.to_s, + # limitations: limitations.to_s, + # position: max_position + # } + @project_license = License.new(license_params) + + if @project_license.save! + redirect_to admins_project_licenses_path + flash[:success] = "创建成功" + else + render :new + flash[:danger] = "创建失败" + end + end + + def edit + + end + + def update + # conditions = params[:license][:conditions_array].reject(&:blank?).join(",") if params[:license][:conditions_array].present? + # permissions = params[:license][:permissions_array].reject(&:blank?).join(",") if params[:license][:permissions_array].present? + # limitations = params[:license][:limitations_array].reject(&:blank?).join(",") if params[:license][:limitations_array].present? + + # other_params = { + # conditions: conditions.to_s, + # permissions: permissions.to_s, + # limitations: limitations.to_s + # } + if @project_license.update_attributes(license_params) + redirect_to admins_project_licenses_path + flash[:success] = "更新成功" + else + render :edit + flash[:danger] = "更新失败" + end + end + + def destroy + if @project_license.present? + if @project_license.destroy + redirect_to admins_project_licenses_path + flash[:success] = "删除成功" + else + redirect_to admins_project_licenses_path + flash[:success] = "删除失败" + end + else + redirect_to admins_project_licenses_path + flash[:success] = "删除失败:许可证已被项目引用" + end + end + + # def move + # cate_opt = params[:opr] + # cate_position = @project_license.position.to_i + # move_status = up_and_down(cate_opt,@project_license,cate_position,"license") + # if move_status == 0 + # @c_msg = "移动成功" + # else + # @c_msg = "移动失败" + # end + # end + + private + def set_license + @project_license = License.find_by_id(params[:id]) + end + + def license_params + params.require(:license).permit(:name,:content) + end + + def validate_params + name = params[:license][:name] + if name.blank? + flash[:danger] = "名称不允许为空" + redirect_to admins_project_licenses_path + elsif check_license_present?(name) && @project_license.blank? + flash[:danger] = "创建失败:名称已存在" + redirect_to admins_project_licenses_path + end + end + + def check_license_present?(name) + return true if name.blank? + name_downcase = name.downcase + name_upcase = name.upcase + name_first_big = name.capitalize + License.exists?(name: name_downcase) || License.exists?(name: name_upcase) || License.exists?(name: name_first_big) + end + +end diff --git a/app/controllers/admins/projects_controller.rb b/app/controllers/admins/projects_controller.rb index 53d94fd9b..2ef79a8e9 100644 --- a/app/controllers/admins/projects_controller.rb +++ b/app/controllers/admins/projects_controller.rb @@ -1,10 +1,11 @@ class Admins::ProjectsController < Admins::BaseController def index - default_sort('created_at', 'desc') + sort_by = params[:sort_by] ||= 'created_on' + sort_direction = params[:sort_direction] ||= 'desc' search = params[:search].to_s.strip - projects = Project.where("name like ?", "%#{search}%") + projects = Project.where("name like ?", "%#{search}%").order("#{sort_by} #{sort_direction}") @projects = paginate projects.includes(:owner, :members, :issues, :versions, :attachments, :project_score) end @@ -21,5 +22,4 @@ class Admins::ProjectsController < Admins::BaseController render_delete_success end end - end \ No newline at end of file diff --git a/app/controllers/admins/users_controller.rb b/app/controllers/admins/users_controller.rb index dee37b0ba..98f0a6bfb 100644 --- a/app/controllers/admins/users_controller.rb +++ b/app/controllers/admins/users_controller.rb @@ -4,7 +4,7 @@ class Admins::UsersController < Admins::BaseController params[:sort_direction] = params[:sort_direction].presence || 'desc' users = Admins::UserQuery.call(params) - @users = paginate users.includes(:user_extension) + @users = paginate users.includes(:user_extension, projects: :members) end def edit diff --git a/app/models/user.rb b/app/models/user.rb index a093665f3..e729b898e 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -607,7 +607,7 @@ class User < ApplicationRecord end def projects_count - Project.joins(:members).where(members: { user_id: self.id }).select(:id).size + Project.includes(:members).joins(:members).where(members: { user_id: self.id }).select(:id).size end # 是否已经签到 diff --git a/app/views/admins/project_categories/_form_modal.html.erb b/app/views/admins/project_categories/_form_modal.html.erb new file mode 100644 index 000000000..fd20936b6 --- /dev/null +++ b/app/views/admins/project_categories/_form_modal.html.erb @@ -0,0 +1,21 @@ + \ No newline at end of file diff --git a/app/views/admins/project_categories/_list.html.erb b/app/views/admins/project_categories/_list.html.erb new file mode 100644 index 000000000..1d3316817 --- /dev/null +++ b/app/views/admins/project_categories/_list.html.erb @@ -0,0 +1,33 @@ + + + + + + + + + + + + <% if project_categories.present? %> + <% project_categories.each_with_index do |project_category, index| %> + + + + + + + + <% end %> + <% else %> + <%= render 'admins/shared/no_data_for_table' %> + <% end %> + +
序号名称<%= sort_tag('项目数', name: 'projects_count', path: admins_project_categories_path) %><%= sort_tag('创建时间', name: 'created_at', path: admins_project_categories_path) %>操作
<%= list_index_no((params[:page] || 1).to_i, index) %> + <%= link_to(project_category.name, "/projects?category_id=#{project_category.id}", target: '_blank') %> + <%= project_category.projects_count %><%= project_category.created_at&.strftime('%Y-%m-%d %H:%M') %> + <%= link_to "编辑", edit_admins_project_category_path(project_category), remote: true, class: "action" %> + <%= link_to "删除", admins_project_category_path(project_category), method: :delete, data:{confirm: "确认删除的吗?"}, class: "action" %> +
+ +<%= render partial: 'admins/shared/paginate', locals: { objects: project_categories } %> \ No newline at end of file diff --git a/app/views/admins/project_categories/edit.js.erb b/app/views/admins/project_categories/edit.js.erb new file mode 100644 index 000000000..a8636cfce --- /dev/null +++ b/app/views/admins/project_categories/edit.js.erb @@ -0,0 +1,2 @@ +$("#project-category-modals").html("<%= j render(partial: 'admins/project_categories/form_modal', locals: {type: 'update'}) %>") +$(".project-category-change-modal").modal('show'); \ No newline at end of file diff --git a/app/views/admins/project_categories/index.html.erb b/app/views/admins/project_categories/index.html.erb new file mode 100644 index 000000000..b635cef43 --- /dev/null +++ b/app/views/admins/project_categories/index.html.erb @@ -0,0 +1,18 @@ +<% define_admin_breadcrumbs do %> + <% add_admin_breadcrumb('分类列表') %> +<% end %> + +
+ <%= form_tag(admins_project_categories_path, method: :get, class: 'form-inline search-form flex-1', remote: true) do %> + <%= text_field_tag(:search, params[:search], class: 'form-control col-12 col-md-2 mr-3', placeholder: '名称检索') %> + <%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %> + + <% end %> + <%= link_to "新增", new_admins_project_category_path, remote: true, class: "btn btn-primary pull-right", "data-disabled-with":"...新增" %> +
+ +
+ <%= render partial: 'admins/project_categories/list', locals: { project_categories: @project_categories } %> +
+
+
diff --git a/app/views/admins/project_categories/index.js.erb b/app/views/admins/project_categories/index.js.erb new file mode 100644 index 000000000..0a5ef2d13 --- /dev/null +++ b/app/views/admins/project_categories/index.js.erb @@ -0,0 +1 @@ +$('.project-category-list-container').html("<%= j( render partial: 'admins/project_categories/list', locals: { project_categories: @project_categories } ) %>"); \ No newline at end of file diff --git a/app/views/admins/project_categories/new.js.erb b/app/views/admins/project_categories/new.js.erb new file mode 100644 index 000000000..8266fd40c --- /dev/null +++ b/app/views/admins/project_categories/new.js.erb @@ -0,0 +1,2 @@ +$("#project-category-modals").html("<%= j render(partial: 'admins/project_categories/form_modal', locals: {type: 'create'}) %>") +$(".project-category-change-modal").modal('show'); \ No newline at end of file diff --git a/app/views/admins/project_ignores/_content.html.erb b/app/views/admins/project_ignores/_content.html.erb new file mode 100644 index 000000000..048feadb8 --- /dev/null +++ b/app/views/admins/project_ignores/_content.html.erb @@ -0,0 +1,9 @@ +
+
<%= @project_ignore.name %>
+ <%= link_to "返回", admins_project_ignores_path, class: "btn btn-default pull-right" %> +
+ +
+<%= @project_ignore.content.html_safe %> + +
\ No newline at end of file diff --git a/app/views/admins/project_ignores/_form.html.erb b/app/views/admins/project_ignores/_form.html.erb new file mode 100644 index 000000000..9a6ded0ba --- /dev/null +++ b/app/views/admins/project_ignores/_form.html.erb @@ -0,0 +1,38 @@ +
+
<%= type == "create" ? "新建" : "编辑" %>忽略文件
+ <%= link_to "返回", admins_project_ignores_path, class: "btn btn-default pull-right" %> +
+ +
+ <%= form_for @project_ignore, url: {controller: "project_ignores", action: "#{type}"} do |f| %> +
+ +
+ <%= f.text_field :name, class: "form-control input-lg", maxlength: "60", placeholder: "请输入忽略文件的全称" %> +
+ +
+
+ +
+ <%= f.text_area :content,class:"form-control", rows: "10", cols: "20",placeholer: "忽略文件的简要介绍,不得超过500字" %> +
+ + + +
+
+ <%= f.submit "确认", class: "btn btn-primary submit-btn" %> +
+ <% end %> +
\ No newline at end of file diff --git a/app/views/admins/project_ignores/_list.html.erb b/app/views/admins/project_ignores/_list.html.erb new file mode 100644 index 000000000..066ef8540 --- /dev/null +++ b/app/views/admins/project_ignores/_list.html.erb @@ -0,0 +1,45 @@ + + + + + + + <% +=begin%> + +<% +=end%> + + + + + + <% if project_ignores.present? %> + <% project_ignores.each_with_index do |project_ignore, index| %> + + + + + <% +=begin%> + +<% +=end%> + + + + <% end %> + <% else %> + <%= render 'admins/shared/no_data_for_table' %> + <% end %> + +
序号名称简介<%= sort_tag('项目数', name: 'projects_count', path: admins_project_licenses_path) %><%= sort_tag('创建时间', name: 'created_at', path: admins_project_licenses_path) %>操作
<%= list_index_no((params[:page] || 1).to_i, index) %> + <%= link_to project_ignore.name, admins_project_ignore_path(project_ignore.id), remote: true %> + + <%= project_ignore.content.to_s.truncate(200) %> + <%= project_license.projects_count %><%= project_ignore.created_at&.strftime('%Y-%m-%d %H:%M') %> + <%= link_to "编辑", edit_admins_project_ignore_path(project_ignore),remote: true, class: "action" %> + <%= link_to "删除", admins_project_ignore_path(project_ignore), method: :delete, data:{confirm: "确认删除的吗?"}, class: "action" %> +
+ +<%= render partial: 'admins/shared/paginate', locals: { objects: project_ignores } %> \ No newline at end of file diff --git a/app/views/admins/project_ignores/edit.js.erb b/app/views/admins/project_ignores/edit.js.erb new file mode 100644 index 000000000..36fe6852a --- /dev/null +++ b/app/views/admins/project_ignores/edit.js.erb @@ -0,0 +1 @@ +$("#admins-project-ignore-content").html("<%= j render partial: 'admins/project_ignores/form', locals:{type: 'update'} %>") \ No newline at end of file diff --git a/app/views/admins/project_ignores/index.html.erb b/app/views/admins/project_ignores/index.html.erb new file mode 100644 index 000000000..a9fc9982e --- /dev/null +++ b/app/views/admins/project_ignores/index.html.erb @@ -0,0 +1,18 @@ +<% define_admin_breadcrumbs do %> + <% add_admin_breadcrumb('git忽略文件') %> +<% end %> +
+
+ <%= form_tag(admins_project_ignores_path, method: :get, class: 'form-inline search-form flex-1', remote: true) do %> + <%= text_field_tag(:search, params[:search], class: 'form-control col-12 col-md-2 mr-3', placeholder: '名称检索') %> + <%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %> + + <% end %> + <%= link_to "新增", new_admins_project_ignore_path, remote: true, class: "btn btn-primary pull-right", "data-disabled-with":"...新增" %> +
+ +
+ <%= render partial: 'admins/project_ignores/list', locals: { project_ignores: @project_ignores } %> +
+
+ diff --git a/app/views/admins/project_ignores/index.js.erb b/app/views/admins/project_ignores/index.js.erb new file mode 100644 index 000000000..9d86113c1 --- /dev/null +++ b/app/views/admins/project_ignores/index.js.erb @@ -0,0 +1 @@ +$('.project-ignore-list-container').html("<%= j( render partial: 'admins/project_ignores/list', locals: { project_ignores: @project_ignores } ) %>"); \ No newline at end of file diff --git a/app/views/admins/project_ignores/new.js.erb b/app/views/admins/project_ignores/new.js.erb new file mode 100644 index 000000000..607a092e6 --- /dev/null +++ b/app/views/admins/project_ignores/new.js.erb @@ -0,0 +1 @@ +$("#admins-project-ignore-content").html("<%= j render partial: 'admins/project_ignores/form', locals:{type: 'create'} %>") \ No newline at end of file diff --git a/app/views/admins/project_ignores/show.js.erb b/app/views/admins/project_ignores/show.js.erb new file mode 100644 index 000000000..0c99dd7fd --- /dev/null +++ b/app/views/admins/project_ignores/show.js.erb @@ -0,0 +1 @@ +$("#admins-project-ignore-content").html("<%= j render partial: 'admins/project_ignores/content' %>") \ No newline at end of file diff --git a/app/views/admins/project_languages/_form_modal.html.erb b/app/views/admins/project_languages/_form_modal.html.erb new file mode 100644 index 000000000..79ceae969 --- /dev/null +++ b/app/views/admins/project_languages/_form_modal.html.erb @@ -0,0 +1,21 @@ + \ No newline at end of file diff --git a/app/views/admins/project_languages/_list.html.erb b/app/views/admins/project_languages/_list.html.erb new file mode 100644 index 000000000..9afaca07c --- /dev/null +++ b/app/views/admins/project_languages/_list.html.erb @@ -0,0 +1,33 @@ + + + + + + + + + + + + <% if project_languages.present? %> + <% project_languages.each_with_index do |project_language, index| %> + + + + + + + + <% end %> + <% else %> + <%= render 'admins/shared/no_data_for_table' %> + <% end %> + +
序号名称<%= sort_tag('项目数', name: 'projects_count', path: admins_project_languages_path) %><%= sort_tag('创建时间', name: 'created_at', path: admins_project_languages_path) %>操作
<%= list_index_no((params[:page] || 1).to_i, index) %> + <%= link_to(project_language.name, "javascript:void(0)") %> + <%= project_language.projects_count %><%= project_language.created_at&.strftime('%Y-%m-%d %H:%M') %> + <%= link_to "编辑", edit_admins_project_language_path(project_language), remote: true, class: "action" %> + <%= link_to "删除", admins_project_language_path(project_language), method: :delete, data:{confirm: "确认删除的吗?"}, class: "action" %> +
+ +<%= render partial: 'admins/shared/paginate', locals: { objects: project_languages } %> \ No newline at end of file diff --git a/app/views/admins/project_languages/edit.js.erb b/app/views/admins/project_languages/edit.js.erb new file mode 100644 index 000000000..4bd5aef5a --- /dev/null +++ b/app/views/admins/project_languages/edit.js.erb @@ -0,0 +1,2 @@ +$("#project-language-modals").html("<%= j render(partial: 'admins/project_languages/form_modal', locals: {type: 'update'}) %>") +$(".project-language-change-modal").modal('show'); \ No newline at end of file diff --git a/app/views/admins/project_languages/index.html.erb b/app/views/admins/project_languages/index.html.erb new file mode 100644 index 000000000..ae1d81ee4 --- /dev/null +++ b/app/views/admins/project_languages/index.html.erb @@ -0,0 +1,18 @@ +<% define_admin_breadcrumbs do %> + <% add_admin_breadcrumb('项目语言') %> +<% end %> + +
+ <%= form_tag(admins_project_languages_path, method: :get, class: 'form-inline search-form flex-1', remote: true) do %> + <%= text_field_tag(:search, params[:search], class: 'form-control col-12 col-md-2 mr-3', placeholder: '名称检索') %> + <%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %> + + <% end %> + <%= link_to "新增", new_admins_project_language_path, remote: true, class: "btn btn-primary pull-right", "data-disabled-with":"...新增" %> +
+ +
+ <%= render partial: 'admins/project_languages/list', locals: { project_languages: @project_languages } %> +
+
+
diff --git a/app/views/admins/project_languages/index.js.erb b/app/views/admins/project_languages/index.js.erb new file mode 100644 index 000000000..3bd78628c --- /dev/null +++ b/app/views/admins/project_languages/index.js.erb @@ -0,0 +1 @@ +$('.project-language-list-container').html("<%= j( render partial: 'admins/project_languages/list', locals: { project_languages: @project_languages } ) %>"); \ No newline at end of file diff --git a/app/views/admins/project_languages/new.js.erb b/app/views/admins/project_languages/new.js.erb new file mode 100644 index 000000000..4b88b4f8b --- /dev/null +++ b/app/views/admins/project_languages/new.js.erb @@ -0,0 +1,2 @@ +$("#project-language-modals").html("<%= j render(partial: 'admins/project_languages/form_modal', locals: {type: 'create'}) %>") +$(".project-language-change-modal").modal('show'); \ No newline at end of file diff --git a/app/views/admins/project_licenses/_content.html.erb b/app/views/admins/project_licenses/_content.html.erb new file mode 100644 index 000000000..f25189a49 --- /dev/null +++ b/app/views/admins/project_licenses/_content.html.erb @@ -0,0 +1,9 @@ +
+
<%= @project_license.name %>
+ <%= link_to "返回", admins_project_licenses_path, class: "btn btn-default pull-right" %> +
+ +
+<%= @project_license.content.html_safe %> + +
\ No newline at end of file diff --git a/app/views/admins/project_licenses/_form.html.erb b/app/views/admins/project_licenses/_form.html.erb new file mode 100644 index 000000000..115b67935 --- /dev/null +++ b/app/views/admins/project_licenses/_form.html.erb @@ -0,0 +1,38 @@ +
+
<%= type == "create" ? "新建" : "编辑" %>开源许可证
+ <%= link_to "返回", admins_project_licenses_path, class: "btn btn-default pull-right" %> +
+ +
+ <%= form_for @project_license, url: {controller: "project_licenses", action: "#{type}"} do |f| %> +
+ +
+ <%= f.text_field :name, class: "form-control input-lg", maxlength: "60", placeholder: "请输入开源许可证的全称" %> +
+ +
+
+ +
+ <%= f.text_area :content,class:"form-control", rows: "10", cols: "20",placeholer: "许可证的简要介绍,不得超过500字" %> +
+ + + +
+
+ <%= f.submit "确认", class: "btn btn-primary submit-btn" %> +
+ <% end %> +
\ No newline at end of file diff --git a/app/views/admins/project_licenses/_list.html.erb b/app/views/admins/project_licenses/_list.html.erb new file mode 100644 index 000000000..1fa4f8d6b --- /dev/null +++ b/app/views/admins/project_licenses/_list.html.erb @@ -0,0 +1,45 @@ + + + + + + + <% +=begin%> + +<% +=end%> + + + + + + <% if project_licenses.present? %> + <% project_licenses.each_with_index do |project_license, index| %> + + + + + <% +=begin%> + +<% +=end%> + + + + <% end %> + <% else %> + <%= render 'admins/shared/no_data_for_table' %> + <% end %> + +
序号名称简介<%= sort_tag('项目数', name: 'projects_count', path: admins_project_licenses_path) %><%= sort_tag('创建时间', name: 'created_at', path: admins_project_licenses_path) %>操作
<%= list_index_no((params[:page] || 1).to_i, index) %> + <%= link_to project_license.name, admins_project_license_path(project_license.id), remote: true %> + + <%= project_license.content.to_s.truncate(200) %> + <%= project_license.projects_count %><%= project_license.created_at&.strftime('%Y-%m-%d %H:%M') %> + <%= link_to "编辑", edit_admins_project_license_path(project_license),remote: true, class: "action" %> + <%= link_to "删除", admins_project_license_path(project_license), method: :delete, data:{confirm: "确认删除的吗?"}, class: "action" %> +
+ +<%= render partial: 'admins/shared/paginate', locals: { objects: project_licenses } %> \ No newline at end of file diff --git a/app/views/admins/project_licenses/edit.js.erb b/app/views/admins/project_licenses/edit.js.erb new file mode 100644 index 000000000..ac48e7e15 --- /dev/null +++ b/app/views/admins/project_licenses/edit.js.erb @@ -0,0 +1 @@ +$("#admins-project-license-content").html("<%= j render partial: 'admins/project_licenses/form', locals:{type: 'update'} %>") \ No newline at end of file diff --git a/app/views/admins/project_licenses/index.html.erb b/app/views/admins/project_licenses/index.html.erb new file mode 100644 index 000000000..31e648006 --- /dev/null +++ b/app/views/admins/project_licenses/index.html.erb @@ -0,0 +1,18 @@ +<% define_admin_breadcrumbs do %> + <% add_admin_breadcrumb('开源许可证') %> +<% end %> +
+
+ <%= form_tag(admins_project_licenses_path, method: :get, class: 'form-inline search-form flex-1', remote: true) do %> + <%= text_field_tag(:search, params[:search], class: 'form-control col-12 col-md-2 mr-3', placeholder: '名称检索') %> + <%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %> + + <% end %> + <%= link_to "新增", new_admins_project_license_path, remote: true, class: "btn btn-primary pull-right", "data-disabled-with":"...新增" %> +
+ +
+ <%= render partial: 'admins/project_licenses/list', locals: { project_licenses: @project_licenses } %> +
+
+ diff --git a/app/views/admins/project_licenses/index.js.erb b/app/views/admins/project_licenses/index.js.erb new file mode 100644 index 000000000..670c34542 --- /dev/null +++ b/app/views/admins/project_licenses/index.js.erb @@ -0,0 +1 @@ +$('.project-license-list-container').html("<%= j( render partial: 'admins/project_licenses/list', locals: { project_licenses: @project_licenses } ) %>"); \ No newline at end of file diff --git a/app/views/admins/project_licenses/new.js.erb b/app/views/admins/project_licenses/new.js.erb new file mode 100644 index 000000000..ee1c173e2 --- /dev/null +++ b/app/views/admins/project_licenses/new.js.erb @@ -0,0 +1 @@ +$("#admins-project-license-content").html("<%= j render partial: 'admins/project_licenses/form', locals:{type: 'create'} %>") \ No newline at end of file diff --git a/app/views/admins/project_licenses/show.js.erb b/app/views/admins/project_licenses/show.js.erb new file mode 100644 index 000000000..eddc040e9 --- /dev/null +++ b/app/views/admins/project_licenses/show.js.erb @@ -0,0 +1 @@ +$("#admins-project-license-content").html("<%= j render partial: 'admins/project_licenses/content' %>") \ No newline at end of file diff --git a/app/views/admins/projects/shared/_list.html.erb b/app/views/admins/projects/shared/_list.html.erb index e2a6307ad..90c328792 100644 --- a/app/views/admins/projects/shared/_list.html.erb +++ b/app/views/admins/projects/shared/_list.html.erb @@ -12,7 +12,7 @@ 里程碑 成员 管理员 - <%= sort_tag('创建时间', name: 'created_at', path: admins_projects_path) %> + <%= sort_tag('创建时间', name: 'created_on', path: admins_projects_path) %> 操作 diff --git a/app/views/admins/shared/_sidebar.html.erb b/app/views/admins/shared/_sidebar.html.erb index d89e9a6f8..7287c0347 100644 --- a/app/views/admins/shared/_sidebar.html.erb +++ b/app/views/admins/shared/_sidebar.html.erb @@ -14,54 +14,18 @@ diff --git a/app/views/admins/users/index.html.erb b/app/views/admins/users/index.html.erb index 74c9215b2..37ca242e3 100644 --- a/app/views/admins/users/index.html.erb +++ b/app/views/admins/users/index.html.erb @@ -23,12 +23,20 @@ <%= text_field_tag(:keyword, params[:keyword], class: 'form-control col-sm-2 ml-3', placeholder: 'ID/姓名/邮箱/手机号检索') %> - <%= text_field_tag(:school_name, params[:school_name], class: 'form-control col-sm-2', placeholder: '学校/单位检索') %> + <% +=begin%> + <%= text_field_tag(:school_name, params[:school_name], class: 'form-control col-sm-2', placeholder: '学校/单位检索') %> +<% +=end%> <%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %> <% end %> <%= javascript_void_link '导入用户', class: 'btn btn-secondary btn-sm', data: { toggle: 'modal', target: '.admin-import-user-modal'} %> - <%= javascript_void_link '导入课堂成员', class: 'btn btn-secondary btn-sm ml-2', data: { toggle: 'modal', target: '.admin-import-course-member-modal'} %> + <% +=begin%> + <%= javascript_void_link '导入课堂成员', class: 'btn btn-secondary btn-sm ml-2', data: { toggle: 'modal', target: '.admin-import-course-member-modal'} %> +<% +=end%>
diff --git a/app/views/admins/users/shared/_user_list.html.erb b/app/views/admins/users/shared/_user_list.html.erb index 2949a087b..5c033d282 100644 --- a/app/views/admins/users/shared/_user_list.html.erb +++ b/app/views/admins/users/shared/_user_list.html.erb @@ -8,8 +8,7 @@ 角色 <%= sort_tag('创建于', name: 'created_on', path: admins_users_path) %> <%= sort_tag('最后登录', name: 'last_login_on', path: admins_users_path) %> - <%= sort_tag('经验值', name: 'experience', path: admins_users_path) %> - <%= sort_tag('金币', name: 'grade', path: admins_users_path) %> + 项目数 操作 @@ -28,8 +27,7 @@ <%= user.identity %> <%= display_text(user.created_on&.strftime('%Y-%m-%d %H:%M')) %> <%= display_text(user.last_login_on&.strftime('%Y-%m-%d %H:%M')) %> - <%= user.experience.to_i %> - <%= user.grade.to_i %> + <%= link_to user.projects_count, "/users/#{user.login}/projects", target: "_blank" %> <%= link_to '编辑', edit_admins_user_path(user), class: 'action' %> diff --git a/app/views/layouts/admin.html.erb b/app/views/layouts/admin.html.erb index f61aaba4f..91a77bf65 100644 --- a/app/views/layouts/admin.html.erb +++ b/app/views/layouts/admin.html.erb @@ -1,7 +1,7 @@ - EduCoder后台管理 + ForgePlus后台管理 diff --git a/config/routes.rb b/config/routes.rb index 8c124d658..af21e3bb1 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -2,9 +2,9 @@ Rails.application.routes.draw do require 'sidekiq/web' require 'admin_constraint' - # mount Sidekiq::Web => '/sidekiq' + mount Sidekiq::Web => '/sidekiq' - mount Sidekiq::Web => '/sidekiq', :constraints => AdminConstraint.new + # mount Sidekiq::Web => '/sidekiq', :constraints => AdminConstraint.new get 'attachments/download/:id', to: 'attachments#show' get 'attachments/download/:id/:filename', to: 'attachments#show' @@ -389,6 +389,10 @@ Rails.application.routes.draw do get :visits_static end end + resources :project_languages + resources :project_categories + resources :project_licenses + resources :project_ignores resources :major_informations, only: [:index] resources :ec_templates, only: [:index, :destroy] do collection do diff --git a/public/favicon.ico b/public/favicon.ico old mode 100755 new mode 100644 index 9c65fe8c7b77e9399a75f48500339c9bf2f74cb4..75a4c3dfd46656c981907ac9d82ddce23c622d7f GIT binary patch literal 10415 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