diff options
author | Phil Hughes <me@iamphill.com> | 2017-06-07 09:26:48 +0000 |
---|---|---|
committer | Phil Hughes <me@iamphill.com> | 2017-06-07 09:26:48 +0000 |
commit | 563ea34692a18d82d9d1bc481002f19b8a407508 (patch) | |
tree | 6aa991974f140b42534e06abe18e4e5287afc49a /app | |
parent | 7adddf49965a1808e7a3a0d1a70b08172c74a762 (diff) | |
parent | 2e311d9d1aac58bbd9c7d6c97c7cbcccf2715347 (diff) | |
download | gitlab-ce-563ea34692a18d82d9d1bc481002f19b8a407508.tar.gz |
Merge branch '12910-snippets-description' into 'master'
Support descriptions for snippets
Closes #31894
See merge request !11071
Diffstat (limited to 'app')
-rw-r--r-- | app/assets/javascripts/dispatcher.js | 10 | ||||
-rw-r--r-- | app/assets/javascripts/dropzone_input.js | 7 | ||||
-rw-r--r-- | app/controllers/projects/snippets_controller.rb | 2 | ||||
-rw-r--r-- | app/controllers/snippets_controller.rb | 10 | ||||
-rw-r--r-- | app/controllers/uploads_controller.rb | 13 | ||||
-rw-r--r-- | app/helpers/gitlab_routing_helper.rb | 2 | ||||
-rw-r--r-- | app/models/snippet.rb | 1 | ||||
-rw-r--r-- | app/uploaders/file_mover.rb | 63 | ||||
-rw-r--r-- | app/uploaders/personal_file_uploader.rb | 6 | ||||
-rw-r--r-- | app/uploaders/records_uploads.rb | 7 | ||||
-rw-r--r-- | app/views/layouts/snippets.html.haml | 5 | ||||
-rw-r--r-- | app/views/shared/form_elements/_description.html.haml (renamed from app/views/shared/issuable/form/_description.html.haml) | 7 | ||||
-rw-r--r-- | app/views/shared/issuable/_form.html.haml | 2 | ||||
-rw-r--r-- | app/views/shared/snippets/_form.html.haml | 7 | ||||
-rw-r--r-- | app/views/shared/snippets/_header.html.haml | 6 |
15 files changed, 131 insertions, 17 deletions
diff --git a/app/assets/javascripts/dispatcher.js b/app/assets/javascripts/dispatcher.js index c3e096561e4..0c420c12345 100644 --- a/app/assets/javascripts/dispatcher.js +++ b/app/assets/javascripts/dispatcher.js @@ -218,6 +218,16 @@ import initSettingsPanels from './settings_panels'; new gl.GLForm($('.tag-form')); new RefSelectDropdown($('.js-branch-select'), window.gl.availableRefs); break; + case 'projects:snippets:new': + case 'projects:snippets:edit': + case 'projects:snippets:create': + case 'projects:snippets:update': + case 'snippets:new': + case 'snippets:edit': + case 'snippets:create': + case 'snippets:update': + new gl.GLForm($('.snippet-form')); + break; case 'projects:releases:edit': new ZenMode(); new gl.GLForm($('.release-form')); diff --git a/app/assets/javascripts/dropzone_input.js b/app/assets/javascripts/dropzone_input.js index 111449bb8f7..98ddcc20036 100644 --- a/app/assets/javascripts/dropzone_input.js +++ b/app/assets/javascripts/dropzone_input.js @@ -5,7 +5,7 @@ import './preview_markdown'; window.DropzoneInput = (function() { function DropzoneInput(form) { - var updateAttachingMessage, $attachingFileMessage, $mdArea, $attachButton, $cancelButton, $retryLink, $uploadingErrorContainer, $uploadingErrorMessage, $uploadProgress, $uploadingProgressContainer, appendToTextArea, btnAlert, child, closeAlertMessage, closeSpinner, divHover, divSpinner, dropzone, $formDropzone, formTextarea, getFilename, handlePaste, iconPaperclip, iconSpinner, insertToTextArea, isImage, maxFileSize, pasteText, uploadsPath, showError, showSpinner, uploadFile; + var updateAttachingMessage, $attachingFileMessage, $mdArea, $attachButton, $cancelButton, $retryLink, $uploadingErrorContainer, $uploadingErrorMessage, $uploadProgress, $uploadingProgressContainer, appendToTextArea, btnAlert, child, closeAlertMessage, closeSpinner, divHover, divSpinner, dropzone, $formDropzone, formTextarea, getFilename, handlePaste, iconPaperclip, iconSpinner, insertToTextArea, isImage, maxFileSize, pasteText, uploadsPath, showError, showSpinner, uploadFile, addFileToForm; Dropzone.autoDiscover = false; divHover = '<div class="div-dropzone-hover"></div>'; iconPaperclip = '<i class="fa fa-paperclip div-dropzone-icon"></i>'; @@ -71,6 +71,7 @@ window.DropzoneInput = (function() { pasteText(response.link.markdown, shouldPad); // Show 'Attach a file' link only when all files have been uploaded. if (!processingFileCount) $attachButton.removeClass('hide'); + addFileToForm(response.link.url); }, error: function(file, errorMessage = 'Attaching the file failed.', xhr) { // If 'error' event is fired by dropzone, the second parameter is error message. @@ -198,6 +199,10 @@ window.DropzoneInput = (function() { return formTextarea.trigger('input'); }; + addFileToForm = function(path) { + $(form).append('<input type="hidden" name="files[]" value="' + _.escape(path) + '">'); + }; + getFilename = function(e) { var value; if (window.clipboardData && window.clipboardData.getData) { diff --git a/app/controllers/projects/snippets_controller.rb b/app/controllers/projects/snippets_controller.rb index 84deefb7875..8a8f8d6a27d 100644 --- a/app/controllers/projects/snippets_controller.rb +++ b/app/controllers/projects/snippets_controller.rb @@ -107,6 +107,6 @@ class Projects::SnippetsController < Projects::ApplicationController end def snippet_params - params.require(:project_snippet).permit(:title, :content, :file_name, :private, :visibility_level) + params.require(:project_snippet).permit(:title, :content, :file_name, :private, :visibility_level, :description) end end diff --git a/app/controllers/snippets_controller.rb b/app/controllers/snippets_controller.rb index 8511457b53d..3d86dd2ea2c 100644 --- a/app/controllers/snippets_controller.rb +++ b/app/controllers/snippets_controller.rb @@ -45,6 +45,8 @@ class SnippetsController < ApplicationController @snippet = CreateSnippetService.new(nil, current_user, create_params).execute + move_temporary_files if @snippet.valid? && params[:files] + recaptcha_check_with_fallback { render :new } end @@ -124,6 +126,12 @@ class SnippetsController < ApplicationController end def snippet_params - params.require(:personal_snippet).permit(:title, :content, :file_name, :private, :visibility_level) + params.require(:personal_snippet).permit(:title, :content, :file_name, :private, :visibility_level, :description) + end + + def move_temporary_files + params[:files].each do |file| + FileMover.new(file, @snippet).execute + end end end diff --git a/app/controllers/uploads_controller.rb b/app/controllers/uploads_controller.rb index eef53730291..dc882b17143 100644 --- a/app/controllers/uploads_controller.rb +++ b/app/controllers/uploads_controller.rb @@ -9,12 +9,16 @@ class UploadsController < ApplicationController private def find_model + return nil unless params[:id] + return render_404 unless upload_model && upload_mount @model = upload_model.find(params[:id]) end def authorize_access! + return nil unless model + authorized = case model when Note @@ -33,6 +37,8 @@ class UploadsController < ApplicationController end def authorize_create_access! + return nil unless model + # for now we support only personal snippets comments authorized = can?(current_user, :comment_personal_snippet, model) @@ -73,7 +79,12 @@ class UploadsController < ApplicationController def uploader return @uploader if defined?(@uploader) - if model.is_a?(PersonalSnippet) + case model + when nil + @uploader = PersonalFileUploader.new(nil, params[:secret]) + + @uploader.retrieve_from_store!(params[:filename]) + when PersonalSnippet @uploader = PersonalFileUploader.new(model, params[:secret]) @uploader.retrieve_from_store!(params[:filename]) diff --git a/app/helpers/gitlab_routing_helper.rb b/app/helpers/gitlab_routing_helper.rb index 40864bed0ff..8c7af62e199 100644 --- a/app/helpers/gitlab_routing_helper.rb +++ b/app/helpers/gitlab_routing_helper.rb @@ -128,7 +128,7 @@ module GitlabRoutingHelper def preview_markdown_path(project, *args) if @snippet.is_a?(PersonalSnippet) - preview_markdown_snippet_path(@snippet) + preview_markdown_snippets_path else preview_markdown_namespace_project_path(project.namespace, project, *args) end diff --git a/app/models/snippet.rb b/app/models/snippet.rb index 6c3358685fe..54014df43b0 100644 --- a/app/models/snippet.rb +++ b/app/models/snippet.rb @@ -11,6 +11,7 @@ class Snippet < ActiveRecord::Base include Editable cache_markdown_field :title, pipeline: :single_line + cache_markdown_field :description cache_markdown_field :content # Aliases to make application_helper#edited_time_ago_with_tooltip helper work properly with snippets. diff --git a/app/uploaders/file_mover.rb b/app/uploaders/file_mover.rb new file mode 100644 index 00000000000..00c2888d224 --- /dev/null +++ b/app/uploaders/file_mover.rb @@ -0,0 +1,63 @@ +class FileMover + attr_reader :secret, :file_name, :model, :update_field + + def initialize(file_path, model, update_field = :description) + @secret = File.split(File.dirname(file_path)).last + @file_name = File.basename(file_path) + @model = model + @update_field = update_field + end + + def execute + move + uploader.record_upload if update_markdown + end + + private + + def move + FileUtils.mkdir_p(File.dirname(file_path)) + FileUtils.move(temp_file_path, file_path) + end + + def update_markdown + updated_text = model.read_attribute(update_field).gsub(temp_file_uploader.to_markdown, uploader.to_markdown) + model.update_attribute(update_field, updated_text) + + true + rescue + revert + + false + end + + def temp_file_path + return @temp_file_path if @temp_file_path + + temp_file_uploader.retrieve_from_store!(file_name) + + @temp_file_path = temp_file_uploader.file.path + end + + def file_path + return @file_path if @file_path + + uploader.retrieve_from_store!(file_name) + + @file_path = uploader.file.path + end + + def uploader + @uploader ||= PersonalFileUploader.new(model, secret) + end + + def temp_file_uploader + @temp_file_uploader ||= PersonalFileUploader.new(nil, secret) + end + + def revert + Rails.logger.warn("Markdown not updated, file move reverted for #{model}") + + FileUtils.move(file_path, temp_file_path) + end +end diff --git a/app/uploaders/personal_file_uploader.rb b/app/uploaders/personal_file_uploader.rb index 969b0a20d38..7f857765fbf 100644 --- a/app/uploaders/personal_file_uploader.rb +++ b/app/uploaders/personal_file_uploader.rb @@ -10,6 +10,10 @@ class PersonalFileUploader < FileUploader end def self.model_path(model) - File.join("/#{base_dir}", model.class.to_s.underscore, model.id.to_s) + if model + File.join("/#{base_dir}", model.class.to_s.underscore, model.id.to_s) + else + File.join("/#{base_dir}", 'temp') + end end end diff --git a/app/uploaders/records_uploads.rb b/app/uploaders/records_uploads.rb index 4c127f29250..feb4f04d7b7 100644 --- a/app/uploaders/records_uploads.rb +++ b/app/uploaders/records_uploads.rb @@ -6,8 +6,6 @@ module RecordsUploads before :remove, :destroy_upload end - private - # After storing an attachment, create a corresponding Upload record # # NOTE: We're ignoring the argument passed to this callback because we want @@ -15,13 +13,16 @@ module RecordsUploads # `Tempfile` object the callback gets. # # Called `after :store` - def record_upload(_tempfile) + def record_upload(_tempfile = nil) + return unless model return unless file_storage? return unless file.exists? Upload.record(self) end + private + # Before removing an attachment, destroy any Upload records at the same path # # Called `before :remove` diff --git a/app/views/layouts/snippets.html.haml b/app/views/layouts/snippets.html.haml index 98b75cea03f..57971205e0e 100644 --- a/app/views/layouts/snippets.html.haml +++ b/app/views/layouts/snippets.html.haml @@ -1,9 +1,8 @@ - header_title "Snippets", snippets_path - content_for :page_specific_javascripts do - - if @snippet&.persisted? && current_user + - if @snippet && current_user :javascript - window.uploads_path = "#{upload_path('personal_snippet', @snippet)}"; - window.preview_markdown_path = "#{preview_markdown_snippet_path(@snippet)}"; + window.uploads_path = "#{upload_path('personal_snippet', id: @snippet.id)}"; = render template: "layouts/application" diff --git a/app/views/shared/issuable/form/_description.html.haml b/app/views/shared/form_elements/_description.html.haml index 7ef0ae96be2..307d4919224 100644 --- a/app/views/shared/issuable/form/_description.html.haml +++ b/app/views/shared/form_elements/_description.html.haml @@ -1,10 +1,11 @@ - project = local_assigns.fetch(:project) -- issuable = local_assigns.fetch(:issuable) +- model = local_assigns.fetch(:model) + - form = local_assigns.fetch(:form) -- supports_slash_commands = issuable.new_record? +- supports_slash_commands = model.new_record? - if supports_slash_commands - - preview_url = preview_markdown_path(project, slash_commands_target_type: issuable.class.name) + - preview_url = preview_markdown_path(project, slash_commands_target_type: model.class.name) - else - preview_url = preview_markdown_path(project) diff --git a/app/views/shared/issuable/_form.html.haml b/app/views/shared/issuable/_form.html.haml index 7748351b333..c016aa2abcd 100644 --- a/app/views/shared/issuable/_form.html.haml +++ b/app/views/shared/issuable/_form.html.haml @@ -17,7 +17,7 @@ = render 'shared/issuable/form/template_selector', issuable: issuable = render 'shared/issuable/form/title', issuable: issuable, form: form, has_wip_commits: commits && commits.detect(&:work_in_progress?) -= render 'shared/issuable/form/description', issuable: issuable, form: form, project: project += render 'shared/form_elements/description', model: issuable, form: form, project: project - if issuable.respond_to?(:confidential) .form-group diff --git a/app/views/shared/snippets/_form.html.haml b/app/views/shared/snippets/_form.html.haml index 0296597b294..8549cb91b03 100644 --- a/app/views/shared/snippets/_form.html.haml +++ b/app/views/shared/snippets/_form.html.haml @@ -3,7 +3,7 @@ = page_specific_javascript_bundle_tag('snippet') .snippet-form-holder - = form_for @snippet, url: url, html: { class: "form-horizontal snippet-form js-requires-input js-quick-submit" } do |f| + = form_for @snippet, url: url, html: { class: "form-horizontal snippet-form js-requires-input js-quick-submit common-note-form" } do |f| = form_errors(@snippet) .form-group @@ -11,6 +11,8 @@ .col-sm-10 = f.text_field :title, class: 'form-control', required: true, autofocus: true + = render 'shared/form_elements/description', model: @snippet, project: @project, form: f + = render 'shared/visibility_level', f: f, visibility_level: @snippet.visibility_level, can_change_visibility_level: true, form_model: @snippet .file-editor @@ -23,6 +25,9 @@ .file-content.code %pre#editor= @snippet.content = f.hidden_field :content, class: 'snippet-file-content' + - if params[:files] + - params[:files].each_with_index do |file, index| + = hidden_field_tag "files[]", file, id: "files_#{index}" .form-actions - if @snippet.new_record? diff --git a/app/views/shared/snippets/_header.html.haml b/app/views/shared/snippets/_header.html.haml index 501c09d71d5..813d8d69d8d 100644 --- a/app/views/shared/snippets/_header.html.haml +++ b/app/views/shared/snippets/_header.html.haml @@ -22,3 +22,9 @@ - if @snippet.updated_at != @snippet.created_at = edited_time_ago_with_tooltip(@snippet, placement: 'bottom', html_class: 'snippet-edited-ago', exclude_author: true) + - if @snippet.description.present? + .description + .wiki + = markdown_field(@snippet, :description) + %textarea.hidden.js-task-list-field + = @snippet.description |