diff options
| author | Dmitriy Zaporozhets <dzaporozhets@gitlab.com> | 2015-01-15 09:18:10 +0000 | 
|---|---|---|
| committer | Dmitriy Zaporozhets <dzaporozhets@gitlab.com> | 2015-01-15 09:18:10 +0000 | 
| commit | 1e0f36b42a7e8fe8a4549b31233262fedfda742c (patch) | |
| tree | bc531132e71a3cfe729ad701dcb9f00f49a0780d /app | |
| parent | 28dc04aac24002f67b1bec5912255f1f6843e4f0 (diff) | |
| parent | b124d9e0bb35cbd77e441197f2f94a785d4f1f7b (diff) | |
| download | gitlab-ce-1e0f36b42a7e8fe8a4549b31233262fedfda742c.tar.gz | |
Merge branch 'fix-comments' into 'master'
Fix comments
Fixes:
* drag-n-drop works for diff comments
* selecting images works for diff comments
* preview works for edit comments
* drag-n-drop works for edit comments
* selecting images works for edit comments
* if comment presented on 'Discussion' and 'Changes' tabs - after edit it updates on both tabs.
* Correctly hide form when edit comment on diff
* fix full-screen for diff comments
See merge request !1398
Diffstat (limited to 'app')
| -rw-r--r-- | app/assets/javascripts/dispatcher.js.coffee | 4 | ||||
| -rw-r--r-- | app/assets/javascripts/dropzone_input.js.coffee | 242 | ||||
| -rw-r--r-- | app/assets/javascripts/markdown_area.js.coffee | 241 | ||||
| -rw-r--r-- | app/assets/javascripts/notes.js.coffee | 20 | ||||
| -rw-r--r-- | app/assets/javascripts/zen_mode.js.coffee | 12 | ||||
| -rw-r--r-- | app/assets/stylesheets/generic/forms.scss | 133 | ||||
| -rw-r--r-- | app/assets/stylesheets/generic/zen.scss | 98 | ||||
| -rw-r--r-- | app/assets/stylesheets/main/mixins.scss | 4 | ||||
| -rw-r--r-- | app/assets/stylesheets/sections/markdown_area.scss | 9 | ||||
| -rw-r--r-- | app/assets/stylesheets/sections/note_form.scss | 171 | ||||
| -rw-r--r-- | app/assets/stylesheets/sections/notes.scss | 166 | ||||
| -rw-r--r-- | app/views/projects/_zen.html.haml | 9 | ||||
| -rw-r--r-- | app/views/projects/notes/_edit_form.html.haml | 22 | ||||
| -rw-r--r-- | app/views/projects/notes/_form.html.haml | 7 | ||||
| -rw-r--r-- | app/views/projects/notes/_note.html.haml | 22 | 
15 files changed, 583 insertions, 577 deletions
| diff --git a/app/assets/javascripts/dispatcher.js.coffee b/app/assets/javascripts/dispatcher.js.coffee index e8b71a71945..e5349d80e94 100644 --- a/app/assets/javascripts/dispatcher.js.coffee +++ b/app/assets/javascripts/dispatcher.js.coffee @@ -33,17 +33,20 @@ class Dispatcher          GitLab.GfmAutoComplete.setup()          shortcut_handler = new ShortcutsNavigation()          new ZenMode() +        new DropzoneInput($('.issue-form'))        when 'projects:merge_requests:new', 'projects:merge_requests:edit'          GitLab.GfmAutoComplete.setup()          new Diff()          shortcut_handler = new ShortcutsNavigation()          new ZenMode() +        new DropzoneInput($('.merge-request-form'))        when 'projects:merge_requests:show'          new Diff()          shortcut_handler = new ShortcutsIssueable()          new ZenMode()        when "projects:merge_requests:diffs"          new Diff() +        new ZenMode()        when 'projects:merge_requests:index'          shortcut_handler = new ShortcutsNavigation()        when 'dashboard:show' @@ -108,6 +111,7 @@ class Dispatcher              new Wikis()              shortcut_handler = new ShortcutsNavigation()              new ZenMode() +            new DropzoneInput($('.wiki-form'))            when 'snippets', 'labels', 'graphs'              shortcut_handler = new ShortcutsNavigation()            when 'team_members', 'deploy_keys', 'hooks', 'services', 'protected_branches' diff --git a/app/assets/javascripts/dropzone_input.js.coffee b/app/assets/javascripts/dropzone_input.js.coffee new file mode 100644 index 00000000000..a0f0d98a8dc --- /dev/null +++ b/app/assets/javascripts/dropzone_input.js.coffee @@ -0,0 +1,242 @@ +class @DropzoneInput +  constructor: (form) -> +    Dropzone.autoDiscover = false +    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=\"fa fa-picture-o div-dropzone-icon\"></i>" +    iconSpinner = "<i class=\"fa fa-spinner fa-spin div-dropzone-icon\"></i>" +    btnAlert = "<button type=\"button\"" + alertAttr + ">×</button>" +    project_image_path_upload = window.project_image_path_upload or null + +    form_textarea = $(form).find("textarea.markdown-area") +    form_textarea.wrap "<div class=\"div-dropzone\"></div>" + +    form_dropzone = $(form).find('.div-dropzone') +    form_dropzone.parent().addClass "div-dropzone-wrapper" +    form_dropzone.append divHover +    $(".div-dropzone-hover").append iconPicture +    form_dropzone.append divSpinner +    $(".div-dropzone-spinner").append iconSpinner +    $(".div-dropzone-spinner").css +      "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..." +        $.get($(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 = form_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: -> +        form_textarea.addClass "div-dropzone-focus" +        form.find(".div-dropzone-hover").css "opacity", 0.7 +        return + +      dragleave: -> +        form_textarea.removeClass "div-dropzone-focus" +        form.find(".div-dropzone-hover").css "opacity", 0 +        return + +      drop: -> +        form_textarea.removeClass "div-dropzone-focus" +        form.find(".div-dropzone-hover").css "opacity", 0 +        form_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: -> +        form_dropzone.find(".div-dropzone-spinner").css +          "opacity": 0.7 +          "display": "inherit" +        return + +      complete: -> +        $(".dz-preview").remove() +        $(".markdown-area").trigger "input" +        $(".div-dropzone-spinner").css +          "opacity": 0 +          "display": "none" +        return +    ) + +    child = $(dropzone[0]).children("textarea") + +    formatLink = (str) -> +      "" + +    handlePaste = (e) -> +      e.preventDefault() +      my_event = e.originalEvent + +      if my_event.clipboardData and my_event.clipboardData.items +        processItem(my_event) + +    processItem = (e) -> +      image = isImage(e) +      if image +        filename = getFilename(e) or "image.png" +        text = "{{" + filename + "}}" +        pasteText(text) +        uploadFile image.getAsFile(), filename + +      else +        text = e.clipboardData.getData("text/plain") +        pasteText(text) + +    isImage = (data) -> +      i = 0 +      while i < data.clipboardData.items.length +        item = data.clipboardData.items[i] +        if item.type.indexOf("image") isnt -1 +          return item +        i++ +      return false + +    pasteText = (text) -> +      caretStart = $(child)[0].selectionStart +      caretEnd = $(child)[0].selectionEnd +      textEnd = $(child).val().length + +      beforeSelection = $(child).val().substring 0, caretStart +      afterSelection = $(child).val().substring caretEnd, textEnd +      $(child).val beforeSelection + text + afterSelection +      form_textarea.trigger "input" + +    getFilename = (e) -> +      if window.clipboardData and window.clipboardData.getData +        value = window.clipboardData.getData("Text") +      else if e.clipboardData and e.clipboardData.getData +        value = e.clipboardData.getData("text/plain") + +      value = value.split("\r") +      value.first() + +    uploadFile = (item, filename) -> +      formData = new FormData() +      formData.append "markdown_img", item, filename +      $.ajax +        url: project_image_path_upload +        type: "POST" +        data: formData +        dataType: "json" +        processData: false +        contentType: false +        headers: +          "X-CSRF-Token": $("meta[name=\"csrf-token\"]").attr("content") + +        beforeSend: -> +          showSpinner() +          closeAlertMessage() + +        success: (e, textStatus, response) -> +          insertToTextArea(filename, formatLink(response.responseJSON.link)) + +        error: (response) -> +          showError(response.responseJSON.message) + +        complete: -> +          closeSpinner() + +    insertToTextArea = (filename, url) -> +      $(child).val (index, val) -> +        val.replace("{{" + filename + "}}", url + "\n") + +    appendToTextArea = (url) -> +      $(child).val (index, val) -> +        val + url + "\n" + +    showSpinner = (e) -> +      form.find(".div-dropzone-spinner").css +        "opacity": 0.7 +        "display": "inherit" + +    closeSpinner = -> +      form.find(".div-dropzone-spinner").css +        "opacity": 0 +        "display": "none" + +    showError = (message) -> +      checkIfMsgExists = $(".error-alert").children().length +      if checkIfMsgExists is 0 +        $(".error-alert").append divAlert +        $(".div-dropzone-alert").append btnAlert + message + +    closeAlertMessage = -> +      form.find(".div-dropzone-alert").alert "close" + +    form.find(".markdown-selector").click (e) -> +      e.preventDefault() +      $(@).closest('.gfm-form').find('.div-dropzone').click() +      return + +  formatLink: (str) -> +    "" diff --git a/app/assets/javascripts/markdown_area.js.coffee b/app/assets/javascripts/markdown_area.js.coffee deleted file mode 100644 index 0ca7070dc8b..00000000000 --- a/app/assets/javascripts/markdown_area.js.coffee +++ /dev/null @@ -1,241 +0,0 @@ -formatLink = (str) -> -  "" - -$(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=\"fa fa-picture-o div-dropzone-icon\"></i>" -  iconSpinner = "<i class=\"fa fa-spinner fa-spin div-dropzone-icon\"></i>" -  btnAlert = "<button type=\"button\"" + alertAttr + ">×</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 -  $(".div-dropzone-spinner").css -    "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..." -      $.get($(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: "" -    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 -        "display": "inherit" -      return - -    complete: -> -      $(".dz-preview").remove() -      $(".markdown-area").trigger "input" -      $(".div-dropzone-spinner").css -        "opacity": 0 -        "display": "none" -      return -  ) - -  child = $(dropzone[0]).children("textarea") - -  formatLink = (str) -> -    "" - -  handlePaste = (e) -> -    e.preventDefault() -    my_event = e.originalEvent - -    if my_event.clipboardData and my_event.clipboardData.items -      processItem(my_event) - -  processItem = (e) -> -    image = isImage(e) -    if image -      filename = getFilename(e) or "image.png" -      text = "{{" + filename + "}}" -      pasteText(text) -      uploadFile image.getAsFile(), filename - -    else -      text = e.clipboardData.getData("text/plain") -      pasteText(text) - -  isImage = (data) -> -    i = 0 -    while i < data.clipboardData.items.length -      item = data.clipboardData.items[i] -      if item.type.indexOf("image") isnt -1 -        return item -      i++ -    return false - -  pasteText = (text) -> -    caretStart = $(child)[0].selectionStart -    caretEnd = $(child)[0].selectionEnd -    textEnd = $(child).val().length - -    beforeSelection = $(child).val().substring 0, caretStart -    afterSelection = $(child).val().substring caretEnd, textEnd -    $(child).val beforeSelection + text + afterSelection -    $(".markdown-area").trigger "input" - -  getFilename = (e) -> -    if window.clipboardData and window.clipboardData.getData -      value = window.clipboardData.getData("Text") -    else if e.clipboardData and e.clipboardData.getData -      value = e.clipboardData.getData("text/plain") - -    value = value.split("\r") -    value.first() - -  uploadFile = (item, filename) -> -    formData = new FormData() -    formData.append "markdown_img", item, filename -    $.ajax -      url: project_image_path_upload -      type: "POST" -      data: formData -      dataType: "json" -      processData: false -      contentType: false -      headers: -        "X-CSRF-Token": $("meta[name=\"csrf-token\"]").attr("content") - -      beforeSend: -> -        showSpinner() -        closeAlertMessage() - -      success: (e, textStatus, response) -> -        insertToTextArea(filename, formatLink(response.responseJSON.link)) - -      error: (response) -> -        showError(response.responseJSON.message) - -      complete: -> -        closeSpinner() - -  insertToTextArea = (filename, url) -> -    $(child).val (index, val) -> -      val.replace("{{" + filename + "}}", url + "\n") - -  appendToTextArea = (url) -> -    $(child).val (index, val) -> -      val + url + "\n" - -  showSpinner = (e) -> -    $(".div-dropzone-spinner").css -      "opacity": 0.7 -      "display": "inherit" - -  closeSpinner = -> -    $(".div-dropzone-spinner").css -      "opacity": 0 -      "display": "none" - -  showError = (message) -> -    checkIfMsgExists = $(".error-alert").children().length -    if checkIfMsgExists is 0 -      $(".error-alert").append divAlert -      $(".div-dropzone-alert").append btnAlert + message - -  closeAlertMessage = -> -    $(".div-dropzone-alert").alert "close" - -  $(".markdown-selector").click (e) -> -    e.preventDefault() -    $(@).closest('.gfm-form').find('.div-dropzone').click() -    return - -  return diff --git a/app/assets/javascripts/notes.js.coffee b/app/assets/javascripts/notes.js.coffee index 4d1c81d91d4..d1935d1d007 100644 --- a/app/assets/javascripts/notes.js.coffee +++ b/app/assets/javascripts/notes.js.coffee @@ -219,6 +219,7 @@ class @Notes    setupNoteForm: (form) ->      disableButtonIfEmptyField form.find(".js-note-text"), form.find(".js-comment-button")      form.removeClass "js-new-note-form" +    form.find('.div-dropzone').remove()      # setup preview buttons      form.find(".js-md-write-button, .js-md-preview-button").tooltip placement: "left" @@ -233,6 +234,7 @@ class @Notes      # remove notify commit author checkbox for non-commit notes      form.find(".js-notify-commit-author").remove()  if form.find("#note_noteable_type").val() isnt "Commit"      GitLab.GfmAutoComplete.setup() +    new DropzoneInput(form)      form.show() @@ -259,8 +261,10 @@ class @Notes    Updates the current note field.    ###    updateNote: (xhr, note, status) => -    note_li = $("#note_" + note.id) +    note_li = $(".note-row-" + note.id)      note_li.replaceWith(note.html) +    note_li.find('.note-edit-form').hide() +    note_li.find('.note-text').show()      code = "#note_" + note.id + " .highlight pre code"      $(code).each (i, e) ->        hljs.highlightBlock(e) @@ -276,11 +280,19 @@ class @Notes      e.preventDefault()      note = $(this).closest(".note")      note.find(".note-text").hide() +    note.find(".note-header").hide() +    base_form = note.find(".note-edit-form") +    form = base_form.clone().insertAfter(base_form) +    form.addClass('current-note-edit-form') +    form.find('.div-dropzone').remove()      # Show the attachment delete link      note.find(".js-note-attachment-delete").show() + +    # Setup markdown form      GitLab.GfmAutoComplete.setup() -    form = note.find(".note-edit-form") +    new DropzoneInput(form) +      form.show()      textarea = form.find("textarea")      textarea.focus() @@ -295,8 +307,8 @@ class @Notes      e.preventDefault()      note = $(this).closest(".note")      note.find(".note-text").show() -    note.find(".js-note-attachment-delete").hide() -    note.find(".note-edit-form").hide() +    note.find(".note-header").show() +    note.find(".current-note-edit-form").remove()    ###    Called in response to deleting a note of any kind. diff --git a/app/assets/javascripts/zen_mode.js.coffee b/app/assets/javascripts/zen_mode.js.coffee index 0c9942a4014..0fb8f7ed75f 100644 --- a/app/assets/javascripts/zen_mode.js.coffee +++ b/app/assets/javascripts/zen_mode.js.coffee @@ -10,7 +10,15 @@ class @ZenMode        if not @active_checkbox          @scroll_position = window.pageYOffset -    $('body').on 'change', '.zennable input[type=checkbox]', (e) => +    $('body').on 'click', '.zen-enter-link', (e) => +      e.preventDefault() +      $(e.currentTarget).closest('.zennable').find('.zen-toggle-comment').prop('checked', true) + +    $('body').on 'click', '.zen-leave-link', (e) => +      e.preventDefault() +      $(e.currentTarget).closest('.zennable').find('.zen-toggle-comment').prop('checked', false) + +    $('body').on 'change', '.zen-toggle-comment', (e) =>        checkbox = e.currentTarget        if checkbox.checked          # Disable other keyboard shortcuts in ZEN mode @@ -32,8 +40,6 @@ class @ZenMode      @active_zen_area = @active_checkbox.parent().find('textarea')      @active_zen_area.focus()      window.location.hash = ZenMode.fullscreen_prefix + @active_checkbox.prop('id') -    # Disable dropzone in ZEN mode -    Dropzone.forElement('.div-dropzone').disable()    exitZenMode: =>      if @active_zen_area isnt null diff --git a/app/assets/stylesheets/generic/forms.scss b/app/assets/stylesheets/generic/forms.scss index 1a832569953..c8982cdc00d 100644 --- a/app/assets/stylesheets/generic/forms.scss +++ b/app/assets/stylesheets/generic/forms.scss @@ -97,136 +97,3 @@ label {  .wiki-content {    margin-top: 35px;  } - -.zennable { -  position: relative; - -  input { -    display: none; -  } - -  .collapse { -    display: none; -    opacity: 0.5; - -    &:before { -      content: '\f066'; -      font-family: FontAwesome; -      color: #000; -      font-size: 28px; -      position: relative; -      padding: 30px 40px 0 0; -    } - -    &:hover { -      opacity: 0.8; -    } -  } - -  .expand { -    opacity: 0.5; - -    &:before { -      content: '\f065'; -      font-family: FontAwesome; -      color: #000; -      font-size: 14px; -      line-height: 14px; -      padding-right: 20px; -      position: relative; -      vertical-align: middle; -    } - -    &:hover { -      opacity: 0.8; -    } -  } - -  input:checked ~ .zen-backdrop .expand { -    display: none; -  } - -  input:checked ~ .zen-backdrop .collapse { -    display: block; -    position: absolute; -    top: 0; -  } - -  label { -    position: absolute; -    top: -26px; -    right: 0; -    font-variant: small-caps; -    text-transform: uppercase; -    font-size: 10px; -    padding: 4px; -    font-weight: 500; -    letter-spacing: 1px; - -    &:before { -      display: inline-block; -      width: 10px; -      height: 14px; -    } -  } - -  input:checked ~ .zen-backdrop { -    background-color: white; -    position: fixed; -    top: 0; -    bottom: 0; -    left: 0; -    right: 0; -    z-index: 1031; - -    textarea { -      border: none; -      box-shadow: none; -      border-radius: 0; -      color: #000; -      font-size: 20px; -      line-height: 26px; -      padding: 30px; -      display: block; -      outline: none; -      resize: none; -      height: 100vh; -      max-width: 900px; -      margin: 0 auto; -    } -  } - -  .zen-backdrop textarea::-webkit-input-placeholder { -    color: white; -  } - -  .zen-backdrop textarea:-moz-placeholder { -    color: white; -  } - -  .zen-backdrop textarea::-moz-placeholder { -    color: white; -  } - -  .zen-backdrop textarea:-ms-input-placeholder { -    color: white; -  } - -  input:checked ~ .zen-backdrop textarea::-webkit-input-placeholder { -    color: #999; -  } - -  input:checked ~ .zen-backdrop textarea:-moz-placeholder { -    color: #999; -    opacity: 1; -  } - -  input:checked ~ .zen-backdrop textarea::-moz-placeholder { -    color: #999; -    opacity: 1; -  } - -  input:checked ~ .zen-backdrop textarea:-ms-input-placeholder { -    color: #999; -  } -} diff --git a/app/assets/stylesheets/generic/zen.scss b/app/assets/stylesheets/generic/zen.scss new file mode 100644 index 00000000000..26afc21a6ab --- /dev/null +++ b/app/assets/stylesheets/generic/zen.scss @@ -0,0 +1,98 @@ +.zennable { +  position: relative; + +  input { +    display: none; +  } + +  .zen-enter-link { +    color: #888; +    position: absolute; +    top: -26px; +    right: 4px; +  } + +  .zen-leave-link { +    display: none; +    color: #888; +    position: absolute; +    top: 10px; +    right: 10px; +    padding: 5px; +    font-size: 36px; + +    &:hover { +      color: #111; +    } +  } + +  input:checked ~ .zen-backdrop .zen-enter-link { +    display: none; +  } + +  input:checked ~ .zen-backdrop .zen-leave-link { +    display: block; +    position: absolute; +    top: 0; +  } + +  input:checked ~ .zen-backdrop { +    background-color: white; +    position: fixed; +    top: 0; +    bottom: 0; +    left: 0; +    right: 0; +    z-index: 1031; + +    textarea { +      border: none; +      box-shadow: none; +      border-radius: 0; +      color: #000; +      font-size: 20px; +      line-height: 26px; +      padding: 30px; +      display: block; +      outline: none; +      resize: none; +      height: 100vh; +      max-width: 900px; +      margin: 0 auto; +    } +  } + +  .zen-backdrop textarea::-webkit-input-placeholder { +    color: white; +  } + +  .zen-backdrop textarea:-moz-placeholder { +    color: white; +  } + +  .zen-backdrop textarea::-moz-placeholder { +    color: white; +  } + +  .zen-backdrop textarea:-ms-input-placeholder { +    color: white; +  } + +  input:checked ~ .zen-backdrop textarea::-webkit-input-placeholder { +    color: #999; +  } + +  input:checked ~ .zen-backdrop textarea:-moz-placeholder { +    color: #999; +    opacity: 1; +  } + +  input:checked ~ .zen-backdrop textarea::-moz-placeholder { +    color: #999; +    opacity: 1; +  } + +  input:checked ~ .zen-backdrop textarea:-ms-input-placeholder { +    color: #999; +  } +} diff --git a/app/assets/stylesheets/main/mixins.scss b/app/assets/stylesheets/main/mixins.scss index 5f83913b73b..ebf68850f98 100644 --- a/app/assets/stylesheets/main/mixins.scss +++ b/app/assets/stylesheets/main/mixins.scss @@ -65,10 +65,6 @@      max-width: 100%;    } -  *:first-child { -    margin-top: 0; -  } -    code { padding: 0 4px; }    h1 { diff --git a/app/assets/stylesheets/sections/markdown_area.scss b/app/assets/stylesheets/sections/markdown_area.scss new file mode 100644 index 00000000000..8ee8eaa4ee7 --- /dev/null +++ b/app/assets/stylesheets/sections/markdown_area.scss @@ -0,0 +1,9 @@ +.markdown-area { +  background: #FFF; +  border: 1px solid #ddd; +  min-height: 100px; +  padding: 5px; +  font-size: 14px; +  box-shadow: none; +  width: 100%; +} diff --git a/app/assets/stylesheets/sections/note_form.scss b/app/assets/stylesheets/sections/note_form.scss new file mode 100644 index 00000000000..26511d799f3 --- /dev/null +++ b/app/assets/stylesheets/sections/note_form.scss @@ -0,0 +1,171 @@ +/** + * Note Form + */ + +.comment-btn { +  @extend .btn-create; +} +.reply-btn { +  @extend .btn-primary; +} +.diff-file .diff-content { +  tr.line_holder:hover { +    &> td.line_content { +      background: $hover !important; +      border-color: darken($hover, 10%) !important; +    } +    &> td.new_line, +    &> td.old_line { +      background: darken($hover, 4%) !important; +      border-color: darken($hover, 10%) !important; +    } +  } + +  tr.line_holder:hover > td .line_note_link { +    opacity: 1.0; +    filter: alpha(opacity=100); +  } +} +.diff-file, +.discussion { +  .new_note { +    margin: 0; +    border: none; +  } +} +.new_note { +  display: none; +} + +.new_note, .edit_note { +  .buttons { +    float: left; +    margin-top: 8px; +  } +  .clearfix { +    margin-bottom: 0; +  } + +  .note-preview-holder { +    > p { +      overflow-x: auto; +    } +  } + +  .note_text { +    width: 100%; +  } +} + +/* loading indicator */ +.notes-busy { +  margin: 18px; +} + +.note-image-attach { +  @extend .col-md-4; +  @extend .thumbnail; +  margin-left: 45px; +  float: none; +} + +.common-note-form { +  margin: 0; +  background: #F9F9F9; +  padding: 5px; +  border: 1px solid #DDD; +} + +.note-form-actions { +  background: #F9F9F9; +  height: 45px; + +  .note-form-option { +    margin-top: 8px; +    margin-left: 30px; +    @extend .pull-left; +  } + +  .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 { +  display: none; +  font-size: 13px; + +  .form-actions { +    padding-left: 20px; + +    .btn-save { +      float: left; +    } + +    .note-form-option { +      float: left; +      padding: 2px 0 0 25px; +    } +  } +} + +.js-note-attachment-delete { +  display: none; +} + +.parallel-comment { +  padding: 6px; +} + +.error-alert > .alert { +  margin-top: 5px; +  margin-bottom: 5px; +} + +.discussion-body, +.diff-file { +  .notes .note { +    border-color: #ddd; +    padding: 10px 15px; +  } + +  .discussion-reply-holder { +    background: #f9f9f9; +    padding: 10px 15px; +    border-top: 1px solid #DDD; +  } +} + +.discussion-notes-count { +  font-size: 16px; +} + +.edit_note { +  .markdown-area { +    min-height: 140px; +  } +  .note-form-actions { +    background: transparent; +  } +} + +.comment-hints { +  color: #999; +  background: #FFF; +  padding: 5px; +  margin-top: -7px; +  border: 1px solid #DDD; +  font-size: 13px; +} diff --git a/app/assets/stylesheets/sections/notes.scss b/app/assets/stylesheets/sections/notes.scss index 1550e30fe53..117e5e7f977 100644 --- a/app/assets/stylesheets/sections/notes.scss +++ b/app/assets/stylesheets/sections/notes.scss @@ -190,169 +190,3 @@ ul.notes {    }  } -/** - * Note Form - */ - -.comment-btn { -  @extend .btn-create; -} -.reply-btn { -  @extend .btn-primary; -} -.diff-file .diff-content { -  tr.line_holder:hover { -    &> td.line_content { -      background: $hover !important; -      border-color: darken($hover, 10%) !important; -    } -    &> td.new_line, -    &> td.old_line { -      background: darken($hover, 4%) !important; -      border-color: darken($hover, 10%) !important; -    } -  } - -  tr.line_holder:hover > td .line_note_link { -    opacity: 1.0; -    filter: alpha(opacity=100); -  } -} -.diff-file, -.discussion { -  .new_note { -    margin: 0; -    border: none; -  } -} -.new_note { -  display: none; -  .buttons { -    float: left; -    margin-top: 8px; -  } -  .clearfix { -    margin-bottom: 0; -  } - -  .note_text { -    background: #FFF; -    border: 1px solid #ddd; -    min-height: 100px; -    padding: 5px; -    font-size: 14px; -    box-shadow: none; -  } - -  .note-preview-holder { -    > p { -      overflow-x: auto; -    } -  } - -  .note_text { -    width: 100%; -  } -} - -/* loading indicator */ -.notes-busy { -  margin: 18px; -} - -.note-image-attach { -  @extend .col-md-4; -  @extend .thumbnail; -  margin-left: 45px; -  float: none; -} - -.common-note-form { -  margin: 0; -  background: #F9F9F9; -  padding: 5px; -  border: 1px solid #DDD; -} - -.note-form-actions { -  background: #F9F9F9; -  height: 45px; - -  .note-form-option { -    margin-top: 8px; -    margin-left: 30px; -    @extend .pull-left; -  } - -  .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 { -  display: none; - -  .note_text { -    border: 1px solid #DDD; -    box-shadow: none; -    font-size: 14px; -    height: 80px; -    width: 100%; -  } - -  .form-actions { -    padding-left: 20px; - -    .btn-save { -      float: left; -    } - -    .note-form-option { -      float: left; -      padding: 2px 0 0 25px; -    } -  } -} - -.js-note-attachment-delete { -  display: none; -} - -.parallel-comment { -  padding: 6px; -} - -.error-alert > .alert { -  margin-top: 5px; -  margin-bottom: 5px; -} - -.discussion-body, -.diff-file { -  .notes .note { -    border-color: #ddd; -    padding: 10px 15px; -  } - -  .discussion-reply-holder { -    background: #f9f9f9; -    padding: 10px 15px; -    border-top: 1px solid #DDD; -  } -} - -.discussion-notes-count { -  font-size: 16px; -} diff --git a/app/views/projects/_zen.html.haml b/app/views/projects/_zen.html.haml index 2bbc49e8eb5..5114c5874ea 100644 --- a/app/views/projects/_zen.html.haml +++ b/app/views/projects/_zen.html.haml @@ -1,7 +1,10 @@  .zennable -  %input#zen-toggle-comment{ tabindex: '-1', type: 'checkbox' } +  %input#zen-toggle-comment.zen-toggle-comment{ tabindex: '-1', type: 'checkbox' }    .zen-backdrop      - classes << ' js-gfm-input markdown-area'      = f.text_area attr, class: classes, placeholder: 'Leave a comment' -    %label{ for: 'zen-toggle-comment', class: 'expand' } Edit in fullscreen -    %label{ for: 'zen-toggle-comment', class: 'collapse' } +    = link_to nil, class: 'zen-enter-link' do +      %i.fa.fa-expand +      Edit in fullscreen +    = link_to nil, class: 'zen-leave-link' do +      %i.fa.fa-compress diff --git a/app/views/projects/notes/_edit_form.html.haml b/app/views/projects/notes/_edit_form.html.haml new file mode 100644 index 00000000000..59e2b3f1b0b --- /dev/null +++ b/app/views/projects/notes/_edit_form.html.haml @@ -0,0 +1,22 @@ +.note-edit-form +  = form_for note, url: project_note_path(@project, note), method: :put, remote: true, authenticity_token: true do |f| +    = render layout: 'projects/md_preview' do +      = render 'projects/zen', f: f, attr: :note, +        classes: 'note_text js-note-text' + +      .comment-hints.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 & dropping or #{link_to "selecting them", '#', class: 'markdown-selector', tabindex: -1 }. + +    .note-form-actions +      .buttons +        = f.submit 'Save Comment', class: "btn btn-primary btn-save btn-grouped js-comment-button" +        = link_to  'Cancel', "#", class: "btn btn-cancel note-edit-cancel" + +      .note-form-option.hidden-xs +        %a.choose-btn.btn.js-choose-note-attachment-button +          %i.fa.fa-paperclip +          %span Choose File ... +          +        %span.file_name.js-attachment-filename +        = f.file_field :attachment, class: "js-note-attachment-input hidden" diff --git a/app/views/projects/notes/_form.html.haml b/app/views/projects/notes/_form.html.haml index 47ffe1fd2f3..3879a0f10da 100644 --- a/app/views/projects/notes/_form.html.haml +++ b/app/views/projects/notes/_form.html.haml @@ -7,8 +7,9 @@    = render layout: 'projects/md_preview' do      = render 'projects/zen', f: f, attr: :note, -                             classes: 'note_text js-note-text' -    .light.clearfix +      classes: 'note_text js-note-text' + +    .comment-hints.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 & dropping or #{link_to "selecting them", '#', class: 'markdown-selector', tabindex: -1 }. @@ -24,7 +25,7 @@          %i.fa.fa-paperclip          %span Choose File ...          -      %span.file_name.js-attachment-filename File name... +      %span.file_name.js-attachment-filename        = f.file_field :attachment, class: "js-note-attachment-input hidden"  :javascript diff --git a/app/views/projects/notes/_note.html.haml b/app/views/projects/notes/_note.html.haml index 80e7342455b..691c169b620 100644 --- a/app/views/projects/notes/_note.html.haml +++ b/app/views/projects/notes/_note.html.haml @@ -1,4 +1,4 @@ -%li.timeline-entry{ id: dom_id(note), class: [dom_class(note), ('system-note' if note.system)], data: { discussion: note.discussion_id } } +%li.timeline-entry{ id: dom_id(note), class: [dom_class(note), "note-row-#{note.id}", ('system-note' if note.system)], data: { discussion: note.discussion_id } }    .timeline-entry-inner      .timeline-icon        - if note.system @@ -42,25 +42,7 @@          .note-text            = preserve do              = markdown(note.note, {no_header_anchors: true}) - -        .note-edit-form -          = form_for note, url: project_note_path(@project, note), method: :put, remote: true, authenticity_token: true do |f| -            = render layout: 'projects/md_preview' do -              = f.text_area :note, class: 'note_text js-note-text js-gfm-input turn-on' - -            .form-actions.clearfix -              = f.submit 'Save changes', class: "btn btn-primary btn-save js-comment-button" - -              .note-form-option -                %a.choose-btn.btn.js-choose-note-attachment-button -                  %i.fa.fa-paperclip -                  %span Choose File ... -                  -                %span.file_name.js-attachment-filename File name... -                = f.file_field :attachment, class: "js-note-attachment-input hidden" - -              = link_to  'Cancel', "#", class: "btn btn-cancel note-edit-cancel" - +        = render 'projects/notes/edit_form', note: note        - if note.attachment.url          .note-attachment | 
