summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Gemfile3
-rw-r--r--Gemfile.lock3
-rw-r--r--app/assets/javascripts/application.js.coffee1
-rw-r--r--app/assets/javascripts/behaviors/toggler_behavior.coffee2
-rw-r--r--app/assets/javascripts/markdown_area.js.coffee85
-rw-r--r--app/assets/stylesheets/application.scss1
-rw-r--r--app/assets/stylesheets/behaviors.scss13
-rw-r--r--app/assets/stylesheets/generic/markdown_area.scss58
-rw-r--r--app/assets/stylesheets/sections/notes.scss32
-rw-r--r--app/controllers/files_controller.rb1
-rw-r--r--app/controllers/projects/issues_controller.rb4
-rw-r--r--app/controllers/projects_controller.rb20
-rw-r--r--app/models/issue.rb4
-rw-r--r--app/uploaders/file_uploader.rb41
-rw-r--r--app/views/layouts/admin.html.haml1
-rw-r--r--app/views/layouts/projects.html.haml1
-rw-r--r--app/views/projects/issues/_form.html.haml14
-rw-r--r--app/views/projects/issues/show.html.haml2
-rw-r--r--app/views/projects/merge_requests/_form.html.haml10
-rw-r--r--app/views/projects/merge_requests/_new_submit.html.haml10
-rw-r--r--app/views/projects/milestones/_form.html.haml10
-rw-r--r--app/views/projects/notes/_form.html.haml25
-rw-r--r--app/views/projects/wikis/_form.html.haml13
-rw-r--r--config/routes.rb3
-rw-r--r--spec/controllers/commits_controller_spec.rb3
-rw-r--r--spec/controllers/projects_controller_spec.rb44
-rw-r--r--spec/factories.rb2
-rw-r--r--spec/fixtures/banana_sample.gifbin0 -> 71759 bytes
-rw-r--r--spec/fixtures/doc_sample.txt3
-rw-r--r--spec/fixtures/rails_sample.jpgbin0 -> 35255 bytes
30 files changed, 363 insertions, 46 deletions
diff --git a/Gemfile b/Gemfile
index f7e3fe7b6dd..9775334a7c1 100644
--- a/Gemfile
+++ b/Gemfile
@@ -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
diff --git a/Gemfile.lock b/Gemfile.lock
index 86c752505bd..3d4a673af1c 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -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)
@@ -579,6 +581,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
diff --git a/app/assets/javascripts/application.js.coffee b/app/assets/javascripts/application.js.coffee
index 587e51a7a83..35e43554661 100644
--- a/app/assets/javascripts/application.js.coffee
+++ b/app/assets/javascripts/application.js.coffee
@@ -29,6 +29,7 @@
#= require underscore
#= require nprogress
#= require nprogress-turbolinks
+#= require dropzone
#= require_tree .
window.slugify = (text) ->
diff --git a/app/assets/javascripts/behaviors/toggler_behavior.coffee b/app/assets/javascripts/behaviors/toggler_behavior.coffee
index d06cb116dfe..8ac5bfe95d8 100644
--- a/app/assets/javascripts/behaviors/toggler_behavior.coffee
+++ b/app/assets/javascripts/behaviors/toggler_behavior.coffee
@@ -1,6 +1,6 @@
$ ->
$("body").on "click", ".js-toggler-target", ->
- container = $(@).closest(".js-toggler-container")
+ container = $(".notes-container")
container.toggleClass("on")
# Toggle button. Show/hide content inside parent container.
diff --git a/app/assets/javascripts/markdown_area.js.coffee b/app/assets/javascripts/markdown_area.js.coffee
new file mode 100644
index 00000000000..def5d12a820
--- /dev/null
+++ b/app/assets/javascripts/markdown_area.js.coffee
@@ -0,0 +1,85 @@
+formatLink = (str) ->
+ "![" + str.alt + "](" + str.url + ")"
+
+$(document).ready ->
+ alertClass = "alert alert-danger alert-dismissable div-dropzone-alert"
+ alertAttr = "class=\"close\" data-dismiss=\"alert\"" + "aria-hidden=\"true\""
+ divHover = "<div class=\"div-dropzone-hover\"></div>"
+ divSpinner = "<div class=\"div-dropzone-spinner\"></div>"
+ divAlert = "<div class=\"" + alertClass + "\"></div>"
+ iconPicture = "<i class=\"icon-picture div-dropzone-icon\"></i>"
+ iconSpinner = "<i class=\"icon-spinner icon-spin div-dropzone-icon\"></i>"
+ btnAlert = "<button type=\"button\"" + alertAttr + ">&times;</button>"
+ project_image_path_upload = window.project_image_path_upload or null
+
+ $("textarea.markdown-area").wrap "<div class=\"div-dropzone\"></div>"
+
+ $(".div-dropzone").parent().addClass "div-dropzone-wrapper"
+
+ $(".div-dropzone").append divHover
+ $(".div-dropzone-hover").append iconPicture
+ $(".div-dropzone").append divSpinner
+ $(".div-dropzone-spinner").append iconSpinner
+
+
+ dropzone = $(".div-dropzone").dropzone(
+ url: project_image_path_upload
+ dictDefaultMessage: ""
+ clickable: true
+ paramName: "markdown_img"
+ maxFilesize: 10
+ uploadMultiple: false
+ acceptedFiles: "image/jpg,image/jpeg,image/gif,image/png"
+ headers:
+ "X-CSRF-Token": $("meta[name=\"csrf-token\"]").attr("content")
+
+ previewContainer: false
+
+ processing: ->
+ $(".div-dropzone-alert").alert "close"
+
+ dragover: ->
+ $(".div-dropzone > textarea").addClass "div-dropzone-focus"
+ $(".div-dropzone-hover").css "opacity", 0.7
+ return
+
+ dragleave: ->
+ $(".div-dropzone > textarea").removeClass "div-dropzone-focus"
+ $(".div-dropzone-hover").css "opacity", 0
+ return
+
+ drop: ->
+ $(".div-dropzone > textarea").removeClass "div-dropzone-focus"
+ $(".div-dropzone-hover").css "opacity", 0
+ $(".div-dropzone > textarea").focus()
+ return
+
+ success: (header, response) ->
+ child = $(dropzone[0]).children("textarea")
+ $(child).val $(child).val() + formatLink(response.link) + "\n"
+ return
+
+ error: (temp, errorMessage) ->
+ checkIfMsgExists = $(".error-alert").children().length
+ if checkIfMsgExists is 0
+ $(".error-alert").append divAlert
+ $(".div-dropzone-alert").append btnAlert + errorMessage
+ return
+
+ sending: ->
+ $(".div-dropzone-spinner").css "opacity", 0.7
+ return
+
+ complete: ->
+ $(".dz-preview").remove()
+ $(".markdown-area").trigger "input"
+ $(".div-dropzone-spinner").css "opacity", 0
+ return
+ )
+
+ $(".markdown-selector").click (e) ->
+ e.preventDefault()
+ $(".div-dropzone").click()
+ return
+
+ return \ No newline at end of file
diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss
index c53873f95a2..0b372a87a11 100644
--- a/app/assets/stylesheets/application.scss
+++ b/app/assets/stylesheets/application.scss
@@ -10,6 +10,7 @@
*= require_self
*= require nprogress
*= require nprogress-bootstrap
+ *= require dropzone/basic
*/
@import "main/*";
diff --git a/app/assets/stylesheets/behaviors.scss b/app/assets/stylesheets/behaviors.scss
index 3fdc20485f2..64e3c8d9ace 100644
--- a/app/assets/stylesheets/behaviors.scss
+++ b/app/assets/stylesheets/behaviors.scss
@@ -5,10 +5,19 @@
.js-details-container.open .content { display: block; }
.js-details-container.open .content.hide { display: none; }
-
// Toggler
//--------
-.js-toggler-container .turn-on { display: inherit; }
+.write-preview-btn .turn-on { display: inherit; }
+.write-preview-btn .turn-off { display: none; }
+
.js-toggler-container .turn-off { display: none; }
.js-toggler-container.on .turn-on { display: none; }
.js-toggler-container.on .turn-off { display: inherit; }
+
+.js-toggler-container.on ~ .note-form-actions {
+ .write-preview-btn .turn-on { display: none; }
+}
+
+.js-toggler-container.on ~ .note-form-actions {
+ .write-preview-btn .turn-off { display: inherit; }
+}
diff --git a/app/assets/stylesheets/generic/markdown_area.scss b/app/assets/stylesheets/generic/markdown_area.scss
new file mode 100644
index 00000000000..a1fe18b02fa
--- /dev/null
+++ b/app/assets/stylesheets/generic/markdown_area.scss
@@ -0,0 +1,58 @@
+.div-dropzone-wrapper {
+ .div-dropzone {
+ position: relative;
+ padding: 0;
+ border: 0;
+ margin-bottom: 5px;
+
+ .div-dropzone-focus {
+ border-color: #66afe9 !important;
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6) !important;
+ outline: 0 !important;
+ }
+
+ .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-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-icon {
+ display: block;
+ text-align: center;
+ font-size: inherit;
+ }
+
+ .dz-preview {
+ display: none;
+ }
+ }
+
+ .hint {
+ float: left;
+ padding: 0;
+ margin: 0;
+ }
+}
+
+.div-dropzone-alert {
+ margin-top: 5px;
+ margin-bottom: 0;
+ transition: opacity 200ms ease-in-out;
+}
diff --git a/app/assets/stylesheets/sections/notes.scss b/app/assets/stylesheets/sections/notes.scss
index 7e56781f56a..755295be1f4 100644
--- a/app/assets/stylesheets/sections/notes.scss
+++ b/app/assets/stylesheets/sections/notes.scss
@@ -272,21 +272,16 @@ ul.notes {
margin-bottom: 0;
}
.note_text_and_preview {
- // makes the "absolute" position for links relative to this
- position: relative;
-
- // preview/edit buttons
- > a {
- position: absolute;
- right: 5px;
- bottom: -60px;
- }
.note_preview {
background: #f5f5f5;
border: 1px solid #ddd;
@include border-radius(4px);
min-height: 80px;
padding: 4px 6px;
+
+ > p {
+ overflow-x: auto;
+ }
}
.note_text {
border: 1px solid #DDD;
@@ -310,7 +305,6 @@ ul.notes {
float: none;
}
-
.common-note-form {
margin: 0;
background: #F9F9F9;
@@ -318,7 +312,6 @@ ul.notes {
border: 1px solid #DDD;
}
-
.note-form-actions {
background: #F9F9F9;
height: 45px;
@@ -333,6 +326,18 @@ ul.notes {
.js-notify-commit-author {
float: left;
}
+
+ .write-preview-btn {
+ // makes the "absolute" position for links relative to this
+ position: relative;
+
+ // preview/edit buttons
+ > a {
+ position: absolute;
+ right: 5px;
+ top: 8px;
+ }
+ }
}
.note-edit-form {
@@ -367,3 +372,8 @@ ul.notes {
.parallel-comment {
padding: 6px;
}
+
+.error-alert > .alert {
+ margin-top: 5px;
+ margin-bottom: 5px;
+}
diff --git a/app/controllers/files_controller.rb b/app/controllers/files_controller.rb
index bf30de565ed..7937454810d 100644
--- a/app/controllers/files_controller.rb
+++ b/app/controllers/files_controller.rb
@@ -14,4 +14,3 @@ class FilesController < ApplicationController
end
end
end
-
diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb
index 4e7a716bfe4..6eec2094f86 100644
--- a/app/controllers/projects/issues_controller.rb
+++ b/app/controllers/projects/issues_controller.rb
@@ -69,7 +69,9 @@ class Projects::IssuesController < Projects::ApplicationController
render :new
end
end
- format.js
+ format.js do |format|
+ @link = @issue.attachment.url.to_js
+ end
end
end
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index e356d09a270..c15205fb68f 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -162,8 +162,28 @@ class ProjectsController < ApplicationController
end
end
+ def upload_image
+ uploader = FileUploader.new('uploads', upload_path, accepted_images)
+ alt = params['markdown_img'].original_filename
+ uploader.store!(params['markdown_img'])
+ link = { 'alt' => File.basename(alt, '.*'),
+ 'url' => File.join(root_url, uploader.url) }
+ respond_to do |format|
+ format.json { render json: { link: link } }
+ end
+ end
+
private
+ def upload_path
+ base_dir = FileUploader.generate_dir
+ File.join(repository.path_with_namespace, base_dir)
+ end
+
+ def accepted_images
+ %w(png jpg jpeg gif)
+ end
+
def set_title
@title = 'New Project'
end
diff --git a/app/models/issue.rb b/app/models/issue.rb
index 16d51345e5a..f0c2e552273 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -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
diff --git a/app/uploaders/file_uploader.rb b/app/uploaders/file_uploader.rb
new file mode 100644
index 00000000000..cbc9271ac14
--- /dev/null
+++ b/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)
+ file.original_filename = self.class.generate_filename(file)
+ super
+ end
+
+ def self.generate_filename(file)
+ original_filename = File.basename(file.original_filename, '.*')
+ extension = File.extname(file.original_filename)
+ new_filename = Digest::MD5.hexdigest(original_filename) + extension
+ end
+
+ def self.generate_dir
+ SecureRandom.hex(5)
+ end
+end
diff --git a/app/views/layouts/admin.html.haml b/app/views/layouts/admin.html.haml
index 53e0dbaef9b..c7a827555a7 100644
--- a/app/views/layouts/admin.html.haml
+++ b/app/views/layouts/admin.html.haml
@@ -10,3 +10,4 @@
.container
.content= yield
+ = yield :embedded_scripts \ No newline at end of file
diff --git a/app/views/layouts/projects.html.haml b/app/views/layouts/projects.html.haml
index 3ae4961b137..11c815c52a7 100644
--- a/app/views/layouts/projects.html.haml
+++ b/app/views/layouts/projects.html.haml
@@ -14,3 +14,4 @@
.container
.content= yield
+ = yield :embedded_scripts \ No newline at end of file
diff --git a/app/views/projects/issues/_form.html.haml b/app/views/projects/issues/_form.html.haml
index 84703229fe6..49d1a87743f 100644
--- a/app/views/projects/issues/_form.html.haml
+++ b/app/views/projects/issues/_form.html.haml
@@ -5,6 +5,7 @@
- contribution_guide_url = project_blob_path(@project, tree_join(@repository.root_ref, @repository.contribution_guide.name))
.alert.alert-info.col-sm-10.col-sm-offset-2
="Please review the <strong>#{link_to "guidelines for contribution", contribution_guide_url}</strong> to this repository.".html_safe
+
= form_for [@project, @issue], html: { class: 'form-horizontal issue-form' } do |f|
-if @issue.errors.any?
.alert.alert-danger
@@ -19,8 +20,12 @@
.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'}.
+ = f.text_area :description, class: 'form-control js-gfm-input markdown-area', rows: 14
+ .col-sm-12.hint
+ .pull-left Issues are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}.
+ .pull-right Attach images (JPG, PNG, GIF) by dragging & dropping or #{link_to "selecting them", '#', class: 'markdown-selector' }.
+ .clearfix
+ .error-alert
%hr
.form-group
.issue-assignee
@@ -57,9 +62,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 ) {
@@ -94,3 +96,5 @@
$('#issue_assignee_id').val("#{current_user.id}").trigger("change");
e.preventDefault();
});
+
+ window.project_image_path_upload = "#{upload_image_project_path @project}";
diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml
index b6d3a8edf4d..2c816e788de 100644
--- a/app/views/projects/issues/show.html.haml
+++ b/app/views/projects/issues/show.html.haml
@@ -73,4 +73,4 @@
= label.name
&nbsp;
-.voting_notes#notes= render "projects/notes/notes_with_form"
+.voting_notes#notes= render "projects/notes/notes_with_form" \ No newline at end of file
diff --git a/app/views/projects/merge_requests/_form.html.haml b/app/views/projects/merge_requests/_form.html.haml
index 290a15e2664..3088f0cf864 100644
--- a/app/views/projects/merge_requests/_form.html.haml
+++ b/app/views/projects/merge_requests/_form.html.haml
@@ -22,8 +22,12 @@
.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 Description is parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}.
+ = f.text_area :description, class: "form-control js-gfm-input markdown-area", rows: 14
+ .col-sm-12.hint
+ .pull-left Description is parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}.
+ .pull-right Attach images (JPG, PNG, GIF) by dragging & dropping or #{link_to "selecting them", '#', class: 'markdown-selector' }.
+ .clearfix
+ .error-alert
%hr
.form-group
.issue-assignee
@@ -98,3 +102,5 @@
return false;
}
});
+
+ window.project_image_path_upload = "#{upload_image_project_path @project}";
diff --git a/app/views/projects/merge_requests/_new_submit.html.haml b/app/views/projects/merge_requests/_new_submit.html.haml
index b5479be708b..dc41ef8135e 100644
--- a/app/views/projects/merge_requests/_new_submit.html.haml
+++ b/app/views/projects/merge_requests/_new_submit.html.haml
@@ -23,8 +23,12 @@
.form-group
.light
= f.label :description, "Description"
- = f.text_area :description, class: "form-control js-gfm-input", rows: 10
- %p.hint Description is parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}.
+ = f.text_area :description, class: "form-control js-gfm-input markdown-area", rows: 10
+ .col-sm-12.hint
+ .pull-left Description is parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}.
+ .pull-right Attach images (JPG, PNG, GIF) by dragging & dropping or #{link_to "selecting them", '#', class: 'markdown-selector' }.
+ .clearfix
+ .error-alert
.form-group
.issue-assignee
= f.label :assignee_id do
@@ -80,3 +84,5 @@
$('#merge_request_assignee_id').val("#{current_user.id}").trigger("change");
e.preventDefault();
});
+
+ window.project_image_path_upload = "#{upload_image_project_path @project}";
diff --git a/app/views/projects/milestones/_form.html.haml b/app/views/projects/milestones/_form.html.haml
index d770bb5b371..7e0fd19d0ab 100644
--- a/app/views/projects/milestones/_form.html.haml
+++ b/app/views/projects/milestones/_form.html.haml
@@ -21,8 +21,12 @@
.form-group
= f.label :description, "Description", class: "control-label"
.col-sm-10
- = f.text_area :description, maxlength: 2000, class: "form-control", rows: 10
- %p.hint Milestones are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}.
+ = f.text_area :description, maxlength: 2000, class: "form-control markdown-area", rows: 10
+ .hint
+ .pull-left Milestones are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}.
+ .pull-left Attach images (JPG, PNG, GIF) by dragging & dropping or #{link_to "selecting them", '#', class: 'markdown-selector' }.
+ .clearfix
+ .error-alert
.col-md-6
.form-group
= f.label :due_date, "Due Date", class: "control-label"
@@ -45,3 +49,5 @@
dateFormat: "yy-mm-dd",
onSelect: function(dateText, inst) { $("#milestone_due_date").val(dateText) }
}).datepicker("setDate", $.datepicker.parseDate('yy-mm-dd', $('#milestone_due_date').val()));
+
+ window.project_image_path_upload = "#{upload_image_project_path @project}";
diff --git a/app/views/projects/notes/_form.html.haml b/app/views/projects/notes/_form.html.haml
index 3db551e993b..cadae9da805 100644
--- a/app/views/projects/notes/_form.html.haml
+++ b/app/views/projects/notes/_form.html.haml
@@ -5,20 +5,15 @@
= f.hidden_field :noteable_id
= f.hidden_field :noteable_type
- .note_text_and_preview.js-toggler-container
- %a.btn.js-note-preview-button.js-toggler-target.turn-off{ href: "javascript:;", data: {url: preview_project_notes_path(@project)} }
- %i.icon-eye-open
- Preview
- %a.btn.btn-primary.js-note-edit-button.js-toggler-target.turn-off{ href: "javascript:;" }
- %i.icon-edit
- Write
-
- = f.text_area :note, size: 255, class: 'note_text js-note-text js-gfm-input turn-on'
+ .note_text_and_preview.js-toggler-container.notes-container
+ = f.text_area :note, size: 255, class: 'note_text js-note-text js-gfm-input turn-on markdown-area'
.note_preview.js-note-preview.turn-off
.hint
- .pull-right Comments are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}.
+ .pull-left Comments are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}.
+ .pull-right Attach images (JPG, PNG, GIF) by dragging & dropping or #{link_to "selecting them", '#', class: 'markdown-selector' }.
.clearfix
+ .error-alert
.note-form-actions
.buttons
@@ -35,4 +30,14 @@
%span.file_name.js-attachment-filename File name...
= f.file_field :attachment, class: "js-note-attachment-input hidden"
+ .write-preview-btn
+ %a.btn.js-note-preview-button.js-toggler-target.turn-off{ href: "javascript:;", data: {url: preview_project_notes_path(@project)} }
+ %i.icon-eye-open
+ Preview
+ %a.btn.btn-primary.js-note-edit-button.js-toggler-target.turn-off{ href: "javascript:;" }
+ %i.icon-edit
+ Write
.clearfix
+
+:javascript
+ window.project_image_path_upload = "#{upload_image_project_path @project}";
diff --git a/app/views/projects/wikis/_form.html.haml b/app/views/projects/wikis/_form.html.haml
index 0c2e33f2282..a43e6f073e1 100644
--- a/app/views/projects/wikis/_form.html.haml
+++ b/app/views/projects/wikis/_form.html.haml
@@ -15,7 +15,6 @@
.col-sm-2
.col-sm-10
%p.cgray
- Wiki content is parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}.
To link to a (new) page you can just type
%code [Link Title](page-slug)
\.
@@ -23,8 +22,12 @@
.form-group
= f.label :content, class: 'control-label'
.col-sm-10
- = f.text_area :content, class: 'form-control js-gfm-input', rows: 18
-
+ = f.text_area :content, class: 'form-control js-gfm-input markdown-area', rows: 18
+ .col-sm-12.hint
+ .pull-left Wiki content is parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}.
+ .pull-right Attach images (JPG, PNG, GIF) by dragging & dropping or #{link_to "selecting them", '#', class: 'markdown-selector' }.
+ .clearfix
+ .error-alert
.form-group
= f.label :commit_message, class: 'control-label'
.col-sm-10= f.text_field :message, class: 'form-control', rows: 18
@@ -36,3 +39,7 @@
- else
= f.submit 'Create page', class: "btn-create btn"
= link_to "Cancel", project_wiki_path(@project, :home), class: "btn btn-cancel"
+
+:javascript
+ window.project_image_path_upload = "#{upload_image_project_path @project}";
+
diff --git a/config/routes.rb b/config/routes.rb
index 7641fe43088..da5a1ba7a87 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -136,8 +136,6 @@ Gitlab::Application.routes.draw do
match "/u/:username" => "users#show", as: :user, constraints: { username: /.*/ }, via: :get
-
-
#
# Dashboard Area
#
@@ -178,6 +176,7 @@ Gitlab::Application.routes.draw do
post :fork
post :archive
post :unarchive
+ post :upload_image
get :autocomplete_sources
get :import
put :retry_import
diff --git a/spec/controllers/commits_controller_spec.rb b/spec/controllers/commits_controller_spec.rb
index fbf4f29acfd..308cfa69219 100644
--- a/spec/controllers/commits_controller_spec.rb
+++ b/spec/controllers/commits_controller_spec.rb
@@ -6,8 +6,7 @@ describe Projects::CommitsController do
before do
sign_in(user)
-
- project.team << [user, :master]
+ project.creator = user
end
describe "GET show" do
diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb
new file mode 100644
index 00000000000..07ca8d25026
--- /dev/null
+++ b/spec/controllers/projects_controller_spec.rb
@@ -0,0 +1,44 @@
+require('spec_helper')
+
+describe ProjectsController do
+ let(:project) { create(:project) }
+ let(:user) { create(:user) }
+ let(:png) { fixture_file_upload(Rails.root + 'spec/fixtures/dk.png', 'image/png') }
+ let(:jpg) { fixture_file_upload(Rails.root + 'spec/fixtures/rails_sample.jpg', 'image/jpg') }
+ let(:gif) { fixture_file_upload(Rails.root + 'spec/fixtures/banana_sample.gif', 'image/gif') }
+ let(:txt) { fixture_file_upload(Rails.root + 'spec/fixtures/doc_sample.txt', 'text/plain') }
+
+ describe "POST #upload_image" do
+ before do
+ sign_in(user)
+ end
+
+ context "without params['markdown_img']" do
+ it "returns an error" do
+ post :upload_image, id: project.to_param
+ expect(response.status).to eq(404)
+ end
+ end
+
+ context "with invalid file" do
+ before do
+ post :upload_image, id: project.to_param, markdown_img: @img
+ end
+
+ it "returns an error" do
+ expect(response.status).to eq(404)
+ end
+ end
+
+ context "with valid file" do
+ before do
+ post :upload_image, id: project.to_param, markdown_img: @img
+ end
+
+ it "returns a content with original filename and new link." do
+ link = { alt: 'rails_sample', link: '' }.to_json
+ expect(response.body).to have_content link
+ end
+ end
+ end
+end \ No newline at end of file
diff --git a/spec/factories.rb b/spec/factories.rb
index 148477d6389..41cc99cbcb9 100644
--- a/spec/factories.rb
+++ b/spec/factories.rb
@@ -201,7 +201,7 @@ FactoryGirl.define do
end
trait :with_attachment do
- attachment { fixture_file_upload(Rails.root + "spec/fixtures/dk.png", "image/png") }
+ attachment { fixture_file_upload(Rails.root + "spec/fixtures/dk.png", "`/png") }
end
end
diff --git a/spec/fixtures/banana_sample.gif b/spec/fixtures/banana_sample.gif
new file mode 100644
index 00000000000..1322ac92d14
--- /dev/null
+++ b/spec/fixtures/banana_sample.gif
Binary files differ
diff --git a/spec/fixtures/doc_sample.txt b/spec/fixtures/doc_sample.txt
new file mode 100644
index 00000000000..45dbc1aadde
--- /dev/null
+++ b/spec/fixtures/doc_sample.txt
@@ -0,0 +1,3 @@
+Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
+
+Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur? \ No newline at end of file
diff --git a/spec/fixtures/rails_sample.jpg b/spec/fixtures/rails_sample.jpg
new file mode 100644
index 00000000000..a847b193325
--- /dev/null
+++ b/spec/fixtures/rails_sample.jpg
Binary files differ