Commit 5700842b authored by Vinnie Okada's avatar Vinnie Okada

Add Markdown preview to more forms

Enable Markdown previews when creating and editing issues, merge
requests, and milestones, and when editing notes.
parent a0a826eb
......@@ -24,6 +24,51 @@ $(document).ready ->
"opacity": 0
"display": "none"
# Preview button
$(document).off "click", ".js-md-preview-button"
$(document).on "click", ".js-md-preview-button", (e) ->
###
Shows the Markdown preview.
Lets the server render GFM into Html and displays it.
###
e.preventDefault()
form = $(this).closest("form")
# toggle tabs
form.find(".js-md-write-button").parent().removeClass "active"
form.find(".js-md-preview-button").parent().addClass "active"
# toggle content
form.find(".md-write-holder").hide()
form.find(".md-preview-holder").show()
preview = form.find(".js-md-preview")
mdText = form.find(".markdown-area").val()
if mdText.trim().length is 0
preview.text "Nothing to preview."
else
preview.text "Loading..."
$.post($(this).data("url"),
md_text: mdText
).success (previewData) ->
preview.html previewData
# Write button
$(document).off "click", ".js-md-write-button"
$(document).on "click", ".js-md-write-button", (e) ->
###
Shows the Markdown textarea.
###
e.preventDefault()
form = $(this).closest("form")
# toggle tabs
form.find(".js-md-write-button").parent().addClass "active"
form.find(".js-md-preview-button").parent().removeClass "active"
# toggle content
form.find(".md-write-holder").show()
form.find(".md-preview-holder").hide()
dropzone = $(".div-dropzone").dropzone(
url: project_image_path_upload
dictDefaultMessage: ""
......
......@@ -36,12 +36,6 @@ class Notes
# delete note attachment
$(document).on "click", ".js-note-attachment-delete", @removeAttachment
# Preview button
$(document).on "click", ".js-note-preview-button", @previewNote
# Preview button
$(document).on "click", ".js-note-write-button", @writeNote
# reset main target form after submit
$(document).on "ajax:complete", ".js-main-target-form", @resetMainTargetForm
......@@ -77,8 +71,6 @@ class Notes
$(document).off "click", ".note-edit-cancel"
$(document).off "click", ".js-note-delete"
$(document).off "click", ".js-note-attachment-delete"
$(document).off "click", ".js-note-preview-button"
$(document).off "click", ".js-note-write-button"
$(document).off "ajax:complete", ".js-main-target-form"
$(document).off "click", ".js-choose-note-attachment-button"
$(document).off "click", ".js-discussion-reply-button"
......@@ -165,47 +157,6 @@ class Notes
# cleanup after successfully creating a diff/discussion note
@removeDiscussionNoteForm(form)
###
Shows write note textarea.
###
writeNote: (e) ->
e.preventDefault()
form = $(this).closest("form")
# toggle tabs
form.find(".js-note-write-button").parent().addClass "active"
form.find(".js-note-preview-button").parent().removeClass "active"
# toggle content
form.find(".note-write-holder").show()
form.find(".note-preview-holder").hide()
###
Shows the note preview.
Lets the server render GFM into Html and displays it.
###
previewNote: (e) ->
e.preventDefault()
form = $(this).closest("form")
# toggle tabs
form.find(".js-note-write-button").parent().removeClass "active"
form.find(".js-note-preview-button").parent().addClass "active"
# toggle content
form.find(".note-write-holder").hide()
form.find(".note-preview-holder").show()
preview = form.find(".js-note-preview")
noteText = form.find(".js-note-text").val()
if noteText.trim().length is 0
preview.text "Nothing to preview."
else
preview.text "Loading..."
$.post($(this).data("url"),
note: noteText
).success (previewData) ->
preview.html previewData
###
Called in response the main target form has been successfully submitted.
......@@ -220,7 +171,7 @@ class Notes
form.find(".js-errors").remove()
# reset text and preview
form.find(".js-note-write-button").click()
form.find(".js-md-write-button").click()
form.find(".js-note-text").val("").trigger "input"
###
......@@ -270,8 +221,8 @@ class Notes
form.removeClass "js-new-note-form"
# setup preview buttons
form.find(".js-note-write-button, .js-note-preview-button").tooltip placement: "left"
previewButton = form.find(".js-note-preview-button")
form.find(".js-md-write-button, .js-md-preview-button").tooltip placement: "left"
previewButton = form.find(".js-md-preview-button")
form.find(".js-note-text").on "input", ->
if $(this).val().trim() isnt ""
previewButton.removeClass("turn-off").addClass "turn-on"
......
......@@ -50,3 +50,28 @@
margin-bottom: 0;
transition: opacity 200ms ease-in-out;
}
.md-preview-holder {
background: #FFF;
border: 1px solid #ddd;
min-height: 100px;
padding: 5px;
font-size: 14px;
box-shadow: none;
}
.new_note,
.edit_note,
.issuable-description,
.milestone-description,
.merge-request-form {
.nav-tabs {
margin-bottom: 0;
border: none;
li a,
li.active a {
border: 1px solid #DDD;
}
}
}
......@@ -224,7 +224,6 @@ ul.notes {
margin-bottom: 0;
}
.note-preview-holder,
.note_text {
background: #FFF;
border: 1px solid #ddd;
......@@ -243,15 +242,6 @@ ul.notes {
.note_text {
width: 100%;
}
.nav-tabs {
margin-bottom: 0;
border: none;
li a,
li.active a {
border: 1px solid #DDD;
}
}
}
/* loading indicator */
......
......@@ -61,10 +61,6 @@ class Projects::NotesController < Projects::ApplicationController
end
end
def preview
render text: view_context.markdown(params[:note])
end
private
def note
......
......@@ -183,6 +183,10 @@ class ProjectsController < ApplicationController
render json: { star_count: @project.star_count }
end
def markdown_preview
render text: view_context.markdown(params[:md_text])
end
private
def upload_path
......
......@@ -14,17 +14,20 @@
.form-group.issuable-description
= f.label :description, 'Description', class: 'control-label'
.col-sm-10
= render 'projects/zen', f: f, attr: :description,
classes: 'description form-control'
.col-sm-12.hint
.pull-left
Parsed with
#{link_to 'GitLab Flavored Markdown', help_page_path('markdown', 'markdown'), target: '_blank'}.
.pull-right
Attach images (JPG, PNG, GIF) by dragging &amp; dropping
or #{link_to 'selecting them', '#', class: 'markdown-selector' }.
.clearfix
.error-alert
= render layout: 'projects/md_preview' do
= render 'projects/zen', f: f, attr: :description,
classes: 'description form-control'
.col-sm-12.hint
.pull-left
Parsed with
#{link_to 'GitLab Flavored Markdown', help_page_path('markdown', 'markdown'), target: '_blank'}.
.pull-right
Attach images (JPG, PNG, GIF) by dragging &amp; dropping
or #{link_to 'selecting them', '#', class: 'markdown-selector' }.
.clearfix
.error-alert
%hr
.form-group
.issue-assignee
......
%ul.nav.nav-tabs
%li.active
= link_to '#md-write-holder', class: 'js-md-write-button' do
Write
%li
= link_to '#md-preview-holder', class: 'js-md-preview-button', data: { url: markdown_preview_project_path(@project) } do
Preview
%div
.md-write-holder
= yield
.md-preview-holder.hide
.js-md-preview
......@@ -21,12 +21,13 @@
.form-group
.light
= f.label :description, "Description"
= render 'projects/zen', f: f, attr: :description,
classes: 'description form-control'
.clearfix.hint
.pull-left Description is parsed with #{link_to "GitLab Flavored Markdown", help_page_path("markdown", "markdown"), target: '_blank'}.
.pull-right Attach images (JPG, PNG, GIF) by dragging & dropping or #{link_to "selecting them", '#', class: 'markdown-selector' }.
.error-alert
= render layout: 'projects/md_preview' do
= render 'projects/zen', f: f, attr: :description,
classes: 'description form-control'
.clearfix.hint
.pull-left Description is parsed with #{link_to "GitLab Flavored Markdown", help_page_path("markdown", "markdown"), target: '_blank'}.
.pull-right Attach images (JPG, PNG, GIF) by dragging & dropping or #{link_to "selecting them", '#', class: 'markdown-selector' }.
.error-alert
.form-group
.issue-assignee
= f.label :assignee_id do
......
......@@ -18,13 +18,14 @@
.col-sm-10
= f.text_field :title, maxlength: 255, class: "form-control"
%p.hint Required
.form-group
.form-group.milestone-description
= f.label :description, "Description", class: "control-label"
.col-sm-10
= render 'projects/zen', f: f, attr: :description, classes: 'description form-control'
.hint
.pull-left Milestones are parsed with #{link_to "GitLab Flavored Markdown", help_page_path("markdown", "markdown"), target: '_blank'}.
.pull-left Attach images (JPG, PNG, GIF) by dragging & dropping or #{link_to "selecting them", '#', class: 'markdown-selector' }.
= render layout: 'projects/md_preview' do
= render 'projects/zen', f: f, attr: :description, classes: 'description form-control'
.hint
.pull-left Milestones are parsed with #{link_to "GitLab Flavored Markdown", help_page_path("markdown", "markdown"), 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
......
......@@ -5,23 +5,13 @@
= f.hidden_field :noteable_id
= f.hidden_field :noteable_type
%ul.nav.nav-tabs
%li.active
= link_to '#note-write-holder', class: 'js-note-write-button' do
Write
%li
= link_to '#note-preview-holder', class: 'js-note-preview-button', data: { url: preview_project_notes_path(@project) } do
Preview
%div
.note-write-holder
= render 'projects/zen', f: f, attr: :note,
classes: 'note_text js-note-text'
.light.clearfix
.pull-left Comments are parsed with #{link_to "GitLab Flavored Markdown", help_page_path("markdown", "markdown"),{ target: '_blank', tabindex: -1 }}
.pull-right Attach images (JPG, PNG, GIF) by dragging &amp; dropping or #{link_to "selecting them", '#', class: 'markdown-selector', tabindex: -1 }.
= render layout: 'projects/md_preview' do
= render 'projects/zen', f: f, attr: :note,
classes: 'note_text js-note-text'
.light.clearfix
.pull-left Comments are parsed with #{link_to "GitLab Flavored Markdown", help_page_path("markdown", "markdown"),{ target: '_blank', tabindex: -1 }}
.pull-right Attach images (JPG, PNG, GIF) by dragging &amp; dropping or #{link_to "selecting them", '#', class: 'markdown-selector', tabindex: -1 }.
.note-preview-holder.hide
.js-note-preview
.note-form-actions
.buttons
......
......@@ -38,7 +38,8 @@
.note-edit-form
= form_for note, url: project_note_path(@project, note), method: :put, remote: true, authenticity_token: true do |f|
= f.text_area :note, class: 'note_text js-note-text js-gfm-input turn-on'
= render layout: 'projects/md_preview' do
= f.text_area :note, class: 'note_text js-note-text markdown-area js-gfm-input turn-on'
.form-actions.clearfix
= f.submit 'Save changes', class: "btn btn-primary btn-save js-comment-button"
......
......@@ -186,6 +186,7 @@ Gitlab::Application.routes.draw do
post :unarchive
post :upload_image
post :toggle_star
post :markdown_preview
get :autocomplete_sources
get :import
put :retry_import
......@@ -328,10 +329,6 @@ Gitlab::Application.routes.draw do
member do
delete :delete_attachment
end
collection do
post :preview
end
end
end
end
......
......@@ -159,3 +159,30 @@ Feature: Project Issues
Given project "Shop" has "Tasks-closed" closed issue with task markdown
When I visit issue page "Tasks-closed"
Then Task checkboxes should be disabled
# Issue description preview
@javascript
Scenario: I can't preview without text
Given I click link "New Issue"
And I haven't written any description text
Then I should not see the Markdown preview button
@javascript
Scenario: I can preview with text
Given I click link "New Issue"
And I write a description like "Nice"
Then I should see the Markdown preview button
@javascript
Scenario: I preview an issue description
Given I click link "New Issue"
And I preview a description text like "Bug fixed :smile:"
Then I should see the Markdown preview
And I should not see the Markdown text field
@javascript
Scenario: I can edit after preview
Given I click link "New Issue"
And I preview a description text like "Bug fixed :smile:"
Then I should see the Markdown edit button
......@@ -187,3 +187,34 @@ Feature: Project Merge Requests
And I visit merge request page "MR-task-open"
And I click link "Close"
Then Task checkboxes should be disabled
# Description preview
@javascript
Scenario: I can't preview without text
Given I visit merge request page "Bug NS-04"
And I click link "Edit"
And I haven't written any description text
Then I should not see the Markdown preview button
@javascript
Scenario: I can preview with text
Given I visit merge request page "Bug NS-04"
And I click link "Edit"
And I write a description like "Nice"
Then I should see the Markdown preview button
@javascript
Scenario: I preview a merge request description
Given I visit merge request page "Bug NS-04"
And I click link "Edit"
And I preview a description text like "Bug fixed :smile:"
Then I should see the Markdown preview
And I should not see the Markdown text field
@javascript
Scenario: I can edit after preview
Given I visit merge request page "Bug NS-04"
And I click link "Edit"
And I preview a description text like "Bug fixed :smile:"
Then I should see the Markdown edit button
......@@ -10,6 +10,10 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps
click_link "New Merge Request"
end
step 'I click link "Edit"' do
click_link 'Edit'
end
step 'I click link "Bug NS-04"' do
click_link "Bug NS-04"
end
......
......@@ -32,7 +32,7 @@ module SharedDiffNote
click_diff_line(sample_commit.line_code)
within("#{diff_file_selector} form[rel$='#{sample_commit.line_code}']") do
fill_in "note[note]", with: "Should fix it :smile:"
find(".js-note-preview-button").trigger("click")
find('.js-md-preview-button').trigger('click')
end
end
......@@ -41,7 +41,7 @@ module SharedDiffNote
within("#{diff_file_selector} form[rel$='#{sample_commit.del_line_code}']") do
fill_in "note[note]", with: "DRY this up"
find(".js-note-preview-button").trigger("click")
find('.js-md-preview-button').trigger('click')
end
end
......@@ -73,7 +73,7 @@ module SharedDiffNote
step 'I should not see the diff comment preview button' do
within(diff_file_selector) do
page.should have_css(".js-note-preview-button", visible: false)
page.should have_css('.js-md-preview-button', visible: false)
end
end
......@@ -131,25 +131,25 @@ module SharedDiffNote
step 'I should see the diff comment preview' do
within("#{diff_file_selector} form") do
page.should have_css(".js-note-preview", visible: false)
page.should have_css('.js-md-preview', visible: false)
end
end
step 'I should see the diff comment edit button' do
within(diff_file_selector) do
page.should have_css(".js-note-write-button", visible: true)
page.should have_css('.js-md-write-button', visible: true)
end
end
step 'I should see the diff comment preview button' do
within(diff_file_selector) do
page.should have_css(".js-note-preview-button", visible: true)
page.should have_css('.js-md-preview-button', visible: true)
end
end
step 'I should see two separate previews' do
within(diff_file_selector) do
page.should have_css(".js-note-preview", visible: true, count: 2)
page.should have_css('.js-md-preview', visible: true, count: 2)
page.should have_content("Should fix it")
page.should have_content("DRY this up")
end
......
......@@ -54,4 +54,43 @@ EOT
'div.description li.task-list-item input[type="checkbox"]:disabled'
)
end
step 'I should not see the Markdown preview' do
find('.gfm-form').should have_css('.js-md-preview', visible: false)
end
step 'I should not see the Markdown preview button' do
find('.gfm-form').should have_css('.js-md-preview-button', visible: false)
end
step 'I should not see the Markdown text field' do
find('.gfm-form').should have_css('textarea', visible: false)
end
step 'I should see the Markdown edit button' do
find('.gfm-form').should have_css('.js-md-write-button', visible: true)
end
step 'I should see the Markdown preview' do
find('.gfm-form').should have_css('.js-md-preview', visible: true)
end
step 'I should see the Markdown preview button' do
find('.gfm-form').should have_css('.js-md-preview-button', visible: true)
end
step 'I write a description like "Nice"' do
find('.gfm-form').fill_in 'Description', with: 'Nice'
end
step 'I preview a description text like "Bug fixed :smile:"' do
within('.gfm-form') do
fill_in 'Description', with: 'Bug fixed :smile:'
find('.js-md-preview-button').trigger('click')
end
end
step 'I haven\'t written any description text' do
find('.gfm-form').fill_in 'Description', with: ''
end
end
......@@ -23,7 +23,7 @@ module SharedNote
step 'I preview a comment text like "Bug fixed :smile:"' do
within(".js-main-target-form") do
fill_in "note[note]", with: "Bug fixed :smile:"
find(".js-note-preview-button").trigger("click")
find('.js-md-preview-button').trigger('click')
end
end
......@@ -51,13 +51,13 @@ module SharedNote
step 'I should not see the comment preview' do
within(".js-main-target-form") do
page.should have_css(".js-note-preview", visible: false)
page.should have_css('.js-md-preview', visible: false)
end
end
step 'I should not see the comment preview button' do
within(".js-main-target-form") do
page.should have_css(".js-note-preview-button", visible: false)
page.should have_css('.js-md-preview-button', visible: false)
end
end
......@@ -81,19 +81,19 @@ module SharedNote
step 'I should see the comment edit button' do
within(".js-main-target-form") do
page.should have_css(".js-note-write-button", visible: true)
page.should have_css('.js-md-write-button', visible: true)
end
end
step 'I should see the comment preview' do
within(".js-main-target-form") do
page.should have_css(".js-note-preview", visible: true)
page.should have_css('.js-md-preview', visible: true)
end
end
step 'I should see the comment preview button' do
within(".js-main-target-form") do
page.should have_css(".js-note-preview-button", visible: true)
page.should have_css('.js-md-preview-button', visible: true)
end
end
......
......@@ -20,7 +20,7 @@ describe 'Comments' do
should have_css(".js-main-target-form", visible: true, count: 1)
find(".js-main-target-form input[type=submit]").value.should == "Add Comment"
within(".js-main-target-form") { should_not have_link("Cancel") }
within(".js-main-target-form") { should have_css(".js-note-preview-button", visible: false) }
within('.js-main-target-form') { should have_css('.js-md-preview-button', visible: false) }
end
describe "with text" do
......@@ -32,7 +32,7 @@ describe 'Comments' do
it 'should have enable submit button and preview button' do
within(".js-main-target-form") { should_not have_css(".js-comment-button[disabled]") }
within(".js-main-target-form") { should have_css(".js-note-preview-button", visible: true) }
within('.js-main-target-form') { should have_css('.js-md-preview-button', visible: true) }
end
end
end
......@@ -41,7 +41,7 @@ describe 'Comments' do
before do
within(".js-main-target-form") do
fill_in "note[note]", with: "This is awsome!"
find(".js-note-preview-button").trigger("click")
find('.js-md-preview-button').trigger('click')
click_button "Add Comment"
end
end
......@@ -49,7 +49,7 @@ describe 'Comments' do
it 'should be added and form reset' do
should have_content("This is awsome!")
within(".js-main-target-form") { should have_no_field("note[note]", with: "This is awesome!") }
within(".js-main-target-form") { should have_css(".js-note-preview", visible: false) }
within('.js-main-target-form') { should have_css('.js-md-preview', visible: false) }
within(".js-main-target-form") { should have_css(".js-note-text", visible: true) }
end
end
......@@ -172,11 +172,11 @@ describe 'Comments' do
# add two separate texts and trigger previews on both
within("tr[id='#{line_code}'] + .js-temp-notes-holder") do
fill_in "note[note]", with: "One comment on line 7"
find(".js-note-preview-button").trigger("click")
find('.js-md-preview-button').trigger('click')
end
within("tr[id='#{line_code_2}'] + .js-temp-notes-holder") do
fill_in "note[note]", with: "Another comment on line 10"
find(".js-note-preview-button").trigger("click")
find('.js-md-preview-button').trigger('click')
end
end
end
......
......@@ -53,14 +53,15 @@ shared_examples "RESTful project resources" do
end
end
# projects POST /projects(.:format) projects#create
# new_project GET /projects/new(.:format) projects#new
# fork_project POST /:id/fork(.:format) projects#fork
# files_project GET /:id/files(.:format) projects#files
# edit_project GET /:id/edit(.:format) projects#edit
# project GET /:id(.:format) projects#show
# PUT /:id(.:format) projects#update
# DELETE /:id(.:format) projects#destroy
# projects POST /projects(.:format) projects#create
# new_project GET /projects/new(.:format) projects#new
# fork_project POST /:id/fork(.:format) projects#fork
# files_project GET /:id/files(.:format) projects#files
# edit_project GET /:id/edit(.:format) projects#edit
# project GET /:id(.:format) projects#show
# PUT /:id(.:format) projects#update
# DELETE /:id(.:format) projects#destroy
# markdown_preview_project POST /:id/markdown_preview(.:format) projects#markdown_preview
describe ProjectsController, "routing" do
it "to #create" do
post("/projects").should route_to('projects#create')
......@@ -93,6 +94,12 @@ describe ProjectsController, "routing" do
it "to #destroy" do
delete("/gitlab/gitlabhq").should route_to('projects#destroy', id: 'gitlab/gitlabhq')
end
it 'to #markdown_preview' do
post('/gitlab/gitlabhq/markdown_preview').should(
route_to('projects#markdown_preview', id: 'gitlab/gitlabhq')
)
end
end
# pages_project_wikis GET /:project_id/wikis/pages(.:format) projects/wikis#pages
......@@ -392,15 +399,10 @@ describe Projects::IssuesController, "routing" do
end
end
# preview_project_notes POST /:project_id/notes/preview(.:format) notes#preview
# project_notes GET /:project_id/notes(.:format) notes#index
# POST /:project_id/notes(.:format) notes#create
# project_note DELETE /:project_id/notes/:id(.:format) notes#destroy
describe Projects::NotesController, "routing" do
it "to #preview" do
post("/gitlab/gitlabhq/notes/preview").should route_to('projects/notes#preview', project_id: 'gitlab/gitlabhq')
end
it_behaves_like "RESTful project resources" do
let(:actions) { [:index, :create, :destroy] }
let(:controller) { 'notes' }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment