Skip to content
Snippets Groups Projects
Commit 42bac7f9 authored by Steven Thonus's avatar Steven Thonus Committed by Hannes Rosenögger
Browse files

adding avatar to project settings page added avatar removal show project...

adding avatar to project settings page added avatar removal show project avatar on dashboard, projects page, project page added rspec and feature tests added project avatar from repository new default project icon added added copying af avatar to forking of project added generated icon fixed avatar fork hound fix style fix test fix
parent c8c05edc
No related branches found
No related tags found
1 merge request!8686add "Uplaod" and "Replace" functionality
Showing
with 252 additions and 4 deletions
app/assets/images/no_project_icon.png

3.31 KiB

Loading
Loading
@@ -18,3 +18,13 @@ class @Project
$.cookie('hide_no_ssh_message', 'false', { path: path })
$(@).parents('.no-ssh-key-message').hide()
e.preventDefault()
# avatar
$('.js-choose-project-avatar-button').bind "click", ->
form = $(this).closest("form")
form.find(".js-project-avatar-input").click()
$('.js-project-avatar-input').bind "change", ->
form = $(this).closest("form")
filename = $(this).val().replace(/^.*[\\\/]/, '')
form.find(".js-avatar-filename").text(filename)
Loading
Loading
@@ -23,3 +23,16 @@
&.s90 { width: 90px; height: 90px; margin-right: 15px; }
&.s160 { width: 160px; height: 160px; margin-right: 20px; }
}
.identicon {
text-align: center;
vertical-align: top;
&.s16 { font-size: 12px; line-height: 1.33; }
&.s24 { font-size: 18px; line-height: 1.33; }
&.s26 { font-size: 20px; line-height: 1.33; }
&.s32 { font-size: 24px; line-height: 1.33; }
&.s60 { font-size: 45px; line-height: 1.33; }
&.s90 { font-size: 68px; line-height: 1.33; }
&.s160 { font-size: 120px; line-height: 1.33; }
}
\ No newline at end of file
Loading
Loading
@@ -75,6 +75,9 @@
}
}
}
.project-avatar {
float: left;
}
 
.project-description {
overflow: hidden;
Loading
Loading
@@ -92,6 +95,9 @@
}
}
 
.dash-project-avatar {
float: left;
}
.dash-project-access-icon {
float: left;
margin-right: 3px;
Loading
Loading
class Projects::AvatarsController < Projects::ApplicationController
layout 'project'
before_filter :project
def show
@blob = @project.repository.blob_at_branch('master', @project.avatar_in_git)
if @blob
headers['X-Content-Type-Options'] = 'nosniff'
send_data(
@blob.data,
type: @blob.mime_type,
disposition: 'inline',
filename: @blob.name
)
else
not_found!
end
end
def destroy
@project.remove_avatar!
@project.save
@project.reset_events_cache
redirect_to edit_project_path(@project)
end
end
Loading
Loading
@@ -50,6 +50,31 @@ module ApplicationHelper
args.any? { |v| v.to_s.downcase == action_name }
end
 
def project_icon(project_id, options = {})
project = Project.find_with_namespace(project_id)
if project.avatar.present?
image_tag project.avatar.url, options
elsif options[:only_uploaded]
image_tag '/assets/no_project_icon.png', options
elsif project.avatar_in_git
image_tag project_avatar_path(project), options
else # generated icon
project_identicon(project, options)
end
end
def project_identicon(project, options = {})
options[:class] ||= ''
options[:class] << ' identicon'
bg_color = Digest::MD5.hexdigest(project.name)[0, 6]
brightness = bg_color[0, 2].hex + bg_color[2, 2].hex + bg_color[4, 2].hex
text_color = (brightness > 375) ? '#000' : '#fff'
content_tag(:div, class: options[:class],
style: "background-color: ##{ bg_color }; color: #{ text_color }") do
project.name[0, 1].upcase
end
end
def group_icon(group_path)
group = Group.find_by(path: group_path)
if group && group.avatar.present?
Loading
Loading
Loading
Loading
@@ -26,6 +26,7 @@
# star_count :integer default(0), not null
# import_type :string(255)
# import_source :string(255)
# avatar :string(255)
#
 
class Project < ActiveRecord::Base
Loading
Loading
@@ -119,6 +120,11 @@ class Project < ActiveRecord::Base
if: :import?
validates :star_count, numericality: { greater_than_or_equal_to: 0 }
validate :check_limit, on: :create
validate :avatar_type,
if: ->(project) { project.avatar && project.avatar_changed? }
validates :avatar, file_size: { maximum: 100.kilobytes.to_i }
mount_uploader :avatar, AttachmentUploader
 
# Scopes
scope :without_user, ->(user) { where("projects.id NOT IN (:ids)", ids: user.authorized_projects.map(&:id) ) }
Loading
Loading
@@ -338,6 +344,24 @@ class Project < ActiveRecord::Base
@ci_service ||= ci_services.select(&:activated?).first
end
 
def avatar_type
unless avatar.image?
errors.add :avatar, 'only images allowed'
end
end
def avatar_in_git
@avatar_file ||= 'logo.png' if repository.blob_at_branch('master', 'logo.png')
@avatar_file ||= 'logo.jpg' if repository.blob_at_branch('master', 'logo.jpg')
@avatar_file ||= 'logo.gif' if repository.blob_at_branch('master', 'logo.gif')
@avatar_file
end
# For compatibility with old code
def code
path
end
def items_for(entity)
case entity
when 'issue' then
Loading
Loading
@@ -529,6 +553,7 @@ class Project < ActiveRecord::Base
# Since we do cache @event we need to reset cache in special cases:
# * when project was moved
# * when project was renamed
# * when the project avatar changes
# Events cache stored like events/23-20130109142513.
# The cache key includes updated_at timestamp.
# Thus it will automatically generate a new fragment
Loading
Loading
Loading
Loading
@@ -14,6 +14,9 @@ module Projects
project.name = @from_project.name
project.path = @from_project.path
project.creator = @current_user
if @from_project.avatar && @from_project.avatar.image?
project.avatar = @from_project.avatar
end
 
if namespace = @params[:namespace]
project.namespace = namespace
Loading
Loading
= link_to project_path(project), class: dom_class(project) do
.dash-project-avatar
= project_icon(project.to_param, alt: '', class: 'avatar s24')
.dash-project-access-icon
= visibility_level_icon(project.visibility_level)
%span.str-truncated
Loading
Loading
Loading
Loading
@@ -11,6 +11,8 @@
- @projects.each do |project|
%li.my-project-row
%h4.project-title
.project-avatar
= project_icon(project.to_param, alt: '', class: 'avatar s60')
.project-access-icon
= visibility_level_icon(project.visibility_level)
= link_to project_path(project), class: dom_class(project) do
Loading
Loading
Loading
Loading
@@ -2,6 +2,7 @@
.project-home-panel{:class => ("empty-project" if empty_repo)}
.project-home-row
.project-home-desc
= project_icon(@project.to_param, alt: '', class: 'avatar s32')
- if @project.description.present?
= escaped_autolink(@project.description)
- if can?(current_user, :admin_project, @project)
Loading
Loading
Loading
Loading
@@ -7,7 +7,8 @@
%p.light Some settings, such as "Transfer Project", are hidden inside the danger area below.
%hr
.panel-body
= form_for @project, remote: true, html: { class: "edit_project form-horizontal" } do |f|
= form_for @project, remote: true, html: { multipart: true, class: "edit_project form-horizontal" }, authenticity_token: true do |f|
%fieldset
.form-group.project_name_holder
= f.label :name, class: 'control-label' do
Loading
Loading
@@ -80,6 +81,31 @@
= f.check_box :snippets_enabled
%span.descr Share code pastes with others out of git repository
 
%fieldset.features
%legend
Project avatar:
.form-group
.col-sm-2
.col-sm-10
= project_icon(@project.to_param, alt: '', class: 'avatar s160', only_uploaded: true)
%p.light
- if @project.avatar_in_git
Project avatar in repository: #{ @project.avatar_in_git }
%p.light
- if @project.avatar?
You can change your project avatar here
- else
You can upload an project avatar here
%a.choose-btn.btn.btn-small.js-choose-project-avatar-button
%i.icon-paper-clip
%span Choose File ...
&nbsp;
%span.file_name.js-avatar-filename File name...
= f.file_field :avatar, class: "js-project-avatar-input hidden"
.light The maximum file size allowed is 100KB.
- if @project.avatar?
%hr
= link_to 'Remove avatar', project_avatar_path(@project), data: { confirm: "Project avatar will be removed. Are you sure?"}, method: :delete, class: "btn btn-remove btn-small remove-avatar"
 
.form-actions
= f.submit 'Save changes', class: "btn btn-save"
Loading
Loading
Loading
Loading
@@ -353,6 +353,8 @@ Gitlab::Application.routes.draw do
delete :delete_attachment
end
end
resource :avatar, only: [:show, :destroy]
end
end
 
Loading
Loading
class AddAvatarToProjects < ActiveRecord::Migration
def change
add_column :projects, :avatar, :string
end
end
Loading
Loading
@@ -327,6 +327,7 @@ ActiveRecord::Schema.define(version: 20150116234544) do
t.integer "star_count", default: 0, null: false
t.string "import_type"
t.string "import_source"
t.string "avatar"
end
 
add_index "projects", ["creator_id"], name: "index_projects_on_creator_id", using: :btree
Loading
Loading
Loading
Loading
@@ -5,6 +5,19 @@ Feature: Project
And project "Shop" has push event
And I visit project "Shop" page
 
Scenario: I edit the project avatar
Given I visit edit project "Shop" page
When I change the project avatar
And I should see new project avatar
And I should see the "Remove avatar" button
Scenario: I remove the project avatar
Given I visit edit project "Shop" page
And I have an project avatar
When I remove my project avatar
Then I should see the default project avatar
And I should not see the "Remove avatar" button
@javascript
Scenario: I should see project activity
When I visit project "Shop" page
Loading
Loading
Loading
Loading
@@ -17,12 +17,53 @@ class Spinach::Features::Project < Spinach::FeatureSteps
end
 
step 'change project path settings' do
fill_in "project_path", with: "new-path"
click_button "Rename"
fill_in 'project_path', with: 'new-path'
click_button 'Rename'
end
 
step 'I should see project with new path settings' do
project.path.should == "new-path"
project.path.should == 'new-path'
end
step 'I change the project avatar' do
attach_file(
:project_avatar,
File.join(Rails.root, 'public', 'gitlab_logo.png')
)
click_button 'Save changes'
@project.reload
end
step 'I should see new project avatar' do
@project.avatar.should be_instance_of AttachmentUploader
url = @project.avatar.url
url.should == "/uploads/project/avatar/#{ @project.id }/gitlab_logo.png"
end
step 'I should see the "Remove avatar" button' do
page.should have_link('Remove avatar')
end
step 'I have an project avatar' do
attach_file(
:project_avatar,
File.join(Rails.root, 'public', 'gitlab_logo.png')
)
click_button 'Save changes'
@project.reload
end
step 'I remove my project avatar' do
click_link 'Remove avatar'
@project.reload
end
step 'I should see the default project avatar' do
@project.avatar?.should be_false
end
step 'I should not see the "Remove avatar" button' do
page.should_not have_link('Remove avatar')
end
 
step 'I should see project "Shop" version' do
Loading
Loading
Loading
Loading
@@ -56,6 +56,28 @@ describe ApplicationHelper do
end
end
 
describe 'project_icon' do
avatar_file_path = File.join(Rails.root, 'public', 'gitlab_logo.png')
it 'should return an url for the avatar' do
project = create(:project)
project.avatar = File.open(avatar_file_path)
project.save!
project_icon(project.to_param).to_s.should ==
"/uploads/project/avatar/#{ project.id }/gitlab_logo.png"
end
it "should give uploaded icon when present" do
project = create(:project)
project.save!
Project.any_instance.stub(:avatar_in_git).and_return(true)
project_icon(project.to_param).to_s.should match(
image_tag(project_avatar_path(project)))
end
end
describe "avatar_icon" do
avatar_file_path = File.join(Rails.root, 'public', 'gitlab_logo.png')
 
Loading
Loading
Loading
Loading
@@ -26,6 +26,7 @@
# star_count :integer default(0), not null
# import_type :string(255)
# import_source :string(255)
# avatar :string(255)
#
 
require 'spec_helper'
Loading
Loading
@@ -310,4 +311,18 @@ describe Project do
expect(project.star_count).to eq(0)
end
end
describe :avatar_type do
let(:project) { create(:project) }
it 'should be true if avatar is image' do
project.update_attribute(:avatar, 'uploads/avatar.png')
project.avatar_type.should be_true
end
it 'should be false if avatar is html page' do
project.update_attribute(:avatar, 'uploads/avatar.html')
project.avatar_type.should == ['only images allowed']
end
end
end
Loading
Loading
@@ -489,4 +489,11 @@ describe Projects::ForksController, "routing" do
it "to #create" do
post("/gitlab/gitlabhq/fork").should route_to("projects/forks#create", project_id: 'gitlab/gitlabhq')
end
# project_avatar DELETE /project/avatar(.:format) projects/avatars#destroy
describe Projects::AvatarsController, 'routing' do
it 'to #destroy' do
delete('/gitlab/gitlabhq/avatar').should route_to(
'projects/avatars#destroy', project_id: 'gitlab/gitlabhq')
end
end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment