{"version":3,"sources":["webpack:///./awards_handler.js","webpack:///./abuse_reports/components/constants.js","webpack:////build/source/node_modules/lodash/_arrayIncludesWith.js","webpack:////build/source/node_modules/lodash/_createSet.js","webpack:///./notes/i18n.js","webpack:///./abuse_reports/components/abuse_category_selector.vue","webpack:///./abuse_reports/components/abuse_category_selector.vue?5b67","webpack:///abuse_reports/components/abuse_category_selector.vue","webpack:///./abuse_reports/components/abuse_category_selector.vue?54dd","webpack:///./notes/components/comment_type_dropdown.vue","webpack:///./notes/components/comment_type_dropdown.vue?30de","webpack:///notes/components/comment_type_dropdown.vue","webpack:///./notes/components/comment_type_dropdown.vue?fa53","webpack:////build/source/node_modules/lodash/uniq.js","webpack:////build/source/node_modules/lodash/_baseUniq.js","webpack:///./deprecated_notes.js","webpack:///./init_deprecated_notes.js","webpack:///./autosave.js","webpack:///./projects/report_abuse/components/report_abuse_dropdown_item.vue?fd8f","webpack:///projects/report_abuse/components/report_abuse_dropdown_item.vue","webpack:///./projects/report_abuse/components/report_abuse_dropdown_item.vue?83c5","webpack:///./projects/report_abuse/components/report_abuse_dropdown_item.vue","webpack:///./projects/report_abuse/index.js"],"names":["transitionEndEventString","FROM_SENTENCE_REGEX","categoryLabelMap","activity","people","nature","food","travel","objects","symbols","flags","AwardsHandler","constructor","emoji","this","eventListeners","toggleButtonSelector","menuClass","bindEvents","_this","$parentEl","targetContainerEl","$","document","registerEventListener","length","requestAnimationFrame","createEmojiMenu","e","stopPropagation","preventDefault","showEmojiMenu","currentTarget","target","closest","removeClass","is","hideMenuElement","emojiButtonSelector","$target","$glEmojiElement","find","$spriteIconElement","emojiName","data","addClass","addAward","getVotesBlock","getAwardUrl","method","element","args","call","push","$addBtn","_this2","hasClass","$menu","blur","positionMenu","showMenuElement","focus","$createdMenu","setTimeout","callback","isCreatingEmojiMenu","categoryMap","getEmojiCategoryMap","categoryNameKey","Object","keys","emojisInCategory","firstCategory","renderCategory","frequentlyUsedEmojis","getFrequentlyUsedEmojis","frequentlyUsedCatgegory","frequentEmojis","emojiMenuMarkup","body","insertAdjacentHTML","addRemainingEmojiMenuCategories","setupSearch","_this3","isAddingRemainingEmojiMenuCategories","menu","querySelector","emojiContentElement","slice","reduce","promiseChain","then","Promise","resolve","categoryMarkup","dispatchEvent","CustomEvent","catch","err","Error","message","name","emojiList","opts","_this4","_escape","map","glEmojiTag","sprite","join","css","top","outerHeight","position","offset","bp","getBreakpointSize","left","outerWidth","votesBlock","awardUrl","_this5","isMainAwardsBlock","isInVueNoteablePage","id","attr","replace","toggleAwardEvent","detail","awardName","noteId","normalizedEmoji","normalizeEmojiName","$emojiButton","findEmojiIcon","postEmoji","addAwardToEmojiBar","undefined","addEmojiToFrequentlyUsedList","isActive","decrementCounter","counter","text","parseInt","addYouToUserList","animateEmoji","createEmoji","$el","currentBlock","resultantVotesBlock","eq","counterNumber","removeYouFromUserList","EMOJI_THUMBS_UP","EMOJI_THUMBS_DOWN","dispose","parents","removeEmoji","remove","$votesBlock","getAwardTooltip","$awardBlock","toSentence","list","sentence","awardBlock","authors","split","splice","indexOf","removeData","removeAttr","fixTitle","origTitle","users","trim","unshift","createAwardButtonForVotesBlock","buttonHtml","insertBefore","$emoji","_this6","axios","post","ok","createAlert","__","scrollToAwards","scrollToElement","isEmojiNameValid","_uniq","concat","localStorage","setItem","FREQUENTLY_USED_EMOJIS_STORAGE_KEY","_this7","getItem","filter","inputName","_this8","$search","term","val","searchEmojis","h5","foundEmojis","findMatchingEmojiElements","show","ul","append","hide","children","getEmojiScore","emojis","value","elem","get","x","dataset","score","sortEmojiElements","$elements","_this9","scores","WeakMap","sort","a","b","aScore","bScore","set","query","matchingEmoji","searchEmoji","getEmojiScoreWithIntent","matchingEmojiNames","$matchingElements","i","elm","clone","$emojiMenu","on","off","destroy","forEach","entry","awardsHandlerPromise","loadAwardsHandler","reload","Emoji","awardsHandler","CATEGORY_OPTIONS","s__","module","exports","array","comparator","index","Set","noop","setToArray","createSet","values","COMMENT_FORM","GENERIC_UNSUBMITTABLE_NETWORK","error","note","comment","wiki","internalComment","issue","startThread","startInternalThread","mergeRequest","epic","bodyPlaceholder","bodyPlaceholderInternal","internal","internalVisibility","discussionThatNeedsResolution","internalDiscussionThatNeedsResolution","discussion","internalDiscussion","actionButtonWithNote","actionButton","withNote","reopen","close","withoutNote","submitButton","commentHelp","internalCommentHelp","addToReviewButton","saveThread","saveComment","addToReview","startReview","addCommentNow","addThreadNow","EDITED_TEXT","actionWithAuthor","actionWithoutAuthor","UPDATE_COMMENT_FORM","defaultError","csrf","components","GlButton","GlDrawer","GlForm","GlFormGroup","GlFormRadioGroup","inject","reportAbusePath","default","props","reportedUserId","type","Number","required","reportedFromUrl","String","showDrawer","Boolean","i18n","title","label","next","selected","mounted","computed","getDrawerHeaderHeight","getContentWrapperHeight","methods","closeDrawer","$emit","component","_vm","_c","_self","attrs","scopedSlots","_u","key","fn","staticClass","_v","_s","$options","proxy","domProps","token","model","$$v","expression","toggleSrText","GlButtonGroup","GlCollapsibleListbox","prop","event","disabled","trackingLabel","discussionsRequireResolution","isInternalNote","noteableDisplayName","noteType","isReviewDropdown","isNoteTypeComment","constants","isNoteTypeDiscussion","dropdownCommentButtonTitle","dropdownStartThreadButtonTitle","commentButtonTitle","startDiscussionDescription","commentDescription","sprintf","dropdownItems","description","testid","handleClick","setNoteType","item","baseUniq","SetCache","arrayIncludes","arrayIncludesWith","cacheHas","iteratee","includes","isCommon","result","seen","outer","seenIndex","normalizeNewlines","str","window","autosize","Autosize","REGEX_QUICK_ACTIONS","Notes","notes_url","last_fetched_at","view","enableGFM","instance","defaultAutocompleteConfig","updateTargetButtons","bind","updateComment","visibilityChange","cancelDiscussionForm","onAddDiffNote","onAddImageDiffNote","setupDiscussionNoteForm","onReplyToDiscussionNote","removeNote","cancelEdit","updateNote","addDiscussionNote","addNoteError","addNote","resetMainTargetForm","refresh","keydownNoteText","toggleCommitList","postComment","clearAlertWrapper","clearAlert","onHashChange","note_ids","updatedNotesTrackingMap","noteable_url","URL","notesCountBadge","basePollingInterval","maxPollingSteps","$wrapperEl","isInMRPage","cleanBinding","addBinding","setPollingInterval","setupMainTargetNoteForm","taskList","TaskList","dataType","fieldName","selector","setViewType","getPagePath","insertAfter","hash","getLocationHash","$anchor","getElementById","loadLazyDiff","getCookie","showEditForm","removeAttachment","updateFormAttachment","onClickRetryLazyLoad","reenableTargetFormSubmitButton","form","el","noteableName","noteTypeInput","formHasContent","commentTypeComponent","Vue","render","createElement","CommentTypeDropdown","change","arg","discussionNoteForm","editNote","myLastNote","myLastNoteEditBtn","newText","originalText","isModifierKey","$textarea","which","gon","current_user_id","trigger","confirmAction","primaryBtnVariant","primaryBtnText","removeDiscussionNoteForm","removeNoteEditForm","initRefresh","interval","clearInterval","setInterval","pollingInterval","hidden","getContent","refreshing","headers","notes","each","renderNote","shouldReset","nthInterval","handleQuickActions","noteEntity","commands_changes","checkMergeRequestStatus","emoji_award","setupNewNote","$note","localTimeAgo","init","updateNoteTargetSelector","$noteToCleanHighlight","addTargetClass","toggleClass","$form","$notesList","discussion_html","renderDiscussionNote","_noteEntity$quick_act","valid","quick_actions_status","messages","addAlert","variant","VARIANT_INFO","parent","parentTimeline","isNewNote","$newNote","animateAppendNote","html","updateNotesCount","isUpdatedNote","isEditing","initialContent","currentContent","sanitizedNoteNote","isTextareaUntouched","putConflictEditWarningInPlace","$updatedNote","animateUpdateNote","isParallelView","discussionContainer","row","discussion_id","discussion_line_code","on_image","diff_discussion_html","internalNote","discussionElement","sanitize","RETURN_DOM","insertAdjacentElement","firstElementChild","renderGFM","$discussion","unwrap","classList","add","after","$notes","contentContainerClass","querySelectorAll","getLineHolder","changesDiscussionContainer","prevAll","first","click","$autosave","reset","createEvent","initEvent","formClone","setupNoteForm","initCommentTypeToggle","glForm","GLForm","textarea","textareaEl","Autosave","_error$response","formParentTimeline","serverErrorMessage","response","errors","alertMessage","reason","toLowerCase","updateNoteError","$editingNote","_error$response2","isNewDiffComment","discussionId","mergeRequestId","ResolveService","toggleResolveForDiscussion","$targetNote","$noteEntityEl","$noteAvatar","$targetNoteBadge","revertNoteEditForm","getNodeToRender","replaceWith","checkContentToAllowEditing","isAllowed","isInViewport","$editForm","getEditFormSelector","$currentlyEditing","putEditFormInPlace","enable","one","noteElId","notesTr","$diffFile","removeBadgeEvent","badgeNumber","replyToDiscussionNote","cleanForm","replyLink","dataHolder","diffFileData","discussionID","link","$link","showReplyInput","toggleDiffNote","lineType","currentUsername","current_username","currentUserAvatar","current_user_avatar_url","currentUserFullname","current_user_fullname","clickEvent","newForm","$noteContainer","appendTo","forceShow","addForm","noteForm","replyButton","rowCssToAdd","nextRow","targetRow","hasNotes","lineTypeSelector","notesContentSelector","notesContent","isCurrentlyShown","isForced","showNow","prev","blurEvent","filename","_form$get","closetext","reopentext","reopenbtn","closebtn","savebtn","disable","$originalContentEl","originalContent","postUrl","targetId","targetType","open_link","close_link","updateCount","$container","GlSkeletonLoader","lines","prepend","fileHolder","syntaxHighlight","$retryButton","renderPlaceholderComponent","url","$errorContainer","$successContainer","renderDiffContent","$element","$closestSystemCommitList","siblings","$svgChevronUpElement","$svgChevronDownElement","alertParams","alert","_this$alert","dismiss","getNotesIds","isNewEntry","inArray","noteItem","gl","mrWidget","checkStatus","noteHtml","last","$item","isNodeTypeElement","getFormData","content","formData","serialize","formContent","formAction","formContentOriginal","hasQuickActions","test","stripQuickActions","getQuickActionDescription","availableQuickActions","tempFormContent","executedCommands","command","RegExp","commandDescription","createPlaceholderNote","uniqueId","isDiscussionNote","discussionClass","$tempNote","createPlaceholderSystemNote","_$form$get","$submitBtn","$closeBtn","isMainForm","isDiscussionForm","isDiscussionResolve","noteUniqueId","systemNoteUniqueId","$notesContainer","supportsQuickActions","_uniqueId","AjaxCache","GfmAutoComplete","dataSources","commands","res","notePosition","y","width","height","JSON","parse","addBadgeEvent","closestDiffFile","$noteBodyText","cachedNoteBodyText","$timeAgo","empty","loadingIconForLegacyJS","inline","size","$node","nodeType","Node","ELEMENT_NODE","dataEl","notesUrl","now","diffView","innerHTML","initialize","field","fallbackKey","lockVersion","getAttribute","isLocalStorageAvailable","AccessorUtilities","canUseLocalStorage","Array","isArray","lockVersionKey","restore","saveAction","save","addEventListener","fallbackText","newValue","originalValue","checked","parseBoolean","triggerInputEvents","inputEvent","Event","bubbles","cancelable","changeEvent","getSavedLockVersion","removeItem","removeEventListener","GlDropdownItem","MountingPortal","AbuseCategorySelector","reportAbuse","open","toggleDrawer","$event","initReportAbuse","provide","ReportAbuseDropdownItem"],"mappings":"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","file":"commons-pages.projects.commit.show-pages.projects.snippets.show-pages.snippets.show.6c74c802.chunk.js","sourcesContent":["/* eslint-disable class-methods-use-this, @gitlab/require-i18n-strings */\n\nimport { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';\nimport $ from 'jquery';\nimport { uniq, escape } from 'lodash';\nimport { getEmojiScoreWithIntent } from '~/emoji/utils';\nimport { scrollToElement } from '~/lib/utils/common_utils';\nimport * as Emoji from '~/emoji';\nimport { dispose, fixTitle } from '~/tooltips';\nimport { createAlert } from '~/alert';\nimport {\n  EMOJI_THUMBS_UP,\n  EMOJI_THUMBS_DOWN,\n  FREQUENTLY_USED_EMOJIS_STORAGE_KEY,\n} from '~/emoji/constants';\nimport axios from './lib/utils/axios_utils';\nimport { isInVueNoteablePage } from './lib/utils/dom_utils';\nimport { __ } from './locale';\n\nconst animationEndEventString = 'animationend webkitAnimationEnd MSAnimationEnd oAnimationEnd';\nconst transitionEndEventString = 'transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd';\n\nconst FROM_SENTENCE_REGEX = /(?:, and | and |, )/; // For separating lists produced by ruby's Array#toSentence\n\nconst categoryLabelMap = {\n  activity: 'Activity',\n  people: 'People',\n  nature: 'Nature',\n  food: 'Food',\n  travel: 'Travel',\n  objects: 'Objects',\n  symbols: 'Symbols',\n  flags: 'Flags',\n};\n\nconst IS_VISIBLE = 'is-visible';\nconst IS_RENDERED = 'is-rendered';\n\nexport class AwardsHandler {\n  constructor(emoji) {\n    this.emoji = emoji;\n    this.eventListeners = [];\n    this.toggleButtonSelector = '.js-add-award';\n    this.menuClass = 'js-award-emoji-menu';\n  }\n\n  bindEvents() {\n    const $parentEl = this.targetContainerEl ? $(this.targetContainerEl) : $(document);\n    // If the user shows intent let's pre-build the menu\n    this.registerEventListener(\n      'one',\n      $parentEl,\n      'mouseenter focus',\n      this.toggleButtonSelector,\n      'mouseenter focus',\n      () => {\n        const $menu = $(`.${this.menuClass}`);\n        if ($menu.length === 0) {\n          requestAnimationFrame(() => {\n            this.createEmojiMenu();\n          });\n        }\n      },\n    );\n    this.registerEventListener('on', $parentEl, 'click', this.toggleButtonSelector, (e) => {\n      e.stopPropagation();\n      e.preventDefault();\n      this.showEmojiMenu($(e.currentTarget));\n    });\n\n    this.registerEventListener('on', $('html'), 'click', (e) => {\n      const $target = $(e.target);\n      if (!$target.closest(`.${this.menuClass}`).length) {\n        $('.js-awards-block.current').removeClass('current');\n        if ($(`.${this.menuClass}`).is(':visible')) {\n          $(`${this.toggleButtonSelector}.is-active`).removeClass('is-active');\n          this.hideMenuElement($(`.${this.menuClass}`));\n        }\n      }\n    });\n\n    const emojiButtonSelector = `.js-awards-block .js-emoji-btn, .${this.menuClass} .js-emoji-btn`;\n    this.registerEventListener('on', $parentEl, 'click', emojiButtonSelector, (e) => {\n      e.preventDefault();\n      const $target = $(e.currentTarget);\n      const $glEmojiElement = $target.find('gl-emoji');\n      const $spriteIconElement = $target.find('.icon');\n      const emojiName = ($glEmojiElement.length ? $glEmojiElement : $spriteIconElement).data(\n        'name',\n      );\n\n      $target.closest('.js-awards-block').addClass('current');\n      this.addAward(this.getVotesBlock(), this.getAwardUrl(), emojiName);\n    });\n  }\n\n  registerEventListener(method = 'on', element, ...args) {\n    element[method].call(element, ...args);\n    this.eventListeners.push({\n      element,\n      args,\n    });\n  }\n\n  showEmojiMenu($addBtn) {\n    if ($addBtn.hasClass('js-note-emoji')) {\n      $addBtn.closest('.note').find('.js-awards-block').addClass('current');\n    } else {\n      $addBtn.closest('.js-awards-block').addClass('current');\n    }\n\n    const $menu = $(`.${this.menuClass}`);\n    if ($menu.length) {\n      if ($menu.is('.is-visible')) {\n        $addBtn.removeClass('is-active');\n        this.hideMenuElement($menu);\n        $('.js-emoji-menu-search').blur();\n      } else {\n        $addBtn.addClass('is-active');\n        this.positionMenu($menu, $addBtn);\n        this.showMenuElement($menu);\n        $('.js-emoji-menu-search').focus();\n      }\n    } else {\n      $addBtn.addClass('is-loading is-active');\n      this.createEmojiMenu(() => {\n        const $createdMenu = $(`.${this.menuClass}`);\n        $addBtn.removeClass('is-loading');\n        this.positionMenu($createdMenu, $addBtn);\n        return setTimeout(() => {\n          this.showMenuElement($createdMenu);\n          $('.js-emoji-menu-search').focus();\n        }, 200);\n      });\n    }\n  }\n\n  // Create the emoji menu with the first category of emojis.\n  // Then render the remaining categories of emojis one by one to avoid jank.\n  createEmojiMenu(callback) {\n    if (this.isCreatingEmojiMenu) {\n      return;\n    }\n    this.isCreatingEmojiMenu = true;\n\n    // Render the first category\n    const categoryMap = this.emoji.getEmojiCategoryMap();\n    const categoryNameKey = Object.keys(categoryMap)[0];\n    const emojisInCategory = categoryMap[categoryNameKey];\n    const firstCategory = this.renderCategory(categoryLabelMap[categoryNameKey], emojisInCategory);\n\n    // Render the frequently used\n    const frequentlyUsedEmojis = this.getFrequentlyUsedEmojis();\n    let frequentlyUsedCatgegory = '';\n    if (frequentlyUsedEmojis.length > 0) {\n      frequentlyUsedCatgegory = this.renderCategory('Frequently used', frequentlyUsedEmojis, {\n        frequentEmojis: true,\n      });\n    }\n\n    const emojiMenuMarkup = `\n      <div class=\"emoji-menu ${this.menuClass}\">\n        <input type=\"text\" name=\"emoji-menu-search\" value=\"\" class=\"js-emoji-menu-search emoji-search search-input form-control\" placeholder=\"Search emoji\" />\n\n        <div class=\"emoji-menu-content\">\n          ${frequentlyUsedCatgegory}\n          ${firstCategory}\n        </div>\n      </div>\n    `;\n\n    const targetEl = this.targetContainerEl ? this.targetContainerEl : document.body;\n    // eslint-disable-next-line no-unsanitized/method\n    targetEl.insertAdjacentHTML('beforeend', emojiMenuMarkup);\n\n    this.addRemainingEmojiMenuCategories();\n    this.setupSearch();\n    if (callback) {\n      callback();\n    }\n  }\n\n  addRemainingEmojiMenuCategories() {\n    if (this.isAddingRemainingEmojiMenuCategories) {\n      return;\n    }\n    this.isAddingRemainingEmojiMenuCategories = true;\n\n    const categoryMap = this.emoji.getEmojiCategoryMap();\n\n    // Avoid the jank and render the remaining categories separately\n    // This will take more time, but makes UI more responsive\n    const menu = document.querySelector(`.${this.menuClass}`);\n    const emojiContentElement = menu.querySelector('.emoji-menu-content');\n    const remainingCategories = Object.keys(categoryMap).slice(1);\n    const allCategoriesAddedPromise = remainingCategories.reduce(\n      (promiseChain, categoryNameKey) =>\n        promiseChain.then(\n          () =>\n            new Promise((resolve) => {\n              const emojisInCategory = categoryMap[categoryNameKey];\n              const categoryMarkup = this.renderCategory(\n                categoryLabelMap[categoryNameKey],\n                emojisInCategory,\n              );\n              requestAnimationFrame(() => {\n                // eslint-disable-next-line no-unsanitized/method\n                emojiContentElement.insertAdjacentHTML('beforeend', categoryMarkup);\n                resolve();\n              });\n            }),\n        ),\n      Promise.resolve(),\n    );\n\n    allCategoriesAddedPromise\n      .then(() => {\n        // Used for tests\n        // We check for the menu in case it was destroyed in the meantime\n        if (menu) {\n          menu.dispatchEvent(new CustomEvent('build-emoji-menu-finish'));\n        }\n      })\n      .catch((err) => {\n        emojiContentElement.insertAdjacentHTML(\n          'beforeend',\n          '<p>We encountered an error while adding the remaining categories</p>',\n        );\n        throw new Error(`Error occurred in addRemainingEmojiMenuCategories: ${err.message}`);\n      });\n  }\n\n  renderCategory(name, emojiList, opts = {}) {\n    return `\n      <h5 class=\"emoji-menu-title\">\n        ${escape(name)}\n      </h5>\n      <ul class=\"clearfix emoji-menu-list ${opts.frequentEmojis ? 'frequent-emojis' : ''}\">\n        ${emojiList\n          .map(\n            (emojiName) => `\n          <li class=\"emoji-menu-list-item\">\n            <button class=\"emoji-menu-btn text-center js-emoji-btn\" type=\"button\">\n              ${this.emoji.glEmojiTag(emojiName, {\n                sprite: true,\n              })}\n            </button>\n          </li>\n        `,\n          )\n          .join('\\n')}\n      </ul>\n    `;\n  }\n\n  positionMenu($menu, $addBtn) {\n    if (this.targetContainerEl) {\n      return $menu.css({\n        top: `${$addBtn.outerHeight()}px`,\n      });\n    }\n\n    const position = $addBtn.data('position');\n    // The menu could potentially be off-screen or in a hidden overflow element\n    // So we position the element absolute in the body\n    const css = {\n      top: `${$addBtn.offset().top + $addBtn.outerHeight()}px`,\n    };\n    // for xs screen we position the element on center\n    if (bp.getBreakpointSize() === 'xs' || bp.getBreakpointSize() === 'sm') {\n      css.left = '5%';\n    } else if (position === 'right') {\n      css.left = `${$addBtn.offset().left - $menu.outerWidth() + 20}px`;\n      $menu.addClass('is-aligned-right');\n    } else {\n      css.left = `${$addBtn.offset().left}px`;\n      $menu.removeClass('is-aligned-right');\n    }\n    return $menu.css(css);\n  }\n\n  // eslint-disable-next-line max-params\n  addAward(votesBlock, awardUrl, emoji, callback) {\n    const isMainAwardsBlock = votesBlock.closest('.js-noteable-awards').length;\n\n    if (isInVueNoteablePage() && !isMainAwardsBlock) {\n      const id = votesBlock.attr('id').replace('note_', '');\n\n      this.hideMenuElement($(`.${this.menuClass}`));\n\n      $(`${this.toggleButtonSelector}.is-active`).removeClass('is-active');\n      const toggleAwardEvent = new CustomEvent('toggleAward', {\n        detail: {\n          awardName: emoji,\n          noteId: id,\n        },\n      });\n\n      document.querySelector('.js-vue-notes-event').dispatchEvent(toggleAwardEvent);\n    }\n\n    const normalizedEmoji = this.emoji.normalizeEmojiName(emoji);\n    const $emojiButton = this.findEmojiIcon(votesBlock, normalizedEmoji).closest('button');\n\n    this.postEmoji($emojiButton, awardUrl, normalizedEmoji, () => {\n      this.addAwardToEmojiBar(votesBlock, normalizedEmoji);\n      return typeof callback === 'function' ? callback() : undefined;\n    });\n\n    this.hideMenuElement($(`.${this.menuClass}`));\n\n    return $(`${this.toggleButtonSelector}.is-active`).removeClass('is-active');\n  }\n\n  addAwardToEmojiBar(votesBlock, emoji) {\n    this.addEmojiToFrequentlyUsedList(emoji);\n    const normalizedEmoji = this.emoji.normalizeEmojiName(emoji);\n    const $emojiButton = this.findEmojiIcon(votesBlock, normalizedEmoji).closest('button');\n    if ($emojiButton.length > 0) {\n      if (this.isActive($emojiButton)) {\n        this.decrementCounter($emojiButton, normalizedEmoji);\n      } else {\n        const counter = $emojiButton.find('.js-counter');\n        counter.text(parseInt(counter.text(), 10) + 1);\n        $emojiButton.addClass('active');\n        this.addYouToUserList(votesBlock, normalizedEmoji);\n        this.animateEmoji($emojiButton);\n      }\n    } else {\n      votesBlock.removeClass('hidden');\n      this.createEmoji(votesBlock, normalizedEmoji);\n    }\n  }\n\n  getVotesBlock() {\n    if (isInVueNoteablePage()) {\n      const $el = $(`${this.toggleButtonSelector}.is-active`).closest('.note.timeline-entry');\n\n      if ($el.length) {\n        return $el;\n      }\n    }\n\n    const currentBlock = $('.js-awards-block.current');\n    let resultantVotesBlock = currentBlock;\n    if (currentBlock.length === 0) {\n      resultantVotesBlock = $('.js-awards-block').eq(0);\n    }\n\n    return resultantVotesBlock;\n  }\n\n  getAwardUrl() {\n    return this.getVotesBlock().data('awardUrl');\n  }\n\n  isActive($emojiButton) {\n    return $emojiButton.hasClass('active');\n  }\n\n  decrementCounter($emojiButton, emoji) {\n    const counter = $('.js-counter', $emojiButton);\n    const counterNumber = parseInt(counter.text(), 10);\n    if (counterNumber > 1) {\n      counter.text(counterNumber - 1);\n      this.removeYouFromUserList($emojiButton);\n    } else if (emoji === EMOJI_THUMBS_UP || emoji === EMOJI_THUMBS_DOWN) {\n      dispose($emojiButton);\n      counter.text('0');\n      this.removeYouFromUserList($emojiButton);\n      if ($emojiButton.parents('.note').length) {\n        this.removeEmoji($emojiButton);\n      }\n    } else {\n      this.removeEmoji($emojiButton);\n    }\n    return $emojiButton.removeClass('active');\n  }\n\n  removeEmoji($emojiButton) {\n    dispose($emojiButton);\n\n    $emojiButton.remove();\n    const $votesBlock = this.getVotesBlock();\n    if ($votesBlock.find('.js-emoji-btn').length === 0) {\n      $votesBlock.addClass('hidden');\n    }\n  }\n\n  getAwardTooltip($awardBlock) {\n    return $awardBlock.attr('data-original-title') || $awardBlock.attr('data-title') || '';\n  }\n\n  toSentence(list) {\n    let sentence;\n    if (list.length <= 2) {\n      sentence = list.join(' and ');\n    } else {\n      sentence = `${list.slice(0, -1).join(', ')}, and ${list[list.length - 1]}`;\n    }\n\n    return sentence;\n  }\n\n  removeYouFromUserList($emojiButton) {\n    const awardBlock = $emojiButton;\n    const originalTitle = this.getAwardTooltip(awardBlock);\n    const authors = originalTitle.split(FROM_SENTENCE_REGEX);\n    authors.splice(authors.indexOf('You'), 1);\n\n    awardBlock\n      .closest('.js-emoji-btn')\n      .removeData('title')\n      .removeAttr('data-title')\n      .removeAttr('data-original-title')\n      .attr('title', this.toSentence(authors));\n\n    fixTitle(awardBlock);\n\n    return awardBlock;\n  }\n\n  addYouToUserList(votesBlock, emoji) {\n    const awardBlock = this.findEmojiIcon(votesBlock, emoji).closest('button');\n    const origTitle = this.getAwardTooltip(awardBlock);\n    let users = [];\n    if (origTitle) {\n      users = origTitle.trim().split(FROM_SENTENCE_REGEX);\n    }\n    users.unshift('You');\n\n    awardBlock.attr('title', this.toSentence(users));\n\n    fixTitle(awardBlock);\n\n    return awardBlock;\n  }\n\n  createAwardButtonForVotesBlock(votesBlock, emojiName) {\n    const buttonHtml = `\n      <button class=\"gl-button btn btn-default award-control js-emoji-btn has-tooltip active\" title=\"You\">\n        ${this.emoji.glEmojiTag(emojiName)}\n        <span class=\"award-control-text js-counter\">1</span>\n      </button>\n    `;\n    const $emojiButton = $(buttonHtml);\n    $emojiButton\n      .insertBefore(votesBlock.find('.js-award-holder'))\n      .find('.emoji-icon')\n      .data('name', emojiName);\n    this.animateEmoji($emojiButton);\n\n    votesBlock.removeClass('current');\n  }\n\n  animateEmoji($emoji) {\n    const className = 'pulse animated once short';\n    $emoji.addClass(className);\n\n    this.registerEventListener('on', $emoji, animationEndEventString, (e) => {\n      $(e.currentTarget).removeClass(className);\n    });\n  }\n\n  createEmoji(votesBlock, emoji) {\n    if ($(`.${this.menuClass}`).length) {\n      this.createAwardButtonForVotesBlock(votesBlock, emoji);\n    }\n    this.createEmojiMenu(() => {\n      this.createAwardButtonForVotesBlock(votesBlock, emoji);\n    });\n  }\n\n  // eslint-disable-next-line max-params\n  postEmoji($emojiButton, awardUrl, emoji, callback) {\n    axios\n      .post(awardUrl, {\n        name: emoji,\n      })\n      .then(({ data }) => {\n        if (data.ok) {\n          callback();\n        }\n      })\n      .catch(() =>\n        createAlert({\n          message: __('Something went wrong on our end.'),\n        }),\n      );\n  }\n\n  findEmojiIcon(votesBlock, emoji) {\n    return votesBlock.find(`.js-emoji-btn [data-name=\"${emoji}\"]`);\n  }\n\n  scrollToAwards() {\n    scrollToElement('.awards', { offset: -110 });\n  }\n\n  addEmojiToFrequentlyUsedList(emoji) {\n    if (this.emoji.isEmojiNameValid(emoji)) {\n      this.frequentlyUsedEmojis = uniq(this.getFrequentlyUsedEmojis().concat(emoji));\n      localStorage.setItem(FREQUENTLY_USED_EMOJIS_STORAGE_KEY, this.frequentlyUsedEmojis.join(','));\n    }\n  }\n\n  getFrequentlyUsedEmojis() {\n    return (\n      this.frequentlyUsedEmojis ||\n      (() => {\n        const frequentlyUsedEmojis = uniq(\n          (localStorage.getItem(FREQUENTLY_USED_EMOJIS_STORAGE_KEY) || '').split(','),\n        );\n        this.frequentlyUsedEmojis = frequentlyUsedEmojis.filter((inputName) =>\n          this.emoji.isEmojiNameValid(inputName),\n        );\n\n        return this.frequentlyUsedEmojis;\n      })()\n    );\n  }\n\n  setupSearch() {\n    const $search = $('.js-emoji-menu-search');\n\n    this.registerEventListener('on', $search, 'input', (e) => {\n      const term = $(e.target).val().trim();\n      this.searchEmojis(term);\n    });\n\n    const $menu = $(`.${this.menuClass}`);\n    this.registerEventListener('on', $menu, transitionEndEventString, (e) => {\n      if (e.target === e.currentTarget) {\n        // Clear the search\n        this.searchEmojis('');\n      }\n    });\n  }\n\n  searchEmojis(term) {\n    const $search = $('.js-emoji-menu-search');\n    $search.val(term);\n\n    // Clean previous search results\n    $('ul.emoji-menu-search, h5.emoji-search-title').remove();\n    if (term.length > 0) {\n      // Generate a search result block\n      const h5 = $('<h5 class=\"emoji-search-title\"/>').text('Search results');\n      const foundEmojis = this.findMatchingEmojiElements(term).show();\n      const ul = $('<ul>').addClass('emoji-menu-list emoji-menu-search').append(foundEmojis);\n      $('.emoji-menu-content ul, .emoji-menu-content h5').hide();\n      $('.emoji-menu-content').append(h5).append(ul);\n    } else {\n      $('.emoji-menu-content').children().show();\n    }\n  }\n\n  getEmojiScore(emojis, value) {\n    const elem = $(value).find('[data-name]').get(0);\n    const emoji = emojis.filter((x) => x.emoji.name === elem.dataset.name)[0];\n    elem.dataset.score = emoji.score;\n\n    return emoji.score;\n  }\n\n  sortEmojiElements(emojis, $elements) {\n    const scores = new WeakMap();\n\n    return $elements.sort((a, b) => {\n      let aScore = scores.get(a);\n      let bScore = scores.get(b);\n\n      if (!aScore) {\n        aScore = this.getEmojiScore(emojis, a);\n        scores.set(a, aScore);\n      }\n\n      if (!bScore) {\n        bScore = this.getEmojiScore(emojis, b);\n        scores.set(b, bScore);\n      }\n\n      return aScore - bScore;\n    });\n  }\n\n  findMatchingEmojiElements(query) {\n    const matchingEmoji = this.emoji\n      .searchEmoji(query)\n      .map((x) => ({ ...x, score: getEmojiScoreWithIntent(x.emoji.name, x.score) }));\n    const matchingEmojiNames = matchingEmoji.map((x) => x.emoji.name);\n    const $emojiElements = $('.emoji-menu-list:not(.frequent-emojis) [data-name]');\n    const $matchingElements = $emojiElements.filter(\n      (i, elm) => matchingEmojiNames.indexOf(elm.dataset.name) >= 0,\n    );\n    return this.sortEmojiElements(matchingEmoji, $matchingElements.closest('li').clone());\n  }\n\n  /* showMenuElement and hideMenuElement are performance optimizations. We use\n   * opacity to show/hide the emoji menu, because we can animate it. But opacity\n   * leaves hidden elements in the render tree, which is unacceptable given the number\n   * of emoji elements in the emoji menu (5k+). To get the best of both worlds, we separately\n   * apply IS_RENDERED to add/remove the menu from the render tree and IS_VISIBLE to animate\n   * the menu being opened and closed. */\n\n  showMenuElement($emojiMenu) {\n    $emojiMenu.addClass(IS_RENDERED);\n\n    // enqueues animation as a microtask, so it begins ASAP once IS_RENDERED added\n    return Promise.resolve().then(() => $emojiMenu.addClass(IS_VISIBLE));\n  }\n\n  hideMenuElement($emojiMenu) {\n    $emojiMenu.on(transitionEndEventString, (e) => {\n      if (e.currentTarget === e.target) {\n        // eslint-disable-next-line @gitlab/no-global-event-off\n        $emojiMenu.removeClass(IS_RENDERED).off(transitionEndEventString);\n      }\n    });\n\n    $emojiMenu.removeClass(IS_VISIBLE);\n  }\n\n  destroy() {\n    this.eventListeners.forEach((entry) => {\n      entry.element.off.call(entry.element, ...entry.args);\n    });\n    $(`.${this.menuClass}`).remove();\n  }\n}\n\nlet awardsHandlerPromise = null;\nexport default function loadAwardsHandler(reload = false) {\n  if (!awardsHandlerPromise || reload) {\n    awardsHandlerPromise = Emoji.initEmojiMap().then(() => {\n      const awardsHandler = new AwardsHandler(Emoji);\n      awardsHandler.bindEvents();\n      return awardsHandler;\n    });\n  }\n  return awardsHandlerPromise;\n}\n","import { s__ } from '~/locale';\n\nexport const CATEGORY_OPTIONS = [\n  { value: 'spam', text: s__(\"ReportAbuse|They're posting spam.\") },\n  { value: 'offensive', text: s__(\"ReportAbuse|They're being offensive or abusive.\") },\n  { value: 'phishing', text: s__(\"ReportAbuse|They're phishing.\") },\n  { value: 'crypto', text: s__(\"ReportAbuse|They're crypto mining.\") },\n  {\n    value: 'credentials',\n    text: s__(\"ReportAbuse|They're posting personal information or credentials.\"),\n  },\n  { value: 'copyright', text: s__(\"ReportAbuse|They're violating a copyright or trademark.\") },\n  { value: 'malware', text: s__(\"ReportAbuse|They're posting malware.\") },\n  { value: 'other', text: s__('ReportAbuse|Something else.') },\n];\n","/**\n * This function is like `arrayIncludes` except that it accepts a comparator.\n *\n * @private\n * @param {Array} [array] The array to inspect.\n * @param {*} target The value to search for.\n * @param {Function} comparator The comparator invoked per element.\n * @returns {boolean} Returns `true` if `target` is found, else `false`.\n */\nfunction arrayIncludesWith(array, value, comparator) {\n  var index = -1,\n      length = array == null ? 0 : array.length;\n\n  while (++index < length) {\n    if (comparator(value, array[index])) {\n      return true;\n    }\n  }\n  return false;\n}\n\nmodule.exports = arrayIncludesWith;\n","var Set = require('./_Set'),\n    noop = require('./noop'),\n    setToArray = require('./_setToArray');\n\n/** Used as references for various `Number` constants. */\nvar INFINITY = 1 / 0;\n\n/**\n * Creates a set object of `values`.\n *\n * @private\n * @param {Array} values The values to add to the set.\n * @returns {Object} Returns the new set.\n */\nvar createSet = !(Set && (1 / setToArray(new Set([,-0]))[1]) == INFINITY) ? noop : function(values) {\n  return new Set(values);\n};\n\nmodule.exports = createSet;\n","import { __, s__ } from '~/locale';\n\nexport const COMMENT_FORM = {\n  GENERIC_UNSUBMITTABLE_NETWORK: __(\n    'Your comment could not be submitted! Please check your network connection and try again.',\n  ),\n  error: __('Comment could not be submitted: %{reason}.'),\n  note: __('Note'),\n  comment: __('Comment'),\n  wiki: __('Wiki'),\n  internalComment: __('Add internal note'),\n  issue: __('issue'),\n  startThread: __('Start thread'),\n  startInternalThread: __('Start internal thread'),\n  mergeRequest: __('merge request'),\n  epic: __('epic'),\n  bodyPlaceholder: __('Write a comment or drag your files here…'),\n  bodyPlaceholderInternal: __('Write an internal note or drag your files here…'),\n  internal: s__('Notes|Make this an internal note'),\n  internalVisibility: s__(\n    'Notes|Internal notes are only visible to members with the role of Planner or higher',\n  ),\n  discussionThatNeedsResolution: __(\n    'Discuss a specific suggestion or question that needs to be resolved.',\n  ),\n  internalDiscussionThatNeedsResolution: __(\n    'Discuss a specific suggestion or question internally that needs to be resolved.',\n  ),\n  discussion: __('Discuss a specific suggestion or question.'),\n  internalDiscussion: __('Discuss a specific suggestion or question internally.'),\n  actionButtonWithNote: __('%{actionText} & %{openOrClose} %{noteable}'),\n  actionButton: {\n    withNote: {\n      reopen: __('%{actionText} & reopen %{noteable}'),\n      close: __('%{actionText} & close %{noteable}'),\n    },\n    withoutNote: {\n      reopen: __('Reopen %{noteable}'),\n      close: __('Close %{noteable}'),\n    },\n  },\n  submitButton: {\n    startThread: __('Start thread'),\n    startInternalThread: __('Start internal thread'),\n    comment: __('Comment'),\n    internalComment: __('Add internal note'),\n    commentHelp: __('Add a general comment to this %{noteableDisplayName}.'),\n    internalCommentHelp: __('Add a confidential internal note to this %{noteableDisplayName}.'),\n  },\n  addToReviewButton: {\n    saveThread: __('Add thread to review'),\n    saveComment: __('Add comment to review'),\n  },\n  addToReview: __('Add to review'),\n  startReview: __('Start review'),\n  addCommentNow: __('Add comment now'),\n  addThreadNow: __('Add thread now'),\n};\n\nexport const EDITED_TEXT = {\n  actionWithAuthor: __('%{actionText} %{actionDetail} %{timeago} by %{author}'),\n  actionWithoutAuthor: __('%{actionText} %{actionDetail}'),\n};\n\nexport const UPDATE_COMMENT_FORM = {\n  error: __('Comment could not be updated: %{reason}.'),\n  defaultError: __('Something went wrong while editing your comment. Please try again.'),\n};\n","var render = function render(){var _vm=this,_c=_vm._self._c;return _c('gl-drawer',{attrs:{\"header-height\":_vm.getDrawerHeaderHeight,\"z-index\":300,\"open\":_vm.showDrawer && _vm.mounted},on:{\"close\":_vm.closeDrawer},scopedSlots:_vm._u([{key:\"title\",fn:function(){return [_c('h2',{staticClass:\"gl-mb-0 gl-mt-0 gl-text-size-h2 gl-leading-24\",attrs:{\"data-testid\":\"category-drawer-title\"}},[_vm._v(\"\\n      \"+_vm._s(_vm.$options.i18n.title)+\"\\n    \")])]},proxy:true},{key:\"default\",fn:function(){return [_c('gl-form',{staticClass:\"gl-text-left\",attrs:{\"action\":_vm.reportAbusePath,\"method\":\"post\"}},[_c('input',{attrs:{\"type\":\"hidden\",\"name\":\"authenticity_token\"},domProps:{\"value\":_vm.$options.csrf.token}}),_vm._v(\" \"),_c('input',{attrs:{\"type\":\"hidden\",\"name\":\"user_id\",\"data-testid\":\"input-user-id\"},domProps:{\"value\":_vm.reportedUserId}}),_vm._v(\" \"),_c('input',{attrs:{\"type\":\"hidden\",\"name\":\"abuse_report[reported_from_url]\",\"data-testid\":\"input-referer\"},domProps:{\"value\":_vm.reportedFromUrl}}),_vm._v(\" \"),_c('gl-form-group',{attrs:{\"label\":_vm.$options.i18n.label,\"label-class\":\"gl-text-default\"}},[_c('gl-form-radio-group',{attrs:{\"options\":_vm.$options.CATEGORY_OPTIONS,\"name\":\"abuse_report[category]\",\"required\":\"\"},model:{value:(_vm.selected),callback:function ($$v) {_vm.selected=$$v},expression:\"selected\"}})],1),_vm._v(\" \"),_c('gl-button',{attrs:{\"type\":\"submit\",\"variant\":\"confirm\",\"data-testid\":\"submit-form-button\"}},[_vm._v(\"\\n        \"+_vm._s(_vm.$options.i18n.next)+\"\\n      \")])],1)]},proxy:true}])})\n}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","import mod from \"-!../../../../../node_modules/thread-loader/dist/cjs.js??ref--13-0!../../../../../node_modules/babel-loader/lib/index.js??ref--13-1!../../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./abuse_category_selector.vue?vue&type=script&lang=js\"; export default mod; export * from \"-!../../../../../node_modules/thread-loader/dist/cjs.js??ref--13-0!../../../../../node_modules/babel-loader/lib/index.js??ref--13-1!../../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./abuse_category_selector.vue?vue&type=script&lang=js\"","<script>\nimport { GlButton, GlDrawer, GlForm, GlFormGroup, GlFormRadioGroup } from '@gitlab/ui';\nimport { getContentWrapperHeight } from '~/lib/utils/dom_utils';\nimport { s__, __ } from '~/locale';\nimport csrf from '~/lib/utils/csrf';\nimport { CATEGORY_OPTIONS } from '~/abuse_reports/components/constants';\n\nexport default {\n  name: 'AbuseCategorySelector',\n  csrf,\n  components: {\n    GlButton,\n    GlDrawer,\n    GlForm,\n    GlFormGroup,\n    GlFormRadioGroup,\n  },\n  inject: {\n    reportAbusePath: {\n      default: '',\n    },\n  },\n  props: {\n    reportedUserId: {\n      type: Number,\n      required: true,\n    },\n    reportedFromUrl: {\n      type: String,\n      required: false,\n      default: '',\n    },\n    showDrawer: {\n      type: Boolean,\n      required: true,\n    },\n  },\n  i18n: {\n    title: __('Report abuse to administrator'),\n    close: __('Close'),\n    label: s__('ReportAbuse|Why are you reporting this user?'),\n    next: __('Next'),\n  },\n  CATEGORY_OPTIONS,\n  data() {\n    return {\n      selected: '',\n      mounted: false,\n    };\n  },\n  computed: {\n    getDrawerHeaderHeight() {\n      // avoid calculating this in advance because it causes layout thrashing\n      // https://gitlab.com/gitlab-org/gitlab/-/issues/331172#note_1269378396\n      if (!this.showDrawer) return '0';\n      return getContentWrapperHeight();\n    },\n  },\n  mounted() {\n    // this is required for the component to properly animate\n    // when it is shown with v-if\n    this.mounted = true;\n  },\n  methods: {\n    closeDrawer() {\n      this.$emit('close-drawer');\n    },\n  },\n};\n</script>\n<template>\n  <gl-drawer\n    :header-height=\"getDrawerHeaderHeight\"\n    :z-index=\"300\"\n    :open=\"showDrawer && mounted\"\n    @close=\"closeDrawer\"\n  >\n    <template #title>\n      <h2 class=\"gl-mb-0 gl-mt-0 gl-text-size-h2 gl-leading-24\" data-testid=\"category-drawer-title\">\n        {{ $options.i18n.title }}\n      </h2>\n    </template>\n    <template #default>\n      <gl-form :action=\"reportAbusePath\" method=\"post\" class=\"gl-text-left\">\n        <input :value=\"$options.csrf.token\" type=\"hidden\" name=\"authenticity_token\" />\n\n        <input type=\"hidden\" name=\"user_id\" :value=\"reportedUserId\" data-testid=\"input-user-id\" />\n        <input\n          type=\"hidden\"\n          name=\"abuse_report[reported_from_url]\"\n          :value=\"reportedFromUrl\"\n          data-testid=\"input-referer\"\n        />\n\n        <gl-form-group :label=\"$options.i18n.label\" label-class=\"gl-text-default\">\n          <gl-form-radio-group\n            v-model=\"selected\"\n            :options=\"$options.CATEGORY_OPTIONS\"\n            name=\"abuse_report[category]\"\n            required\n          />\n        </gl-form-group>\n\n        <gl-button type=\"submit\" variant=\"confirm\" data-testid=\"submit-form-button\">\n          {{ $options.i18n.next }}\n        </gl-button>\n      </gl-form>\n    </template>\n  </gl-drawer>\n</template>\n","import { render, staticRenderFns } from \"./abuse_category_selector.vue?vue&type=template&id=4bfeb9fb\"\nimport script from \"./abuse_category_selector.vue?vue&type=script&lang=js\"\nexport * from \"./abuse_category_selector.vue?vue&type=script&lang=js\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n  script,\n  render,\n  staticRenderFns,\n  false,\n  null,\n  null,\n  null\n  \n)\n\nexport default component.exports","var render = function render(){var _vm=this,_c=_vm._self._c;return _c('gl-button-group',{staticClass:\"js-comment-button js-comment-submit-button comment-type-dropdown gl-mb-3 gl-w-full sm:gl-mb-0 sm:gl-w-auto\",attrs:{\"data-track-label\":_vm.trackingLabel,\"data-track-action\":\"click_button\",\"data-testid\":\"comment-button\"}},[_c('gl-button',{attrs:{\"type\":\"submit\",\"variant\":\"confirm\",\"disabled\":_vm.disabled},on:{\"click\":_vm.handleClick}},[_vm._v(\"\\n    \"+_vm._s(_vm.commentButtonTitle)+\"\\n  \")]),_vm._v(\" \"),_c('gl-collapsible-listbox',{attrs:{\"variant\":\"confirm\",\"text-sr-only\":\"\",\"toggle-text\":_vm.$options.i18n.toggleSrText,\"disabled\":_vm.disabled,\"items\":_vm.dropdownItems,\"selected\":_vm.noteType},on:{\"select\":_vm.setNoteType},scopedSlots:_vm._u([{key:\"list-item\",fn:function({ item }){return [_c('div',{attrs:{\"data-testid\":item.testid}},[_c('strong',[_vm._v(_vm._s(item.text))]),_vm._v(\" \"),_c('p',{staticClass:\"gl-m-0\"},[_vm._v(_vm._s(item.description))])])]}}])})],1)\n}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","import mod from \"-!../../../../../node_modules/thread-loader/dist/cjs.js??ref--13-0!../../../../../node_modules/babel-loader/lib/index.js??ref--13-1!../../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./comment_type_dropdown.vue?vue&type=script&lang=js\"; export default mod; export * from \"-!../../../../../node_modules/thread-loader/dist/cjs.js??ref--13-0!../../../../../node_modules/babel-loader/lib/index.js??ref--13-1!../../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./comment_type_dropdown.vue?vue&type=script&lang=js\"","<script>\nimport { GlButtonGroup, GlButton, GlCollapsibleListbox } from '@gitlab/ui';\n\nimport { sprintf, __ } from '~/locale';\nimport { COMMENT_FORM } from '~/notes/i18n';\nimport * as constants from '../constants';\n\nexport default {\n  name: 'CommentTypeDropdown',\n  i18n: {\n    ...COMMENT_FORM,\n    toggleSrText: __('Comment type'),\n  },\n  components: {\n    GlButtonGroup,\n    GlButton,\n    GlCollapsibleListbox,\n  },\n  model: {\n    prop: 'noteType',\n    event: 'change',\n  },\n  props: {\n    disabled: {\n      type: Boolean,\n      required: false,\n      default: false,\n    },\n    trackingLabel: {\n      type: String,\n      required: false,\n      default: undefined,\n    },\n    discussionsRequireResolution: {\n      type: Boolean,\n      required: false,\n      default: false,\n    },\n    isInternalNote: {\n      type: Boolean,\n      required: false,\n      default: false,\n    },\n    noteableDisplayName: {\n      type: String,\n      required: true,\n    },\n    noteType: {\n      type: String,\n      required: true,\n    },\n    isReviewDropdown: {\n      type: Boolean,\n      required: false,\n      default: false,\n    },\n  },\n  computed: {\n    isNoteTypeComment() {\n      return this.noteType === constants.COMMENT;\n    },\n    isNoteTypeDiscussion() {\n      return this.noteType === constants.DISCUSSION;\n    },\n    dropdownCommentButtonTitle() {\n      const { comment, internalComment } = this.$options.i18n.submitButton;\n\n      return this.isInternalNote ? internalComment : comment;\n    },\n    dropdownStartThreadButtonTitle() {\n      const { startThread, startInternalThread } = this.$options.i18n.submitButton;\n\n      return this.isInternalNote ? startInternalThread : startThread;\n    },\n    commentButtonTitle() {\n      const { comment, internalComment, startThread, startInternalThread } = this.$options.i18n;\n      const { saveThread, saveComment } = this.$options.i18n.addToReviewButton;\n\n      if (this.isInternalNote) {\n        return this.noteType === constants.COMMENT ? internalComment : startInternalThread;\n      }\n\n      if (this.isReviewDropdown) {\n        return this.noteType === constants.COMMENT ? saveComment : saveThread;\n      }\n\n      return this.noteType === constants.COMMENT ? comment : startThread;\n    },\n    startDiscussionDescription() {\n      const {\n        discussionThatNeedsResolution,\n        internalDiscussionThatNeedsResolution,\n        discussion,\n        internalDiscussion,\n      } = this.$options.i18n;\n\n      if (this.isInternalNote) {\n        return this.discussionsRequireResolution\n          ? internalDiscussionThatNeedsResolution\n          : internalDiscussion;\n      }\n      return this.discussionsRequireResolution ? discussionThatNeedsResolution : discussion;\n    },\n    commentDescription() {\n      const { commentHelp, internalCommentHelp } = this.$options.i18n.submitButton;\n\n      return sprintf(this.isInternalNote ? internalCommentHelp : commentHelp, {\n        noteableDisplayName: this.noteableDisplayName,\n      });\n    },\n    dropdownItems() {\n      return [\n        {\n          text: this.dropdownCommentButtonTitle,\n          description: this.commentDescription,\n          value: constants.COMMENT,\n        },\n        {\n          text: this.dropdownStartThreadButtonTitle,\n          description: this.startDiscussionDescription,\n          value: constants.DISCUSSION,\n          testid: 'discussion-menu-item',\n        },\n      ];\n    },\n  },\n  methods: {\n    handleClick() {\n      this.$emit('click');\n    },\n    setNoteType(value) {\n      this.$emit('change', value);\n    },\n  },\n};\n</script>\n\n<template>\n  <gl-button-group\n    class=\"js-comment-button js-comment-submit-button comment-type-dropdown gl-mb-3 gl-w-full sm:gl-mb-0 sm:gl-w-auto\"\n    :data-track-label=\"trackingLabel\"\n    data-track-action=\"click_button\"\n    data-testid=\"comment-button\"\n  >\n    <gl-button type=\"submit\" variant=\"confirm\" :disabled=\"disabled\" @click=\"handleClick\">\n      {{ commentButtonTitle }}\n    </gl-button>\n    <gl-collapsible-listbox\n      variant=\"confirm\"\n      text-sr-only\n      :toggle-text=\"$options.i18n.toggleSrText\"\n      :disabled=\"disabled\"\n      :items=\"dropdownItems\"\n      :selected=\"noteType\"\n      @select=\"setNoteType\"\n    >\n      <template #list-item=\"{ item }\">\n        <div :data-testid=\"item.testid\">\n          <strong>{{ item.text }}</strong>\n          <p class=\"gl-m-0\">{{ item.description }}</p>\n        </div>\n      </template>\n    </gl-collapsible-listbox>\n  </gl-button-group>\n</template>\n","import { render, staticRenderFns } from \"./comment_type_dropdown.vue?vue&type=template&id=63ac1d67\"\nimport script from \"./comment_type_dropdown.vue?vue&type=script&lang=js\"\nexport * from \"./comment_type_dropdown.vue?vue&type=script&lang=js\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n  script,\n  render,\n  staticRenderFns,\n  false,\n  null,\n  null,\n  null\n  \n)\n\nexport default component.exports","var baseUniq = require('./_baseUniq');\n\n/**\n * Creates a duplicate-free version of an array, using\n * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * for equality comparisons, in which only the first occurrence of each element\n * is kept. The order of result values is determined by the order they occur\n * in the array.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Array\n * @param {Array} array The array to inspect.\n * @returns {Array} Returns the new duplicate free array.\n * @example\n *\n * _.uniq([2, 1, 2]);\n * // => [2, 1]\n */\nfunction uniq(array) {\n  return (array && array.length) ? baseUniq(array) : [];\n}\n\nmodule.exports = uniq;\n","var SetCache = require('./_SetCache'),\n    arrayIncludes = require('./_arrayIncludes'),\n    arrayIncludesWith = require('./_arrayIncludesWith'),\n    cacheHas = require('./_cacheHas'),\n    createSet = require('./_createSet'),\n    setToArray = require('./_setToArray');\n\n/** Used as the size to enable large array optimizations. */\nvar LARGE_ARRAY_SIZE = 200;\n\n/**\n * The base implementation of `_.uniqBy` without support for iteratee shorthands.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {Function} [iteratee] The iteratee invoked per element.\n * @param {Function} [comparator] The comparator invoked per element.\n * @returns {Array} Returns the new duplicate free array.\n */\nfunction baseUniq(array, iteratee, comparator) {\n  var index = -1,\n      includes = arrayIncludes,\n      length = array.length,\n      isCommon = true,\n      result = [],\n      seen = result;\n\n  if (comparator) {\n    isCommon = false;\n    includes = arrayIncludesWith;\n  }\n  else if (length >= LARGE_ARRAY_SIZE) {\n    var set = iteratee ? null : createSet(array);\n    if (set) {\n      return setToArray(set);\n    }\n    isCommon = false;\n    includes = cacheHas;\n    seen = new SetCache;\n  }\n  else {\n    seen = iteratee ? [] : result;\n  }\n  outer:\n  while (++index < length) {\n    var value = array[index],\n        computed = iteratee ? iteratee(value) : value;\n\n    value = (comparator || value !== 0) ? value : 0;\n    if (isCommon && computed === computed) {\n      var seenIndex = seen.length;\n      while (seenIndex--) {\n        if (seen[seenIndex] === computed) {\n          continue outer;\n        }\n      }\n      if (iteratee) {\n        seen.push(computed);\n      }\n      result.push(value);\n    }\n    else if (!includes(seen, computed, comparator)) {\n      if (seen !== result) {\n        seen.push(computed);\n      }\n      result.push(value);\n    }\n  }\n  return result;\n}\n\nmodule.exports = baseUniq;\n","/* eslint-disable camelcase,\nno-unused-expressions, default-case,\nconsistent-return, no-param-reassign,\nno-shadow, no-useless-escape,\nclass-methods-use-this */\n\n/* global ResolveService */\n\n/*\ndeprecated_notes_spec.js is the spec for the legacy, jQuery notes application. It has nothing to do with the new, fancy Vue notes app.\n */\n\nimport { GlSkeletonLoader } from '@gitlab/ui';\nimport Autosize from 'autosize';\nimport $ from 'jquery';\nimport { escape, uniqueId } from 'lodash';\nimport Vue from 'vue';\nimport { renderGFM } from '~/behaviors/markdown/render_gfm';\nimport { createAlert, VARIANT_INFO } from '~/alert';\nimport { sanitize } from '~/lib/dompurify';\nimport '~/lib/utils/jquery_at_who';\nimport AjaxCache from '~/lib/utils/ajax_cache';\nimport { loadingIconForLegacyJS } from '~/loading_icon_for_legacy_js';\nimport syntaxHighlight from '~/syntax_highlight';\nimport CommentTypeDropdown from '~/notes/components/comment_type_dropdown.vue';\nimport * as constants from '~/notes/constants';\nimport { confirmAction } from '~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal';\nimport { COMMENT_FORM, UPDATE_COMMENT_FORM } from '~/notes/i18n';\nimport Autosave from './autosave';\nimport loadAwardsHandler from './awards_handler';\nimport { defaultAutocompleteConfig } from './gfm_auto_complete';\nimport GLForm from './gl_form';\nimport axios from './lib/utils/axios_utils';\nimport {\n  getCookie,\n  isInViewport,\n  getPagePath,\n  scrollToElement,\n  isModifierKey,\n  isInMRPage,\n} from './lib/utils/common_utils';\nimport { localTimeAgo } from './lib/utils/datetime_utility';\nimport { getLocationHash } from './lib/utils/url_utility';\nimport { sprintf, s__, __ } from './locale';\nimport TaskList from './task_list';\n\nwindow.autosize = Autosize;\n\nfunction normalizeNewlines(str) {\n  return str.replace(/\\r\\n/g, '\\n');\n}\n\nconst REGEX_QUICK_ACTIONS = /^\\/\\w+.*$/gm;\n\nexport default class Notes {\n  // eslint-disable-next-line max-params\n  static initialize(notes_url, last_fetched_at, view, enableGFM) {\n    if (!this.instance) {\n      this.instance = new Notes(notes_url, last_fetched_at, view, enableGFM);\n    }\n  }\n\n  static getInstance() {\n    return this.instance;\n  }\n\n  // eslint-disable-next-line max-params\n  constructor(notes_url, last_fetched_at, view, enableGFM = defaultAutocompleteConfig) {\n    this.updateTargetButtons = this.updateTargetButtons.bind(this);\n    this.updateComment = this.updateComment.bind(this);\n    this.visibilityChange = this.visibilityChange.bind(this);\n    this.cancelDiscussionForm = this.cancelDiscussionForm.bind(this);\n    this.onAddDiffNote = this.onAddDiffNote.bind(this);\n    this.onAddImageDiffNote = this.onAddImageDiffNote.bind(this);\n    this.setupDiscussionNoteForm = this.setupDiscussionNoteForm.bind(this);\n    this.onReplyToDiscussionNote = this.onReplyToDiscussionNote.bind(this);\n    this.removeNote = this.removeNote.bind(this);\n    this.cancelEdit = this.cancelEdit.bind(this);\n    this.updateNote = this.updateNote.bind(this);\n    this.addDiscussionNote = this.addDiscussionNote.bind(this);\n    this.addNoteError = this.addNoteError.bind(this);\n    this.addNote = this.addNote.bind(this);\n    this.resetMainTargetForm = this.resetMainTargetForm.bind(this);\n    this.refresh = this.refresh.bind(this);\n    this.keydownNoteText = this.keydownNoteText.bind(this);\n    this.toggleCommitList = this.toggleCommitList.bind(this);\n    this.postComment = this.postComment.bind(this);\n    this.clearAlertWrapper = this.clearAlert.bind(this);\n    this.onHashChange = this.onHashChange.bind(this);\n    this.note_ids = [];\n\n    this.notes_url = notes_url;\n    this.enableGFM = enableGFM;\n    // Used to keep track of updated notes while people are editing things\n    this.updatedNotesTrackingMap = {};\n    this.last_fetched_at = last_fetched_at;\n    this.noteable_url = document.URL;\n    this.notesCountBadge ||\n      (this.notesCountBadge = $('.issuable-details').find('.notes-tab .badge'));\n    this.basePollingInterval = 15000;\n    this.maxPollingSteps = 4;\n\n    this.$wrapperEl = isInMRPage() ? $(document).find('.diffs') : $(document);\n    this.cleanBinding();\n    this.addBinding();\n    this.setPollingInterval();\n    this.setupMainTargetNoteForm(enableGFM);\n    this.taskList = new TaskList({\n      dataType: 'note',\n      fieldName: 'note',\n      selector: '.notes',\n    });\n    this.setViewType(view);\n\n    // We are in the merge requests page so we need another edit form for Changes tab\n    if (getPagePath(1) === 'merge_requests') {\n      $('.note-edit-form').clone().addClass('mr-note-edit-form').insertAfter('.note-edit-form');\n    }\n\n    const hash = getLocationHash();\n    const $anchor = hash && document.getElementById(hash);\n\n    if ($anchor) {\n      this.loadLazyDiff({ currentTarget: $anchor });\n    }\n  }\n\n  setViewType(view) {\n    this.view = getCookie('diff_view') || view;\n  }\n\n  addBinding() {\n    // Edit note link\n    this.$wrapperEl.on('click', '.js-note-edit', this.showEditForm.bind(this));\n    this.$wrapperEl.on('click', '.note-edit-cancel', this.cancelEdit);\n    // Reopen and close actions for Issue/MR combined with note form submit\n    this.$wrapperEl.on(\n      'click',\n      // this oddly written selector needs to match the old style (button with class) as\n      // well as the new DOM styling from the Vue-based note form\n      'button.js-comment-submit-button, .js-comment-submit-button > button:first-child',\n      this.postComment,\n    );\n    this.$wrapperEl.on('click', '.js-comment-save-button', this.updateComment);\n    this.$wrapperEl.on('keyup input', '.js-note-text', this.updateTargetButtons);\n    // resolve a discussion\n    this.$wrapperEl.on('click', '.js-comment-resolve-button', this.postComment);\n    // remove a note (in general)\n    this.$wrapperEl.on('ajax:success', '.js-note-delete', this.removeNote);\n    // delete note attachment\n    this.$wrapperEl.on('click', '.js-note-attachment-delete', this.removeAttachment);\n    // update the file name when an attachment is selected\n    this.$wrapperEl.on('change', '.js-note-attachment-input', this.updateFormAttachment);\n    // reply to diff/discussion notes\n    this.$wrapperEl.on('focus', '.js-discussion-reply-button', this.onReplyToDiscussionNote);\n    // add diff note\n    this.$wrapperEl.on('click', '.js-add-diff-note-button', this.onAddDiffNote);\n    // add diff note for images\n    this.$wrapperEl.on('click', '.js-add-image-diff-note-button', this.onAddImageDiffNote);\n    // hide diff note form\n    this.$wrapperEl.on('click', '.js-close-discussion-note-form', this.cancelDiscussionForm);\n    // toggle commit list\n    this.$wrapperEl.on('click', '.system-note-commit-list-toggler', this.toggleCommitList);\n\n    this.$wrapperEl.on('click', '.js-toggle-lazy-diff', this.loadLazyDiff);\n    this.$wrapperEl.on(\n      'click',\n      '.js-toggle-lazy-diff-retry-button',\n      this.onClickRetryLazyLoad.bind(this),\n    );\n\n    // fetch notes when tab becomes visible\n    this.$wrapperEl.on('visibilitychange', this.visibilityChange);\n    // when issue status changes, we need to refresh data\n    this.$wrapperEl.on('issuable:change', this.refresh);\n    // ajax:events that happen on Form when actions like Reopen, Close are performed on Issues and MRs.\n    this.$wrapperEl.on('ajax:success', '.js-main-target-form', this.addNote);\n    this.$wrapperEl.on('ajax:success', '.js-discussion-note-form', this.addDiscussionNote);\n    this.$wrapperEl.on('ajax:success', '.js-main-target-form', this.resetMainTargetForm);\n    this.$wrapperEl.on(\n      'ajax:complete',\n      '.js-main-target-form',\n      this.reenableTargetFormSubmitButton,\n    );\n    // when a key is clicked on the notes\n    this.$wrapperEl.on('keydown', '.js-note-text', this.keydownNoteText);\n    // When the URL fragment/hash has changed, `#note_xxx`\n    $(window).on('hashchange', this.onHashChange);\n  }\n\n  cleanBinding() {\n    this.$wrapperEl.off('click', '.js-note-edit');\n    this.$wrapperEl.off('click', '.note-edit-cancel');\n    this.$wrapperEl.off('ajax:success', '.js-note-delete');\n    this.$wrapperEl.off('click', '.js-note-attachment-delete');\n    this.$wrapperEl.off('click', '.js-discussion-reply-button');\n    this.$wrapperEl.off('click', '.js-add-diff-note-button');\n    this.$wrapperEl.off('click', '.js-add-image-diff-note-button');\n    // eslint-disable-next-line @gitlab/no-global-event-off\n    this.$wrapperEl.off('visibilitychange');\n    this.$wrapperEl.off('keyup input', '.js-note-text');\n    this.$wrapperEl.off('click', '.js-note-target-reopen');\n    this.$wrapperEl.off('click', '.js-note-target-close');\n    this.$wrapperEl.off('keydown', '.js-note-text');\n    this.$wrapperEl.off('click', '.js-comment-resolve-button');\n    this.$wrapperEl.off('click', '.system-note-commit-list-toggler');\n    this.$wrapperEl.off('click', '.js-toggle-lazy-diff');\n    this.$wrapperEl.off('click', '.js-toggle-lazy-diff-retry-button');\n    this.$wrapperEl.off('ajax:success', '.js-main-target-form');\n    this.$wrapperEl.off('ajax:success', '.js-discussion-note-form');\n    this.$wrapperEl.off('ajax:complete', '.js-main-target-form');\n    $(window).off('hashchange', this.onHashChange);\n  }\n\n  static initCommentTypeToggle(form) {\n    const el = form.querySelector('.js-comment-type-dropdown');\n    const { noteableName } = el.dataset;\n    const noteTypeInput = form.querySelector('#note_type');\n    const formHasContent = form.querySelector('.js-note-text').value.trim().length > 0;\n\n    form.commentTypeComponent = new Vue({\n      el,\n      data() {\n        return {\n          noteType: constants.COMMENT,\n          disabled: !formHasContent,\n        };\n      },\n      render(createElement) {\n        return createElement(CommentTypeDropdown, {\n          props: {\n            noteType: this.noteType,\n            noteableDisplayName: noteableName,\n            disabled: this.disabled,\n          },\n          on: {\n            change: (arg) => {\n              this.noteType = arg;\n              if (this.noteType === constants.DISCUSSION) {\n                noteTypeInput.value = constants.DISCUSSION_NOTE;\n              } else {\n                noteTypeInput.value = '';\n              }\n            },\n          },\n        });\n      },\n    });\n  }\n\n  async keydownNoteText(e) {\n    let discussionNoteForm;\n    let editNote;\n    let myLastNote;\n    let myLastNoteEditBtn;\n    let newText;\n    let originalText;\n\n    if (isModifierKey(e)) {\n      return;\n    }\n\n    const $textarea = $(e.target);\n    // Edit previous note when UP arrow is hit\n    switch (e.which) {\n      case 38:\n        if ($textarea.val() !== '') {\n          return;\n        }\n        myLastNote = $(\n          `li.note[data-author-id='${gon.current_user_id}'][data-editable]:last`,\n          $textarea.closest('.note, .notes_holder, #notes'),\n        );\n        if (myLastNote.length) {\n          myLastNoteEditBtn = myLastNote.find('.js-note-edit');\n          return myLastNoteEditBtn.trigger('click', [true, myLastNote]);\n        }\n        break;\n      // Cancel creating diff note or editing any note when ESCAPE is hit\n      case 27:\n        discussionNoteForm = $textarea.closest('.js-discussion-note-form');\n        if (discussionNoteForm.length) {\n          if ($textarea.val() !== '') {\n            const confirmed = await confirmAction(__('Your comment will be discarded.'), {\n              primaryBtnVariant: 'danger',\n              primaryBtnText: __('Discard'),\n            });\n            if (!confirmed) return;\n          }\n          this.removeDiscussionNoteForm(discussionNoteForm);\n          return;\n        }\n        editNote = $textarea.closest('.note');\n        if (editNote.length) {\n          originalText = $textarea.closest('form').data('originalNote');\n          newText = $textarea.val();\n          if (originalText !== newText) {\n            const confirmed = await confirmAction(\n              __('Are you sure you want to discard this comment?'),\n              {\n                primaryBtnVariant: 'danger',\n                primaryBtnText: __('Discard'),\n              },\n            );\n            if (!confirmed) return;\n          }\n          return this.removeNoteEditForm(editNote);\n        }\n    }\n  }\n\n  initRefresh() {\n    if (Notes.interval) {\n      clearInterval(Notes.interval);\n    }\n    Notes.interval = setInterval(() => this.refresh(), this.pollingInterval);\n  }\n\n  refresh() {\n    if (!document.hidden) {\n      return this.getContent();\n    }\n  }\n\n  getContent() {\n    if (this.refreshing) {\n      return;\n    }\n\n    this.refreshing = true;\n\n    axios\n      .get(`${this.notes_url}?html=true`, {\n        headers: {\n          'X-Last-Fetched-At': this.last_fetched_at,\n        },\n      })\n      .then(({ data }) => {\n        const { notes } = data;\n        this.last_fetched_at = data.last_fetched_at;\n        this.setPollingInterval(data.notes.length);\n        $.each(notes, (i, note) => this.renderNote(note));\n\n        this.refreshing = false;\n      })\n      .catch(() => {\n        this.refreshing = false;\n      });\n  }\n\n  /**\n   * Increase @pollingInterval up to 120 seconds on every function call,\n   * if `shouldReset` has a truthy value, 'null' or 'undefined' the variable\n   * will reset to @basePollingInterval.\n   *\n   * Note: this function is used to gradually increase the polling interval\n   * if there aren't new notes coming from the server\n   */\n  setPollingInterval(shouldReset) {\n    if (shouldReset == null) {\n      shouldReset = true;\n    }\n    const nthInterval = this.basePollingInterval * 2 ** (this.maxPollingSteps - 1);\n    if (shouldReset) {\n      this.pollingInterval = this.basePollingInterval;\n    } else if (this.pollingInterval < nthInterval) {\n      this.pollingInterval *= 2;\n    }\n    return this.initRefresh();\n  }\n\n  handleQuickActions(noteEntity) {\n    let votesBlock;\n    if (noteEntity.commands_changes) {\n      if ('merge' in noteEntity.commands_changes) {\n        Notes.checkMergeRequestStatus();\n      }\n\n      if ('emoji_award' in noteEntity.commands_changes) {\n        votesBlock = $('.js-awards-block').eq(0);\n\n        loadAwardsHandler()\n          .then((awardsHandler) => {\n            awardsHandler.addAwardToEmojiBar(votesBlock, noteEntity.commands_changes.emoji_award);\n            awardsHandler.scrollToAwards();\n          })\n          .catch(() => {\n            // ignore\n          });\n      }\n    }\n  }\n\n  setupNewNote($note) {\n    // Update datetime format on the recent note\n    localTimeAgo($note.find('.js-timeago').get(), false);\n\n    this.taskList.init();\n\n    // This stops the note highlight, #note_xxx`, from being removed after real time update\n    // The `:target` selector does not re-evaluate after we replace element in the DOM\n    Notes.updateNoteTargetSelector($note);\n    this.$noteToCleanHighlight = $note;\n  }\n\n  onHashChange() {\n    if (this.$noteToCleanHighlight) {\n      Notes.updateNoteTargetSelector(this.$noteToCleanHighlight);\n    }\n\n    this.$noteToCleanHighlight = null;\n  }\n\n  static updateNoteTargetSelector($note) {\n    const hash = getLocationHash();\n    // Needs to be an explicit true/false for the jQuery `toggleClass(force)`\n    const addTargetClass = Boolean(hash && $note.filter(`#${hash}`).length > 0);\n    $note.toggleClass('target', addTargetClass);\n  }\n\n  /**\n   * Render note in main comments area.\n   *\n   * Note: for rendering inline notes use renderDiscussionNote\n   */\n  renderNote(noteEntity, $form, $notesList = $('.main-notes-list')) {\n    if (noteEntity.discussion_html) {\n      return this.renderDiscussionNote(noteEntity, $form);\n    }\n\n    if (!noteEntity.valid) {\n      if (noteEntity?.quick_actions_status?.messages) {\n        if (noteEntity.commands_changes && Object.keys(noteEntity.commands_changes).length > 0) {\n          $notesList.find('.system-note.being-posted').remove();\n        }\n        this.addAlert({\n          message: noteEntity.quick_actions_status.messages,\n          variant: VARIANT_INFO,\n          parent: this.parentTimeline.get(0),\n        });\n        this.refresh();\n      }\n      return;\n    }\n\n    const $note = $notesList.find(`#note_${noteEntity.id}`);\n    if (Notes.isNewNote(noteEntity, this.note_ids)) {\n      if (isInMRPage()) {\n        return;\n      }\n\n      if ($notesList.length) {\n        $notesList.find('.system-note.being-posted').remove();\n      }\n      const $newNote = Notes.animateAppendNote(noteEntity.html, $notesList);\n\n      this.setupNewNote($newNote);\n      this.refresh();\n      return this.updateNotesCount(1);\n    }\n    if (Notes.isUpdatedNote(noteEntity, $note)) {\n      // The server can send the same update multiple times so we need to make sure to only update once per actual update.\n      const isEditing = $note.hasClass('is-editing');\n      const initialContent = normalizeNewlines($note.find('.original-note-content').text().trim());\n      const $textarea = $note.find('.js-note-text');\n      const currentContent = $textarea.val();\n      // There can be CRLF vs LF mismatches if we don't sanitize and compare the same way\n      const sanitizedNoteNote = normalizeNewlines(noteEntity.note);\n      const isTextareaUntouched =\n        currentContent === initialContent || currentContent === sanitizedNoteNote;\n\n      if (isEditing && isTextareaUntouched) {\n        $textarea.val(noteEntity.note);\n        this.updatedNotesTrackingMap[noteEntity.id] = noteEntity;\n      } else if (isEditing && !isTextareaUntouched) {\n        this.putConflictEditWarningInPlace(noteEntity, $note);\n        this.updatedNotesTrackingMap[noteEntity.id] = noteEntity;\n      } else {\n        const $updatedNote = Notes.animateUpdateNote(noteEntity.html, $note);\n        this.setupNewNote($updatedNote);\n      }\n    }\n  }\n\n  isParallelView() {\n    return getCookie('diff_view') === 'parallel';\n  }\n\n  /**\n   * Render note in discussion area. To render inline notes use renderDiscussionNote.\n   */\n  renderDiscussionNote(noteEntity, $form) {\n    let discussionContainer;\n    let row;\n\n    if (!Notes.isNewNote(noteEntity, this.note_ids)) {\n      return;\n    }\n\n    const form =\n      $form || $(`.js-discussion-note-form[data-discussion-id=\"${noteEntity.discussion_id}\"]`);\n    row =\n      form.length || !noteEntity.discussion_line_code\n        ? form.closest('tr')\n        : $(`#${noteEntity.discussion_line_code}`);\n\n    if (noteEntity.on_image) {\n      row = form;\n    }\n\n    // is this the first note of discussion?\n    discussionContainer = $(`.notes[data-discussion-id=\"${noteEntity.discussion_id}\"]`);\n    if (!discussionContainer.length) {\n      discussionContainer = form.closest('.discussion').find('.notes');\n    }\n    if (discussionContainer.length === 0) {\n      if (noteEntity.diff_discussion_html) {\n        let discussionElement = document.createElement('table');\n        let internalNote;\n\n        if (!noteEntity.on_image) {\n          /*\n            DOMPurify will strip table-less <tr>/<td>, so to get it to stop deleting\n            nodes (since our note HTML starts with a table-less <tr>), we need to wrap\n            the noteEntity discussion HTML in a <table> to perform the other\n            sanitization.\n          */\n          internalNote = sanitize(`<table>${noteEntity.diff_discussion_html}</table>`, {\n            RETURN_DOM: true,\n          });\n          /*\n            Since we wrapped the <tr> in a <table>, we need to extract the <tr> back out.\n            DOMPurify returns a Body Element, so we have to start there, then get the\n            wrapping table, and then get the content we actually want.\n            Curiously, DOMPurify **ADDS** a totally novel <tbody>, so we're actually\n            inserting a completely as-yet-unseen <tbody> element here.\n          */\n          discussionElement = internalNote.querySelector('table').querySelector('.notes_holder');\n        } else {\n          // Image comments don't need <table> manipulation, they're already <div>s\n          internalNote = sanitize(noteEntity.diff_discussion_html, {\n            RETURN_DOM: true,\n          });\n          discussionElement.insertAdjacentElement('afterbegin', internalNote.firstElementChild);\n        }\n\n        renderGFM(discussionElement);\n        const $discussion = $(discussionElement).unwrap();\n\n        if (noteEntity.on_image) {\n          discussionElement.classList.add('discussion-notes', 'gl-block');\n        }\n\n        if (!this.isParallelView() || row.hasClass('js-temp-notes-holder') || noteEntity.on_image) {\n          // insert the note and the reply button after the temp row\n          row.after($discussion);\n        } else {\n          // Merge new discussion HTML in\n          const $notes = $discussion.find(\n            `.notes[data-discussion-id=\"${noteEntity.discussion_id}\"]`,\n          );\n          const contentContainerClass = $notes\n            .closest('.notes-content')\n            .attr('class')\n            .split(' ')\n            .join('.');\n\n          row\n            .find(`.${contentContainerClass} .content`)\n            .append($notes.closest('.content').children());\n        }\n      } else {\n        Notes.animateAppendNote(noteEntity.discussion_html, $('.main-notes-list'));\n      }\n    } else {\n      // append new note to all matching discussions\n      Notes.animateAppendNote(noteEntity.html, discussionContainer);\n    }\n\n    localTimeAgo(document.querySelectorAll('.js-timeago'), false);\n    Notes.checkMergeRequestStatus();\n    return this.updateNotesCount(1);\n  }\n\n  getLineHolder(changesDiscussionContainer) {\n    return $(changesDiscussionContainer)\n      .closest('.notes_holder')\n      .prevAll('.line_holder')\n      .first()\n      .get(0);\n  }\n\n  /**\n   * Called in response the main target form has been successfully submitted.\n   *\n   * Removes any errors.\n   * Resets text and preview.\n   * Resets buttons.\n   */\n  resetMainTargetForm(e) {\n    const form = $('.js-main-target-form');\n    // remove validation errors\n    form.find('.js-errors').remove();\n    // reset text and preview\n    if (form.find('.js-md-preview-button').val() === 'edit') {\n      form.find('.js-md-preview-button').click();\n    }\n\n    form.find('.js-note-text').val('').trigger('input');\n    form.find('.js-note-text').each(function reset() {\n      this.$autosave.reset();\n    });\n\n    const event = document.createEvent('Event');\n    event.initEvent('autosize:update', true, false);\n    form.find('.js-autosize')[0].dispatchEvent(event);\n\n    this.updateTargetButtons(e);\n  }\n\n  reenableTargetFormSubmitButton() {\n    const form = $('.js-main-target-form');\n    return form.find('.js-note-text').trigger('input');\n  }\n\n  /**\n   * Shows the main form and does some setup on it.\n   *\n   * Sets some hidden fields in the form.\n   */\n  setupMainTargetNoteForm(enableGFM) {\n    // find the form\n    const form = $('.js-new-note-form');\n    // Set a global clone of the form for later cloning\n    this.formClone = form.clone();\n    // show the form\n    this.setupNoteForm(form, enableGFM);\n    // fix classes\n    form.removeClass('js-new-note-form');\n    form.addClass('js-main-target-form');\n    form.find('#note_line_code').remove();\n    form.find('#note_position').remove();\n    form.find('#note_type').val('');\n    form.find('#note_project_id').remove();\n    form.find('#in_reply_to_discussion_id').remove();\n    this.parentTimeline = form.parents('.timeline');\n\n    if (form.length) {\n      Notes.initCommentTypeToggle(form.get(0));\n    }\n  }\n\n  /**\n   * General note form setup.\n   *\n   * deactivates the submit button when text is empty\n   * hides the preview button when text is empty\n   * set up GFM auto complete\n   * show the form\n   */\n  setupNoteForm(form, enableGFM = defaultAutocompleteConfig) {\n    this.glForm = new GLForm(form, enableGFM);\n    const textarea = form.find('.js-note-text');\n    const key = [\n      s__('NoteForm|Note'),\n      form.find('#note_noteable_type').val(),\n      form.find('#note_noteable_id').val(),\n      form.find('#note_commit_id').val(),\n      form.find('#note_type').val(),\n      form.find('#note_project_id').val(),\n      form.find('#in_reply_to_discussion_id').val(),\n\n      // LegacyDiffNote\n      form.find('#note_line_code').val(),\n\n      // DiffNote\n      form.find('#note_position').val(),\n    ];\n    const textareaEl = textarea.get(0);\n    // eslint-disable-next-line no-new\n    if (textareaEl) new Autosave(textareaEl, key);\n  }\n\n  /**\n   * Called in response to the new note form being submitted\n   *\n   * Adds new note to list.\n   */\n  addNote($form, note) {\n    return this.renderNote(note);\n  }\n\n  addNoteError(error, $form) {\n    let formParentTimeline;\n    if ($form.hasClass('js-main-target-form')) {\n      formParentTimeline = $form.parents('.timeline');\n    } else if ($form.hasClass('js-discussion-note-form')) {\n      formParentTimeline = $form.closest('.discussion-notes').find('.notes');\n    }\n\n    const serverErrorMessage = error?.response?.data?.errors;\n\n    const alertMessage = serverErrorMessage\n      ? sprintf(COMMENT_FORM.error, { reason: serverErrorMessage.toLowerCase() }, false)\n      : COMMENT_FORM.GENERIC_UNSUBMITTABLE_NETWORK;\n\n    return this.addAlert({\n      message: alertMessage,\n      parent: formParentTimeline.get(0),\n    });\n  }\n\n  updateNoteError(error, $editingNote) {\n    const serverErrorMessage = error?.response?.data?.errors;\n\n    const alertMessage = serverErrorMessage\n      ? sprintf(UPDATE_COMMENT_FORM.error, { reason: serverErrorMessage }, false)\n      : UPDATE_COMMENT_FORM.defaultError;\n\n    return this.addAlert({\n      message: alertMessage,\n      parent: $editingNote.get(0),\n    });\n  }\n\n  /**\n   * Called in response to the new note form being submitted\n   *\n   * Adds new note to list.\n   */\n  addDiscussionNote($form, note, isNewDiffComment) {\n    if ($form.attr('data-resolve-all') != null) {\n      const discussionId = $form.data('discussionId');\n      const mergeRequestId = $form.data('noteableIid');\n\n      if (ResolveService != null) {\n        ResolveService.toggleResolveForDiscussion(mergeRequestId, discussionId);\n      }\n    }\n\n    this.renderNote(note, $form);\n    // cleanup after successfully creating a diff/discussion note\n    if (isNewDiffComment) {\n      this.removeDiscussionNoteForm($form);\n    }\n  }\n\n  /**\n   * Called in response to the edit note form being submitted\n   *\n   * Updates the current note field.\n   */\n  updateNote(noteEntity, $targetNote) {\n    // Convert returned HTML to a jQuery object so we can modify it further\n    const $noteEntityEl = $(noteEntity.html);\n    const $noteAvatar = $noteEntityEl.find('.image-diff-avatar-link');\n    const $targetNoteBadge = $targetNote.find('.design-note-pin');\n\n    $noteAvatar.append($targetNoteBadge);\n    this.revertNoteEditForm($targetNote);\n    renderGFM(Notes.getNodeToRender($noteEntityEl));\n    // Find the note's `li` element by ID and replace it with the updated HTML\n    const $note_li = $(`.note-row-${noteEntity.id}`);\n\n    $note_li.replaceWith($noteEntityEl);\n    this.setupNewNote($noteEntityEl);\n  }\n\n  checkContentToAllowEditing($el) {\n    const initialContent = $el.find('.original-note-content').text().trim();\n    const currentContent = $el.find('.js-note-text').val();\n    let isAllowed = true;\n\n    if (currentContent === initialContent) {\n      this.removeNoteEditForm($el);\n    } else {\n      const isWidgetVisible = isInViewport($el.get(0));\n\n      if (!isWidgetVisible) {\n        scrollToElement($el);\n      }\n\n      $el.find('.js-finish-edit-warning').show();\n      isAllowed = false;\n    }\n\n    return isAllowed;\n  }\n\n  /**\n   * Called in response to clicking the edit note link\n   *\n   * Replaces the note text with the note edit form\n   * Adds a data attribute to the form with the original content of the note for cancellations\n   */\n  showEditForm(e) {\n    e.preventDefault();\n\n    const $target = $(e.target);\n    const $editForm = $(this.getEditFormSelector($target));\n    const $note = $target.closest('.note');\n    const $currentlyEditing = $('.note.is-editing:visible');\n\n    this.clearAlertWrapper();\n\n    if ($currentlyEditing.length) {\n      const isEditAllowed = this.checkContentToAllowEditing($currentlyEditing);\n\n      if (!isEditAllowed) {\n        return;\n      }\n    }\n\n    $note.find('.js-note-attachment-delete').show();\n    $editForm.addClass('current-note-edit-form');\n    $note.addClass('is-editing');\n    this.putEditFormInPlace($target);\n  }\n\n  /**\n   * Called in response to clicking the edit note link\n   *\n   * Hides edit form and restores the original note text to the editor textarea.\n   */\n  cancelEdit(e) {\n    e.preventDefault();\n    const $target = $(e.target);\n    const $note = $target.closest('.note');\n    const noteId = $note.attr('data-note-id');\n\n    this.revertNoteEditForm($target);\n\n    if (this.updatedNotesTrackingMap[noteId]) {\n      const $newNote = $(this.updatedNotesTrackingMap[noteId].html);\n      $note.replaceWith($newNote);\n      this.setupNewNote($newNote);\n      // Now that we have taken care of the update, clear it out\n      delete this.updatedNotesTrackingMap[noteId];\n    } else {\n      $note.find('.js-finish-edit-warning').hide();\n      this.removeNoteEditForm($note);\n    }\n  }\n\n  revertNoteEditForm($target) {\n    $target = $target || $('.note.is-editing:visible');\n    const selector = this.getEditFormSelector($target);\n    const $editForm = $(selector);\n\n    $editForm.insertBefore('.js-snippets-note-edit-form-holder');\n    $editForm.find('.js-comment-save-button').enable();\n    $editForm.find('.js-finish-edit-warning').hide();\n  }\n\n  getEditFormSelector($el) {\n    let selector = '.note-edit-form:not(.mr-note-edit-form)';\n\n    if ($el.parents('#diffs').length) {\n      selector = '.note-edit-form.mr-note-edit-form';\n    }\n\n    return selector;\n  }\n\n  removeNoteEditForm($note) {\n    const form = $note.find('.diffs .current-note-edit-form');\n\n    $note.removeClass('is-editing');\n    form.removeClass('current-note-edit-form');\n    form.find('.js-finish-edit-warning').hide();\n    // Replace markdown textarea text with original note text.\n    return form.find('.js-note-text').val(form.find('form.edit-note').data('originalNote'));\n  }\n\n  /**\n   * Called in response to deleting a note of any kind.\n   *\n   * Removes the actual note from view.\n   * Removes the whole discussion if the last note is being removed.\n   */\n  removeNote(e) {\n    const $note = $(e.currentTarget).closest('.note');\n\n    $note.one('ajax:complete', () => {\n      const noteElId = $note.attr('id');\n      $(`.note[id=\"${noteElId}\"]`).each((i, el) => {\n        // A same note appears in the \"Discussion\" and in the \"Changes\" tab, we have\n        // to remove all. Using $('.note[id='noteId']') ensure we get all the notes,\n        // where $('#noteId') would return only one.\n        const $note = $(el);\n        const $notes = $note.closest('.discussion-notes');\n        const discussionId = $('.notes', $notes).data('discussionId');\n\n        $note.remove();\n\n        // check if this is the last note for this line\n        if ($notes.find('.note').length === 0) {\n          const notesTr = $notes.closest('tr');\n\n          // \"Discussions\" tab\n          $notes.closest('.timeline-entry').remove();\n\n          $(`.js-diff-avatars-${discussionId}`).trigger('remove.vue');\n\n          // The notes tr can contain multiple lists of notes, like on the parallel diff\n          // notesTr does not exist for image diffs\n          if (notesTr.find('.discussion-notes').length > 1 || notesTr.length === 0) {\n            const $diffFile = $notes.closest('.diff-file');\n            if ($diffFile.length > 0) {\n              const removeBadgeEvent = new CustomEvent('removeBadge.imageDiff', {\n                detail: {\n                  // badgeNumber's start with 1 and index starts with 0\n                  badgeNumber: $notes.index() + 1,\n                },\n              });\n\n              $diffFile[0].dispatchEvent(removeBadgeEvent);\n            }\n\n            $notes.remove();\n          } else if (notesTr.length > 0) {\n            notesTr.remove();\n          }\n        }\n      });\n\n      Notes.checkMergeRequestStatus();\n      return this.updateNotesCount(-1);\n    });\n  }\n\n  /**\n   * Called in response to clicking the delete attachment link\n   *\n   * Removes the attachment wrapper view, including image tag if it exists\n   * Resets the note editing form\n   */\n  removeAttachment() {\n    const $note = $(this).closest('.note');\n    $note.find('.note-attachment').remove();\n    $note.find('.note-body > .note-text').show();\n    $note.find('.note-header').show();\n    return $note.find('.diffs .current-note-edit-form').remove();\n  }\n\n  /**\n   * Called when clicking on the \"reply\" button for a diff line.\n   *\n   * Shows the note form below the notes.\n   */\n  onReplyToDiscussionNote(e) {\n    this.replyToDiscussionNote(e.target);\n  }\n\n  replyToDiscussionNote(target) {\n    const form = this.cleanForm(this.formClone.clone());\n    const replyLink = $(target).closest('.js-discussion-reply-button');\n    // insert the form after the button\n    replyLink.closest('.discussion-reply-holder').hide().after(form);\n\n    // show the form\n    return this.setupDiscussionNoteForm(replyLink, form);\n  }\n\n  /**\n   * Shows the diff or discussion form and does some setup on it.\n   *\n   * Sets some hidden fields in the form.\n   *\n   * Note: dataHolder must have the \"discussionId\" and \"lineCode\" data attributes set.\n   */\n  setupDiscussionNoteForm(dataHolder, form) {\n    // set up note target\n    let diffFileData = dataHolder.closest('.text-file');\n\n    if (diffFileData.length === 0) {\n      diffFileData = dataHolder.closest('.image');\n    }\n\n    const discussionID = dataHolder.data('discussionId');\n\n    if (discussionID) {\n      form.attr('data-discussion-id', discussionID);\n      form.find('#in_reply_to_discussion_id').val(discussionID);\n    }\n\n    form.find('#note_project_id').val(dataHolder.data('discussionProjectId'));\n\n    form.attr('data-line-code', dataHolder.data('lineCode'));\n    form.find('#line_type').val(dataHolder.data('lineType'));\n\n    form.find('#note_noteable_type').val(diffFileData.data('noteableType'));\n    form.find('#note_noteable_id').val(diffFileData.data('noteableId'));\n    form.find('#note_commit_id').val(diffFileData.data('commitId'));\n\n    form.find('#note_type').val(dataHolder.data('noteType'));\n\n    // LegacyDiffNote\n    form.find('#note_line_code').val(dataHolder.data('lineCode'));\n\n    // DiffNote\n    form.find('#note_position').val(dataHolder.attr('data-position'));\n\n    form.append('</div>').find('.js-close-discussion-note-form').show().removeClass('hide');\n    form.find('.js-note-target-close').remove();\n    form.find('.js-note-new-discussion').remove();\n    this.setupNoteForm(form);\n\n    form.removeClass('js-main-target-form').addClass('discussion-form js-discussion-note-form');\n\n    form.find('.js-note-text').focus();\n    form.find('.js-comment-resolve-button').attr('data-discussion-id', discussionID);\n  }\n\n  /**\n   * Called when clicking on the \"add a comment\" button on the side of a diff line.\n   *\n   * Inserts a temporary row for the form below the line.\n   * Sets up the form and shows it.\n   */\n  onAddDiffNote(e) {\n    e.preventDefault();\n    const link = e.currentTarget || e.target;\n    const $link = $(link);\n    const showReplyInput = !$link.hasClass('js-diff-comment-avatar');\n    this.toggleDiffNote({\n      target: $link,\n      lineType: link.dataset.lineType,\n      showReplyInput,\n      currentUsername: gon.current_username,\n      currentUserAvatar: gon.current_user_avatar_url,\n      currentUserFullname: gon.current_user_fullname,\n    });\n  }\n\n  onAddImageDiffNote(e) {\n    const $link = $(e.currentTarget || e.target);\n    const $diffFile = $link.closest('.diff-file');\n\n    const clickEvent = new CustomEvent('click.imageDiff', {\n      detail: e,\n    });\n\n    $diffFile[0].dispatchEvent(clickEvent);\n\n    // Set up comment form\n    let newForm;\n    const $noteContainer = $link.closest('.diff-viewer').find('.note-container');\n    const $form = $noteContainer.find('> .discussion-form');\n\n    if ($form.length === 0) {\n      newForm = this.cleanForm(this.formClone.clone());\n      newForm.appendTo($noteContainer);\n    } else {\n      newForm = $form;\n    }\n\n    this.setupDiscussionNoteForm($link, newForm);\n  }\n\n  toggleDiffNote({ target, lineType, forceShow, showReplyInput = false }) {\n    let addForm;\n    let newForm;\n    let noteForm;\n    let replyButton;\n    let rowCssToAdd;\n    const $link = $(target);\n    const row = $link.closest('tr');\n    const nextRow = row.next();\n    let targetRow = row;\n    if (nextRow.is('.notes_holder')) {\n      targetRow = nextRow;\n    }\n\n    const hasNotes = nextRow.is('.notes_holder');\n    addForm = false;\n    let lineTypeSelector = '';\n    rowCssToAdd =\n      '<tr class=\"notes_holder js-temp-notes-holder\"><td class=\"notes-content\" colspan=\"3\"><div class=\"content\"></div></td></tr>';\n    // In parallel view, look inside the correct left/right pane\n    if (this.isParallelView()) {\n      lineTypeSelector = `.${lineType}`;\n      rowCssToAdd =\n        '<tr class=\"notes_holder js-temp-notes-holder\"><td class=\"notes_line old\"></td><td class=\"notes-content parallel old\"><div class=\"content\"></div></td><td class=\"notes_line new\"></td><td class=\"notes-content parallel new\"><div class=\"content\"></div></td></tr>';\n    }\n    const notesContentSelector = `.notes-content${lineTypeSelector} .content`;\n    let notesContent = targetRow.find(notesContentSelector);\n\n    if (hasNotes && showReplyInput) {\n      targetRow.show();\n      notesContent = targetRow.find(notesContentSelector);\n      if (notesContent.length) {\n        notesContent.show();\n        replyButton = notesContent.find('.js-discussion-reply-button:visible');\n        if (replyButton.length) {\n          this.replyToDiscussionNote(replyButton[0]);\n        } else {\n          // In parallel view, the form may not be present in one of the panes\n          noteForm = notesContent.find('.js-discussion-note-form');\n          if (noteForm.length === 0) {\n            addForm = true;\n          }\n        }\n      }\n    } else if (showReplyInput) {\n      // add a notes row and insert the form\n      row.after(rowCssToAdd);\n      targetRow = row.next();\n      notesContent = targetRow.find(notesContentSelector);\n      addForm = true;\n    } else {\n      const isCurrentlyShown = targetRow.find('.content:not(:empty)').is(':visible');\n      const isForced = forceShow === true || forceShow === false;\n      const showNow = forceShow === true || (!isCurrentlyShown && !isForced);\n\n      targetRow.toggleClass('hide', !showNow);\n      notesContent.toggleClass('hide', !showNow);\n    }\n\n    if (addForm) {\n      newForm = this.cleanForm(this.formClone.clone());\n      newForm.appendTo(notesContent);\n      // show the form\n      return this.setupDiscussionNoteForm($link, newForm);\n    }\n  }\n\n  /**\n   * Called in response to \"cancel\" on a diff note form.\n   *\n   * Shows the reply button again.\n   * Removes the form and if necessary it's temporary row.\n   */\n  removeDiscussionNoteForm(form) {\n    const row = form.closest('tr');\n    const glForm = form.data('glForm');\n    glForm.destroy();\n    form.find('.js-note-text').each(function reset() {\n      this.$autosave.reset();\n    });\n    // show the reply button (will only work for replies)\n    form.prev('.discussion-reply-holder').show();\n    if (row.is('.js-temp-notes-holder')) {\n      // remove temporary row for diff lines\n      return row.remove();\n    }\n    // only remove the form\n    return form.remove();\n  }\n\n  cancelDiscussionForm(e) {\n    e.preventDefault();\n    const $form = $(e.target).closest('.js-discussion-note-form');\n    const $discussionNote = $(e.target).closest('.discussion-notes');\n\n    if ($discussionNote.length === 0) {\n      // Only send blur event when the discussion form\n      // is not part of a discussion note\n      const $diffFile = $form.closest('.diff-file');\n\n      if ($diffFile.length > 0) {\n        const blurEvent = new CustomEvent('blur.imageDiff', {\n          detail: e,\n        });\n\n        $diffFile[0].dispatchEvent(blurEvent);\n      }\n    }\n\n    return this.removeDiscussionNoteForm($form);\n  }\n\n  /**\n   * Called after an attachment file has been selected.\n   *\n   * Updates the file name for the selected attachment.\n   */\n  updateFormAttachment() {\n    const form = $(this).closest('form');\n    // get only the basename\n    const filename = $(this)\n      .val()\n      .replace(/^.*[\\\\\\/]/, '');\n    return form.find('.js-attachment-filename').text(filename);\n  }\n\n  /**\n   * Called when the tab visibility changes\n   */\n  visibilityChange() {\n    return this.refresh();\n  }\n\n  updateTargetButtons(e) {\n    let closetext;\n    let reopentext;\n    const textarea = $(e.target);\n    const form = textarea.parents('form');\n    const reopenbtn = form.find('.js-note-target-reopen');\n    const closebtn = form.find('.js-note-target-close');\n    const savebtn = form.find('.js-comment-save-button');\n    const commentTypeComponent = form.get(0)?.commentTypeComponent;\n\n    if (textarea.val().trim().length > 0) {\n      savebtn.enable();\n      reopentext = reopenbtn.attr('data-alternative-text');\n      closetext = closebtn.attr('data-alternative-text');\n      if (reopenbtn.text() !== reopentext) {\n        reopenbtn.text(reopentext);\n      }\n      if (closebtn.text() !== closetext) {\n        closebtn.text(closetext);\n      }\n      if (reopenbtn.is(':not(.btn-comment-and-reopen)')) {\n        reopenbtn.addClass('btn-comment-and-reopen');\n      }\n      if (closebtn.is(':not(.btn-comment-and-close)')) {\n        closebtn.addClass('btn-comment-and-close');\n      }\n      if (commentTypeComponent) {\n        commentTypeComponent.disabled = false;\n      }\n    } else {\n      savebtn.disable();\n      reopentext = reopenbtn.data('originalText');\n      closetext = closebtn.data('originalText');\n      if (reopenbtn.text() !== reopentext) {\n        reopenbtn.text(reopentext);\n      }\n      if (closebtn.text() !== closetext) {\n        closebtn.text(closetext);\n      }\n      if (reopenbtn.is('.btn-comment-and-reopen')) {\n        reopenbtn.removeClass('btn-comment-and-reopen');\n      }\n      if (closebtn.is('.btn-comment-and-close')) {\n        closebtn.removeClass('btn-comment-and-close');\n      }\n      if (commentTypeComponent) {\n        commentTypeComponent.disabled = true;\n      }\n    }\n  }\n\n  putEditFormInPlace($el) {\n    const $editForm = $(this.getEditFormSelector($el));\n    const $note = $el.closest('.note');\n\n    $editForm.insertAfter($note.find('.note-text'));\n\n    const $originalContentEl = $note.find('.original-note-content');\n    const originalContent = $originalContentEl.text().trim();\n    const postUrl = $originalContentEl.data('postUrl');\n    const targetId = $originalContentEl.data('targetId');\n    const targetType = $originalContentEl.data('targetType');\n\n    this.glForm = new GLForm($editForm.find('form'), this.enableGFM);\n\n    $editForm.find('form').attr('action', `${postUrl}?html=true`).attr('data-remote', 'true');\n    $editForm.find('.js-form-target-id').val(targetId);\n    $editForm.find('.js-form-target-type').val(targetType);\n    $editForm.find('.js-note-text').focus().val(originalContent);\n    // reset preview\n    if ($editForm.find('.js-md-preview-button').val() === 'edit') {\n      $editForm.find('.js-md-preview-button').click();\n    }\n    $editForm.find('.referenced-users').hide();\n  }\n\n  putConflictEditWarningInPlace(noteEntity, $note) {\n    if ($note.find('.js-conflict-edit-warning').length === 0) {\n      const open_link = `<a href=\"#note_${noteEntity.id}\" target=\"_blank\" rel=\"noopener noreferrer\">`;\n      const $alert = $(`<div class=\"js-conflict-edit-warning alert alert-danger\">\n        ${sprintf(\n          s__(\n            'Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost',\n          ),\n          {\n            open_link,\n            close_link: '</a>',\n          },\n        )}\n      </div>`);\n      $alert.insertAfter($note.find('.note-text'));\n    }\n  }\n\n  updateNotesCount(updateCount) {\n    return this.notesCountBadge.text(parseInt(this.notesCountBadge.text(), 10) + updateCount);\n  }\n\n  static renderPlaceholderComponent($container) {\n    const el = $container.find('.js-code-placeholder').get(0);\n    // eslint-disable-next-line no-new\n    new Vue({\n      el,\n      components: {\n        GlSkeletonLoader,\n      },\n      render(createElement) {\n        return createElement('gl-skeleton-loader');\n      },\n    });\n  }\n\n  static renderDiffContent($container, data) {\n    const { discussion_html } = data;\n    const lines = $(discussion_html).find('.line_holder');\n    lines.addClass('fade-in');\n    $container.find('.diff-content > table > tbody').prepend(lines);\n    const fileHolder = $container.find('.file-holder');\n    $container.find('.line-holder-placeholder').remove();\n    syntaxHighlight(fileHolder);\n  }\n\n  onClickRetryLazyLoad(e) {\n    const $retryButton = $(e.currentTarget);\n\n    $retryButton.prop('disabled', true);\n\n    return this.loadLazyDiff(e).then(() => {\n      $retryButton.prop('disabled', false);\n    });\n  }\n\n  loadLazyDiff(e) {\n    const $container = $(e.currentTarget).closest('.js-toggle-container');\n    Notes.renderPlaceholderComponent($container);\n\n    $container.find('.js-toggle-lazy-diff').removeClass('js-toggle-lazy-diff');\n\n    const $tableEl = $container.find('tbody');\n    if ($tableEl.length === 0) return;\n\n    const fileHolder = $container.find('.file-holder');\n    const url = fileHolder.data('linesPath');\n\n    const $errorContainer = $container.find('.js-error-lazy-load-diff');\n    const $successContainer = $container.find('.js-success-lazy-load');\n\n    /**\n     * We only fetch resolved discussions.\n     * Unresolved discussions don't have an endpoint being provided.\n     */\n    if (url) {\n      return axios\n        .get(url)\n        .then(({ data }) => {\n          // Reset state in case last request returned error\n          $successContainer.removeClass('hidden');\n          $errorContainer.addClass('hidden');\n\n          Notes.renderDiffContent($container, data);\n        })\n        .catch(() => {\n          $successContainer.addClass('hidden');\n          $errorContainer.removeClass('hidden');\n        });\n    }\n    return Promise.resolve();\n  }\n\n  toggleCommitList(e) {\n    const $element = $(e.currentTarget);\n    const $closestSystemCommitList = $element.siblings('.system-note-commit-list');\n    const $svgChevronUpElement = $element.find('svg.js-chevron-up');\n    const $svgChevronDownElement = $element.find('svg.js-chevron-down');\n\n    $svgChevronUpElement.toggleClass('gl-hidden');\n    $svgChevronDownElement.toggleClass('gl-hidden');\n\n    $closestSystemCommitList.toggleClass('hide-shade');\n  }\n\n  addAlert(...alertParams) {\n    this.alert = createAlert(...alertParams);\n  }\n\n  clearAlert() {\n    this.alert?.dismiss();\n  }\n\n  cleanForm($form) {\n    // Remove dropdown\n    $form.find('.dropdown-menu').remove();\n\n    return $form;\n  }\n\n  /**\n   * Check if note does not exist on page\n   */\n  static isNewNote(noteEntity, note_ids) {\n    if (note_ids.length === 0) {\n      note_ids = Notes.getNotesIds();\n    }\n    const isNewEntry = $.inArray(noteEntity.id, note_ids) === -1;\n    if (isNewEntry) {\n      note_ids.push(noteEntity.id);\n    }\n    return isNewEntry;\n  }\n\n  /**\n   * Get notes ids\n   */\n  static getNotesIds() {\n    /**\n     * The selector covers following notes\n     *  - notes and thread below the snippets and commit page\n     *  - notes on the file of commit page\n     *  - notes on an image file of commit page\n     */\n    const notesList = [...document.querySelectorAll('.notes:not(.notes-form) li[id]')];\n    return notesList.map((noteItem) => parseInt(noteItem.dataset.noteId, 10));\n  }\n\n  /**\n   * Check if $note already contains the `noteEntity` content\n   */\n  static isUpdatedNote(noteEntity, $note) {\n    // There can be CRLF vs LF mismatches if we don't sanitize and compare the same way\n    const sanitizedNoteEntityText = normalizeNewlines(noteEntity.note.trim());\n    const currentNoteText = normalizeNewlines(\n      $note.find('.original-note-content').first().text().trim(),\n    );\n    return sanitizedNoteEntityText !== currentNoteText;\n  }\n\n  static checkMergeRequestStatus() {\n    if (getPagePath(1) === 'merge_requests' && gl.mrWidget) {\n      gl.mrWidget.checkStatus();\n    }\n  }\n\n  static animateAppendNote(noteHtml, $notesList) {\n    const $note = $(noteHtml);\n\n    $note.addClass('fade-in-full');\n    renderGFM(Notes.getNodeToRender($note));\n    if ($notesList.find('.discussion-reply-holder').length) {\n      $notesList.children('.timeline-entry').last().after($note);\n    } else {\n      $notesList.append($note);\n    }\n    return $note;\n  }\n\n  static animateUpdateNote(noteHtml, $note) {\n    const $updatedNote = $(noteHtml);\n\n    $updatedNote.addClass('fade-in');\n    renderGFM(Notes.getNodeToRender($updatedNote));\n    $note.replaceWith($updatedNote);\n    return $updatedNote;\n  }\n\n  static getNodeToRender($note) {\n    for (const $item of $note) {\n      if (Notes.isNodeTypeElement($item)) {\n        return $item;\n      }\n    }\n    return '';\n  }\n\n  /**\n   * Get data from Form attributes to use for saving/submitting comment.\n   */\n  getFormData($form) {\n    const content = $form.find('.js-note-text').val();\n    return {\n      // eslint-disable-next-line no-jquery/no-serialize\n      formData: $form.serialize(),\n      formContent: escape(content),\n      formAction: $form.attr('action'),\n      formContentOriginal: content,\n    };\n  }\n\n  /**\n   * Identify if comment has any quick actions\n   */\n  hasQuickActions(formContent) {\n    return REGEX_QUICK_ACTIONS.test(formContent);\n  }\n\n  /**\n   * Remove quick actions and leave comment with pure message\n   */\n  stripQuickActions(formContent) {\n    return formContent.replace(REGEX_QUICK_ACTIONS, '').trim();\n  }\n\n  /**\n   * Gets appropriate description from quick actions found in provided `formContent`\n   */\n  getQuickActionDescription(formContent, availableQuickActions = []) {\n    let tempFormContent;\n\n    // Identify executed quick actions from `formContent`\n    const executedCommands = availableQuickActions.filter((command) => {\n      const commandRegex = new RegExp(`/${command.name}`);\n      return commandRegex.test(formContent);\n    });\n\n    if (executedCommands && executedCommands.length) {\n      if (executedCommands.length > 1) {\n        tempFormContent = __('Applying multiple commands');\n      } else {\n        const commandDescription = executedCommands[0].description.toLowerCase();\n        tempFormContent = sprintf(__('Applying command to %{commandDescription}'), {\n          commandDescription,\n        });\n      }\n    } else {\n      tempFormContent = __('Applying command');\n    }\n\n    return tempFormContent;\n  }\n\n  /**\n   * Create placeholder note DOM element populated with comment body\n   * that we will show while comment is being posted.\n   * Once comment is _actually_ posted on server, we will have final element\n   * in response that we will show in place of this temporary element.\n   */\n  createPlaceholderNote({\n    formContent,\n    uniqueId,\n    isDiscussionNote,\n    currentUsername,\n    currentUserFullname,\n    currentUserAvatar,\n  }) {\n    const discussionClass = isDiscussionNote ? 'discussion' : '';\n    const $tempNote = $(\n      `<li id=\"${uniqueId}\" class=\"note being-posted fade-in-half timeline-entry\">\n         <div class=\"timeline-entry-inner\">\n            <div class=\"timeline-icon\">\n               <a href=\"/${escape(currentUsername)}\">\n                 <img class=\"avatar s32\" src=\"${currentUserAvatar}\" />\n               </a>\n            </div>\n            <div class=\"timeline-content ${discussionClass}\">\n               <div class=\"note-header\">\n                  <div class=\"note-header-info\">\n                     <a href=\"/${escape(currentUsername)}\">\n                       <span class=\"gl-hidden sm:gl-inline-block gl-font-bold\">${escape(\n                         currentUsername,\n                       )}</span>\n                       <span class=\"note-headline-light\">${escape(currentUsername)}</span>\n                     </a>\n                  </div>\n               </div>\n               <div class=\"note-body\">\n                 <div class=\"note-text\">\n                   <p>${formContent}</p>\n                 </div>\n               </div>\n            </div>\n         </div>\n      </li>`,\n    );\n\n    $tempNote.find('.gl-hidden.sm:gl-inline-block').text(escape(currentUserFullname));\n    $tempNote.find('.note-headline-light').text(`@${escape(currentUsername)}`);\n\n    return $tempNote;\n  }\n\n  /**\n   * Create Placeholder System Note DOM element populated with quick action description\n   */\n  createPlaceholderSystemNote({ formContent, uniqueId }) {\n    const $tempNote = $(\n      `<li id=\"${uniqueId}\" class=\"note system-note timeline-entry being-posted fade-in-half\">\n         <div class=\"timeline-entry-inner\">\n           <div class=\"timeline-content\">\n             <i>${formContent}</i>\n           </div>\n         </div>\n       </li>`,\n    );\n\n    return $tempNote;\n  }\n\n  /**\n   * This method does following tasks step-by-step whenever a new comment\n   * is submitted by user (both main thread comments as well as discussion comments).\n   *\n   * 1) Get Form metadata\n   * 2) Identify comment type; a) Main thread b) Discussion thread c) Discussion resolve\n   * 3) Build temporary placeholder element (using `createPlaceholderNote`)\n   * 4) Show placeholder note on UI\n   * 5) Perform network request to submit the note using `axios.post`\n   *    a) If request is successfully completed\n   *        1. Remove placeholder element\n   *        2. Show submitted Note element\n   *        3. Perform post-submit errands\n   *           a. Mark discussion as resolved if comment submission was for resolve.\n   *           b. Reset comment form to original state.\n   *    b) If request failed\n   *        1. Remove placeholder element\n   *        2. Show error alert message about failure\n   */\n  postComment(e) {\n    e.preventDefault();\n\n    // Get Form metadata\n    const $submitBtn = $(e.target);\n    $submitBtn.prop('disabled', true);\n    let $form = $submitBtn.parents('form');\n    const commentTypeComponent = $form.get(0)?.commentTypeComponent;\n    if (commentTypeComponent) commentTypeComponent.disabled = true;\n    const $closeBtn = $form.find('.js-note-target-close');\n    const isDiscussionNote =\n      $submitBtn.parent().find('li.droplab-item-selected').attr('id') === 'discussion';\n    const isMainForm = $form.hasClass('js-main-target-form');\n    const isDiscussionForm = $form.hasClass('js-discussion-note-form');\n    const isDiscussionResolve = $submitBtn.hasClass('js-comment-resolve-button');\n    const { formData, formContent, formAction, formContentOriginal } = this.getFormData($form);\n    let noteUniqueId;\n    let systemNoteUniqueId;\n    let hasQuickActions = false;\n    let $notesContainer;\n    let tempFormContent;\n\n    // Get reference to notes container based on type of comment\n    if (isDiscussionForm) {\n      $notesContainer = $form.parent('.discussion-notes').find('.notes');\n    } else if (isMainForm) {\n      $notesContainer = $('ul.main-notes-list');\n    }\n\n    // If comment is to resolve discussion, disable submit buttons while\n    // comment posting is finished.\n    if (isDiscussionResolve) {\n      $form.find('.js-comment-submit-button').disable();\n    }\n\n    tempFormContent = formContent;\n    if (this.glForm.supportsQuickActions && this.hasQuickActions(formContent)) {\n      tempFormContent = this.stripQuickActions(formContent);\n      hasQuickActions = true;\n    }\n\n    // Show placeholder note\n    if (tempFormContent) {\n      noteUniqueId = uniqueId('tempNote_');\n      $notesContainer.append(\n        this.createPlaceholderNote({\n          formContent: tempFormContent,\n          uniqueId: noteUniqueId,\n          isDiscussionNote,\n          currentUsername: gon.current_username,\n          currentUserFullname: gon.current_user_fullname,\n          currentUserAvatar: gon.current_user_avatar_url,\n        }),\n      );\n    }\n\n    // Show placeholder system note\n    if (hasQuickActions) {\n      systemNoteUniqueId = uniqueId('tempSystemNote_');\n      $notesContainer.append(\n        this.createPlaceholderSystemNote({\n          formContent: this.getQuickActionDescription(\n            formContent,\n            AjaxCache.get(gl.GfmAutoComplete.dataSources.commands),\n          ),\n          uniqueId: systemNoteUniqueId,\n        }),\n      );\n    }\n\n    // Clear the form textarea\n    if ($notesContainer.length) {\n      if (isMainForm) {\n        this.resetMainTargetForm(e);\n      } else if (isDiscussionForm) {\n        this.removeDiscussionNoteForm($form);\n      }\n    }\n\n    $closeBtn.text($closeBtn.data('originalText'));\n\n    // Make request to submit comment on server\n    return axios\n      .post(`${formAction}?html=true`, formData)\n      .then((res) => {\n        const note = res.data;\n\n        $submitBtn.prop('disabled', false);\n        if (commentTypeComponent) commentTypeComponent.disabled = false;\n\n        // Submission successful! remove placeholder\n        $notesContainer.find(`#${noteUniqueId}`).remove();\n\n        const $diffFile = $form.closest('.diff-file');\n        if ($diffFile.length > 0) {\n          const blurEvent = new CustomEvent('blur.imageDiff', {\n            detail: e,\n          });\n\n          $diffFile[0].dispatchEvent(blurEvent);\n        }\n\n        // Reset cached commands list when command is applied\n        if (hasQuickActions) {\n          $form.find('textarea.js-note-text').trigger('clear-commands-cache.atwho');\n        }\n\n        // Clear previous form errors\n        this.clearAlertWrapper();\n\n        // Check if this was discussion comment\n        if (isDiscussionForm) {\n          // Remove flash-container\n          $notesContainer.find('.flash-container').remove();\n\n          // If comment intends to resolve discussion, do the same.\n          if (isDiscussionResolve) {\n            $form\n              .attr('data-discussion-id', $submitBtn.data('discussionId'))\n              .attr('data-resolve-all', 'true')\n              .attr('data-project-path', $submitBtn.data('projectPath'));\n          }\n\n          // Show final note element on UI\n          const isNewDiffComment = $notesContainer.length === 0;\n          this.addDiscussionNote($form, note, isNewDiffComment);\n\n          if (isNewDiffComment) {\n            // Add image badge, avatar badge and toggle discussion badge for new image diffs\n            const notePosition = $form.find('#note_position').val();\n            if ($diffFile.length > 0 && notePosition.length > 0) {\n              const { x, y, width, height } = JSON.parse(notePosition);\n              const addBadgeEvent = new CustomEvent('addBadge.imageDiff', {\n                detail: {\n                  x,\n                  y,\n                  width,\n                  height,\n                  noteId: `note_${note.id}`,\n                  discussionId: note.discussion_id,\n                },\n              });\n\n              $diffFile[0].dispatchEvent(addBadgeEvent);\n            }\n          }\n\n          // append flash-container to the Notes list\n          if ($notesContainer.length) {\n            $notesContainer.append('<div class=\"flash-container\" style=\"display: none;\"></div>');\n          }\n        } else if (isMainForm) {\n          // Check if this was main thread comment\n          // Show final note element on UI and perform form and action buttons cleanup\n          this.addNote($form, note);\n          this.reenableTargetFormSubmitButton(e);\n        }\n\n        if (note.commands_changes) {\n          this.handleQuickActions(note);\n        }\n\n        $form.trigger('ajax:success', [note]);\n      })\n      .catch((error) => {\n        // Submission failed, remove placeholder note and show Flash error message\n        $notesContainer.find(`#${noteUniqueId}`).remove();\n        $submitBtn.prop('disabled', false);\n        if (commentTypeComponent) commentTypeComponent.disabled = false;\n\n        const blurEvent = new CustomEvent('blur.imageDiff', {\n          detail: e,\n        });\n\n        const closestDiffFile = $form.closest('.diff-file');\n\n        if (closestDiffFile.length) {\n          closestDiffFile[0].dispatchEvent(blurEvent);\n        }\n\n        if (hasQuickActions) {\n          $notesContainer.find(`#${systemNoteUniqueId}`).remove();\n        }\n\n        // Show form again on UI on failure\n        if (isDiscussionForm && $notesContainer.length) {\n          const replyButton = $notesContainer.parent().find('.js-discussion-reply-button');\n          this.replyToDiscussionNote(replyButton[0]);\n          $form = $notesContainer.parent().find('form');\n        }\n\n        $form.find('.js-note-text').val(formContentOriginal);\n        this.reenableTargetFormSubmitButton(e);\n        this.addNoteError(error, $form);\n      });\n  }\n\n  /**\n   * This method does following tasks step-by-step whenever an existing comment\n   * is updated by user (both main thread comments as well as discussion comments).\n   *\n   * 1) Get Form metadata\n   * 2) Update note element with new content\n   * 3) Perform network request to submit the updated note using `axios.post`\n   *    a) If request is successfully completed\n   *        1. Show submitted Note element\n   *    b) If request failed\n   *        1. Revert Note element to original content\n   *        2. Show error Flash message about failure\n   */\n  updateComment(e) {\n    e.preventDefault();\n\n    // Get Form metadata\n    const $submitBtn = $(e.target);\n    const $form = $submitBtn.parents('form');\n    const $closeBtn = $form.find('.js-note-target-close');\n    const $editingNote = $form.parents('.note.is-editing');\n    const $noteBody = $editingNote.find('.js-task-list-container');\n    const $noteBodyText = $noteBody.find('.note-text');\n    const { formData, formContent, formAction } = this.getFormData($form);\n\n    // Cache original comment content\n    const cachedNoteBodyText = $noteBodyText.html();\n\n    // Show updated comment content temporarily\n    $noteBodyText.html(formContent);\n    $editingNote.removeClass('is-editing fade-in-full').addClass('being-posted fade-in-half');\n\n    const $timeAgo = $editingNote.find('.note-headline-meta a');\n\n    $timeAgo.empty();\n    $timeAgo.append(loadingIconForLegacyJS({ inline: true, size: 'sm' }));\n\n    // Make request to update comment on server\n    axios\n      .post(`${formAction}?html=true`, formData)\n      .then(({ data }) => {\n        // Submission successful! render final note element\n        this.updateNote(data, $editingNote);\n      })\n      .catch((error) => {\n        $editingNote.addClass('is-editing fade-in-full').removeClass('being-posted fade-in-half');\n        // Submission failed, revert back to original note\n        $noteBodyText.html(cachedNoteBodyText);\n        $editingNote.find('.gl-spinner').remove();\n\n        // Show Flash message about failure\n        this.updateNoteError(error, $editingNote);\n      });\n\n    return $closeBtn.text($closeBtn.data('originalText'));\n  }\n\n  /**\n   * Function to check if node is element to avoid comment and text\n   */\n  static isNodeTypeElement($node) {\n    return $node.nodeType === Node.ELEMENT_NODE;\n  }\n}\n","import Notes from './deprecated_notes';\n\nexport default () => {\n  const dataEl = document.querySelector('.js-notes-data');\n  const { notesUrl, now, diffView, enableGFM } = JSON.parse(dataEl.innerHTML);\n\n  // Create a singleton so that we don't need to assign\n  // into the window object, we can just access the current isntance with Notes.instance\n  Notes.initialize(notesUrl, now, diffView, enableGFM);\n};\n","import { parseBoolean } from '~/lib/utils/common_utils';\nimport AccessorUtilities from './lib/utils/accessor';\n\nexport default class Autosave {\n  // eslint-disable-next-line max-params\n  constructor(field, key, fallbackKey, lockVersion) {\n    this.field = field;\n    this.type = this.field.getAttribute('type');\n    this.isLocalStorageAvailable = AccessorUtilities.canUseLocalStorage();\n    this.key = Array.isArray(key) ? `autosave/${key.join('/')}` : `autosave/${key}`;\n    this.fallbackKey = fallbackKey;\n    this.lockVersionKey = `${this.key}/lockVersion`;\n    this.lockVersion = lockVersion;\n    this.restore();\n    this.saveAction = this.save.bind(this);\n    // used by app/assets/javascripts/deprecated_notes.js\n    this.field.$autosave = this;\n    this.field.addEventListener('input', this.saveAction);\n  }\n\n  restore() {\n    if (!this.isLocalStorageAvailable) return;\n    const text = window.localStorage.getItem(this.key);\n    const fallbackText = window.localStorage.getItem(this.fallbackKey);\n    const newValue = text || fallbackText;\n\n    if (newValue == null) return;\n\n    let originalValue = this.field.value;\n    if (this.type === 'checkbox') {\n      originalValue = this.field.checked;\n      this.field.checked = parseBoolean(newValue);\n    } else {\n      this.field.value = newValue;\n    }\n\n    if (originalValue === newValue) return;\n    this.triggerInputEvents();\n  }\n\n  triggerInputEvents() {\n    // trigger events so @input, @change and v-model trigger in Vue components\n    const inputEvent = new Event('input', { bubbles: true, cancelable: false });\n    const changeEvent = new Event('change', { bubbles: true, cancelable: false });\n    this.field.dispatchEvent(inputEvent);\n    this.field.dispatchEvent(changeEvent);\n  }\n\n  getSavedLockVersion() {\n    if (!this.isLocalStorageAvailable) return undefined;\n    return window.localStorage.getItem(this.lockVersionKey);\n  }\n\n  save() {\n    const value = this.type === 'checkbox' ? this.field.checked : this.field.value;\n\n    if (this.isLocalStorageAvailable && value) {\n      if (this.fallbackKey) {\n        window.localStorage.setItem(this.fallbackKey, value);\n      }\n      if (this.lockVersion !== undefined) {\n        window.localStorage.setItem(this.lockVersionKey, this.lockVersion);\n      }\n      return window.localStorage.setItem(this.key, value);\n    }\n\n    return this.reset();\n  }\n\n  reset() {\n    if (!this.isLocalStorageAvailable) return undefined;\n\n    window.localStorage.removeItem(this.lockVersionKey);\n    window.localStorage.removeItem(this.fallbackKey);\n    return window.localStorage.removeItem(this.key);\n  }\n\n  dispose() {\n    delete this.field.$autosave;\n    this.field.removeEventListener('input', this.saveAction);\n  }\n}\n","import mod from \"-!../../../../../../node_modules/thread-loader/dist/cjs.js??ref--13-0!../../../../../../node_modules/babel-loader/lib/index.js??ref--13-1!../../../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./report_abuse_dropdown_item.vue?vue&type=script&lang=js\"; export default mod; export * from \"-!../../../../../../node_modules/thread-loader/dist/cjs.js??ref--13-0!../../../../../../node_modules/babel-loader/lib/index.js??ref--13-1!../../../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./report_abuse_dropdown_item.vue?vue&type=script&lang=js\"","<script>\nimport { GlDropdownItem } from '@gitlab/ui';\nimport { MountingPortal } from 'portal-vue';\nimport { s__ } from '~/locale';\n\nimport AbuseCategorySelector from '~/abuse_reports/components/abuse_category_selector.vue';\n\nexport default {\n  name: 'ReportAbuseDropdownItem',\n  components: {\n    GlDropdownItem,\n    MountingPortal,\n    AbuseCategorySelector,\n  },\n  inject: ['reportedUserId', 'reportedFromUrl'],\n  i18n: {\n    reportAbuse: s__('ReportAbuse|Report abuse'),\n  },\n  data() {\n    return {\n      open: false,\n    };\n  },\n  methods: {\n    toggleDrawer(open) {\n      this.open = open;\n    },\n  },\n};\n</script>\n<template>\n  <span>\n    <gl-dropdown-item @click=\"toggleDrawer(true)\">{{ $options.i18n.reportAbuse }}</gl-dropdown-item>\n\n    <mounting-portal mount-to=\"#js-report-abuse-drawer\" name=\"abuse-category-selector\" append>\n      <abuse-category-selector\n        :reported-user-id=\"reportedUserId\"\n        :reported-from-url=\"reportedFromUrl\"\n        :show-drawer=\"open\"\n        @close-drawer=\"toggleDrawer(false)\"\n      />\n    </mounting-portal>\n  </span>\n</template>\n","import { render, staticRenderFns } from \"./report_abuse_dropdown_item.vue?vue&type=template&id=59e7af4a\"\nimport script from \"./report_abuse_dropdown_item.vue?vue&type=script&lang=js\"\nexport * from \"./report_abuse_dropdown_item.vue?vue&type=script&lang=js\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n  script,\n  render,\n  staticRenderFns,\n  false,\n  null,\n  null,\n  null\n  \n)\n\nexport default component.exports","var render = function render(){var _vm=this,_c=_vm._self._c;return _c('span',[_c('gl-dropdown-item',{on:{\"click\":function($event){return _vm.toggleDrawer(true)}}},[_vm._v(_vm._s(_vm.$options.i18n.reportAbuse))]),_vm._v(\" \"),_c('mounting-portal',{attrs:{\"mount-to\":\"#js-report-abuse-drawer\",\"name\":\"abuse-category-selector\",\"append\":\"\"}},[_c('abuse-category-selector',{attrs:{\"reported-user-id\":_vm.reportedUserId,\"reported-from-url\":_vm.reportedFromUrl,\"show-drawer\":_vm.open},on:{\"close-drawer\":function($event){return _vm.toggleDrawer(false)}}})],1)],1)\n}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","import Vue from 'vue';\nimport ReportAbuseDropdownItem from './components/report_abuse_dropdown_item.vue';\n\nexport const initReportAbuse = () => {\n  const items = document.querySelectorAll('.js-report-abuse-dropdown-item');\n\n  items.forEach((el) => {\n    if (!el) return false;\n\n    const { reportAbusePath, reportedUserId, reportedFromUrl } = el.dataset;\n\n    return new Vue({\n      el,\n      name: 'ReportAbuseDropdownItemRoot',\n      provide: {\n        reportAbusePath,\n        reportedUserId: parseInt(reportedUserId, 10),\n        reportedFromUrl,\n      },\n      render(createElement) {\n        return createElement(ReportAbuseDropdownItem);\n      },\n    });\n  });\n};\n"],"sourceRoot":""}