Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Image upload in creating issue #6962

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions Gemfile
Expand Up @@ -69,6 +69,9 @@ gem "haml-rails"
# Files attachments
gem "carrierwave"

# Drag and Drop UI
gem 'dropzonejs-rails'

# for aws storage
gem "fog", "~> 1.14", group: :aws
gem "unf", group: :aws
Expand Down
3 changes: 3 additions & 0 deletions Gemfile.lock
Expand Up @@ -103,6 +103,8 @@ GEM
diffy (3.0.3)
docile (1.1.1)
dotenv (0.9.0)
dropzonejs-rails (0.4.14)
rails (> 3.1)
email_spec (1.5.0)
launchy (~> 2.1)
mail (~> 2.2)
Expand Down Expand Up @@ -577,6 +579,7 @@ DEPENDENCIES
devise (= 3.0.4)
devise-async (= 0.8.0)
diffy (~> 3.0.3)
dropzonejs-rails
email_spec
email_validator (~> 1.4.0)
enumerize
Expand Down
1 change: 1 addition & 0 deletions app/assets/javascripts/application.js.coffee
Expand Up @@ -29,6 +29,7 @@
#= require underscore
#= require nprogress
#= require nprogress-turbolinks
#= require dropzone
#= require_tree .

window.slugify = (text) ->
Expand Down
1 change: 1 addition & 0 deletions app/assets/stylesheets/application.scss
Expand Up @@ -10,6 +10,7 @@
*= require_self
*= require nprogress
*= require nprogress-bootstrap
*= require dropzone/basic
*/

@import "main/*";
Expand Down
55 changes: 55 additions & 0 deletions app/assets/stylesheets/sections/issues.scss
Expand Up @@ -168,3 +168,58 @@ form.edit-issue {
}
}
}

#div-dropzone {
position: relative;

#div-dropzone-hover {
position: absolute;
top: 50%;
left: 50%;
margin-top: -0.5em;
margin-left: -0.6em;
opacity: 0;
font-size: 50px;
transition: opacity 200ms ease-in-out;
}

#div-dropzone-error {
position: absolute;
top: 50%;
width: 100%;
background-color: #e74c3c;
margin-top: -1em;
opacity: 0;
font-size: 20px;
text-align: center;
transition: opacity 200ms ease-in-out;
}

#div-dropzone-spinner {
position: absolute;
top: 100%;
left: 100%;
margin-top: -1.1em;
margin-left: -1.1em;
opacity: 0;
font-size: 30px;
transition: opacity 200ms ease-in-out;
}
}

#div-dropzone {
padding: 0;
border: 0;
}

.div-dropzone-icon {
display: block;
text-align: center;
font-size: inherit;
}

.div-dropzone-icon-error {
display: inline;
text-align: center;
font-size: inherit;
}
3 changes: 1 addition & 2 deletions app/controllers/files_controller.rb
Expand Up @@ -13,5 +13,4 @@ def download
redirect_to uploader.url
end
end
end

end

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Final newline missing.

28 changes: 24 additions & 4 deletions app/controllers/projects/issues_controller.rb
Expand Up @@ -60,7 +60,6 @@ def show

def create
@issue = Issues::CreateService.new(project, current_user, params[:issue]).execute

respond_to do |format|
format.html do
if @issue.valid?
Expand All @@ -69,15 +68,19 @@ def create
render :new
end
end
format.js
format.js do |format|
# issue = Issues.create()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this comment try to explain?


@link = @issue.attachment.url.to_js
end
end
end

def update
@issue = Issues::UpdateService.new(project, current_user, params[:issue]).execute(issue)

respond_to do |format|
format.js
format.js

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trailing whitespace detected.

format.html do
if @issue.valid?
redirect_to [@project, @issue]
Expand All @@ -93,6 +96,24 @@ def bulk_update
redirect_to :back, notice: "#{result[:count]} issues updated"
end

def upload_image
@main_dir = FileUploader.generate_dir
upload_path = File.join(project.namespace.path, @project.path, 'issues', @main_dir)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line is too long. [87/80]

accepted_types = %w(png jpg jpeg gif)
uploader = FileUploader.new('uploads', upload_path, accepted_types)
links = []
params['issue-imgs'].each do |img|
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't it be simpler to limit the upload API to a single image (rather than several images at once), and let the javascript/browser send one request per image to upload?

IMHO it would make the error handling easier on the browser side: each upload would receive its own success or error. If several files can be uploaded at once the error handling must deal with partial errors.

alt = uploader.store!(img)
links << { 'alt' => File.basename(alt, '.*'),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trailing whitespace detected.

'url' => File.join(root_url, uploader.url) }
end


Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extra blank line detected.

respond_to do |format|
format.json { render json: { links: links } }
end
end

protected

def issue
Expand Down Expand Up @@ -128,7 +149,6 @@ def issues_filtered
#
def redirect_old
issue = @project.issues.find_by(id: params[:id])

if issue
redirect_to project_issue_path(@project, issue)
return
Expand Down
7 changes: 6 additions & 1 deletion app/models/issue.rb
Expand Up @@ -15,8 +15,12 @@
# milestone_id :integer
# state :string(255)
# iid :integer
# attachment :string(255)
#

require 'carrierwave/orm/activerecord'
require 'file_size_validator'

class Issue < ActiveRecord::Base
include Issuable
include InternalId
Expand All @@ -30,7 +34,8 @@ class Issue < ActiveRecord::Base
scope :of_user_team, ->(team) { where(project_id: team.project_ids, assignee_id: team.member_ids) }

attr_accessible :title, :assignee_id, :position, :description,
:milestone_id, :label_list, :state_event
:milestone_id, :label_list, :author_id_of_changes,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you add the author_id_of_changes here?

:state_event

acts_as_taggable_on :labels

Expand Down
2 changes: 0 additions & 2 deletions app/services/issues/create_service.rb
Expand Up @@ -3,14 +3,12 @@ class CreateService < Issues::BaseService
def execute
issue = project.issues.new(params)
issue.author = current_user

if issue.save
notification_service.new_issue(issue, current_user)
event_service.open_issue(issue, current_user)
issue.create_cross_references!(issue.project, current_user)
execute_hooks(issue)
end

issue
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please avoid changes like this in files where you're not adding/changing code.

end
Expand Down
2 changes: 1 addition & 1 deletion app/uploaders/attachment_uploader.rb
Expand Up @@ -33,4 +33,4 @@ def file_storage?
def reset_events_cache(file)
model.reset_events_cache if model.is_a?(User)
end
end
end

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Final newline missing.

41 changes: 41 additions & 0 deletions app/uploaders/file_uploader.rb
@@ -0,0 +1,41 @@
# encoding: utf-8
class FileUploader < CarrierWave::Uploader::Base
storage :file

def initialize(base_dir, path, allowed_extensions = nil)
@base_dir = base_dir
@path = path
@allowed_extensions = allowed_extensions
end

def base_dir
@base_dir
end

def store_dir
File.join(base_dir, @path)
end

def cache_dir
File.join(base_dir, 'tmp', @path)
end

def extension_white_list
@allowed_extensions
end

def store!(file)
original_filename = file.original_filename
file.original_filename = self.class.generate_filename(file) + File.extname(original_filename)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line is too long. [97/80]

super
original_filename
end

def self.generate_filename(file)
Digest::MD5.hexdigest(File.basename(file.original_filename, '.*'))
end

def self.generate_dir
SecureRandom.hex(5)
end
end
90 changes: 83 additions & 7 deletions app/views/projects/issues/_form.html.haml
Expand Up @@ -19,8 +19,19 @@
.form-group
= f.label :description, 'Description', class: 'control-label'
.col-sm-10
= f.text_area :description, class: "form-control js-gfm-input", rows: 14
%p.hint Issues are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}.
#div-dropzone
= f.text_area :description, class: 'form-control js-gfm-input', rows: 14
#div-dropzone-hover
%i.icon-picture.div-dropzone-icon
#div-dropzone-error
%i.icon-remove.div-dropzone-icon-error
%div#dropzone-error-message{style:'display:inline'}
Can't Attach File
#div-dropzone-spinner
%i.icon-spinner.icon-spin.div-dropzone-icon
%p.hint{style: "display: inline"} Issues are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}.
%p.hint.pull-right{style: "display: inline"} Attach images (JPG, PNG, GIF) by dragging & dropping or #{link_to "selecting them", '#', class: 'markdown-selector' }.

%hr
.form-group
.issue-assignee
Expand All @@ -46,8 +57,6 @@
= f.text_field :label_list, maxlength: 2000, class: "form-control"
%p.hint Separate labels with commas.



.form-actions
- if @issue.new_record?
= f.submit 'Submit new issue', class: "btn btn-create"
Expand All @@ -57,9 +66,6 @@
- cancel_path = @issue.new_record? ? project_issues_path(@project) : project_issue_path(@project, @issue)
= link_to "Cancel", cancel_path, class: 'btn btn-cancel'




:javascript
$("#issue_label_list")
.bind( "keydown", function( event ) {
Expand Down Expand Up @@ -94,3 +100,73 @@
$('#issue_assignee_id').val("#{current_user.id}").trigger("change");
e.preventDefault();
});

function handlePaste(e) {
clipboardData = e.originalEvent.clipboardData;
for (var i = 0 ; i < clipboardData.items.length ; i++) {
var item = clipboardData.items[i];
console.log(item);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dont forget to remove the console.log's :-)

if (item.type.indexOf("image") != -1) {
uploadFile(item.getAsFile());
}
else {
console.log("Discarding non-image paste data");
}
}
}

function formatLinks(links) {
var md_links = [];
links.forEach(function (str) {
md_links.push('![' + str.alt + '](' + str.url + ')');
})
return md_links;
}

$('#div-dropzone').dropzone({
url: "#{upload_image_project_issues_path}",
dictDefaultMessage: "",
paramName: "issue-imgs",
maxFilesize: 10,
uploadMultiple: true,
acceptedFiles: "image/jpg,image/jpeg,image/gif,image/png",
headers: { "X-CSRF-Token": $('meta[name="csrf-token"]').attr('content')},

success: function(header,response){
$("#issue_description").val($("#issue_description").val() + formatLinks(response.links).join("\n") + "\n");
},

error: function(temp, errorMessage) {
$('#dropzone-error-message').text(errorMessage);
$('#div-dropzone-error').css('opacity', 0.7);
$('#div-dropzone-error').delay(500).fadeTo("slow", 0);
},

sending: function() {
$('#div-dropzone-spinner').css('opacity', 0.7);
},

complete: function() {
$('#div-dropzone-spinner').css('opacity',0);
}
});

$('#div-dropzone').on('dragenter',function(){
$(this).children('textarea').focus();
$('#div-dropzone-hover').css('opacity',0.7);
});

$('body').on('dragover',function(){
$('#div-dropzone').children('textarea').blur();
$('#div-dropzone-hover').css('opacity',0);
});

$('#div-dropzone').on('drop',function(){
$('.dz-preview').remove();
$('#div-dropzone-hover').css('opacity',0);
});

$('.markdown-selector').click(function() {
$('#div-dropzone').click();
});

2 changes: 1 addition & 1 deletion app/views/projects/issues/new.html.haml
@@ -1 +1 @@
= render "form"
= render "form"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No newline?

3 changes: 2 additions & 1 deletion app/views/projects/issues/show.html.haml
Expand Up @@ -49,6 +49,7 @@
.wiki
= preserve do
= markdown @issue.description

.context
%cite.cgray
= render partial: 'issue_context', locals: { issue: @issue }
Expand All @@ -73,4 +74,4 @@
= label.name
&nbsp;

.voting_notes#notes= render "projects/notes/notes_with_form"
.voting_notes#notes= render "projects/notes/notes_with_form"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No newline?