All files / app/assets/javascripts single_file_diff.js

87.71% Statements 50/57
70.58% Branches 12/17
57.14% Functions 4/7
89.28% Lines 50/56

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108                    8x 8x 8x         8x       3x 3x 3x 3x 3x 3x     3x 3x 2x 2x 2x 2x 2x   1x 1x 1x     3x     3x           5x           5x 5x 2x 2x 2x 2x 3x 2x 2x 2x 2x   1x 1x 1x         1x 1x   1x     1x 1x 1x 1x         1x   1x 1x   1x 1x   1x                  
import $ from 'jquery';
import { createAlert } from '~/alert';
import { loadingIconForLegacyJS } from '~/loading_icon_for_legacy_js';
import { spriteIcon } from '~/lib/utils/common_utils';
import FilesCommentButton from './files_comment_button';
import initImageDiffHelper from './image_diff/helpers/init_image_diff';
import axios from './lib/utils/axios_utils';
import { __ } from './locale';
import syntaxHighlight from './syntax_highlight';
 
const WRAPPER = '<div class="diff-content"></div>';
const LOADING_HTML = loadingIconForLegacyJS().outerHTML;
const ERROR_HTML = `<div class="nothing-here-block">${spriteIcon(
  'warning-solid',
  's16',
)} Could not load diff</div>`;
const COLLAPSED_HTML =
  '<div class="nothing-here-block diff-collapsed">This diff is collapsed. <button class="click-to-expand btn btn-link gl-button">Click to expand it.</button></div>';
 
export default class SingleFileDiff {
  constructor(file) {
    this.file = file;
    this.toggleDiff = this.toggleDiff.bind(this);
    this.content = $('.diff-content', this.file);
    this.$chevronRightIcon = $('.diff-toggle-caret .chevron-right', this.file);
    this.$chevronDownIcon = $('.diff-toggle-caret .chevron-down', this.file);
    this.diffForPath = this.content
      .find('div:not(.note-text)[data-diff-for-path]')
      .data('diffForPath');
    this.isOpen = !this.diffForPath;
    if (this.diffForPath) {
      this.collapsedContent = this.content;
      this.loadingContent = $(WRAPPER).addClass('loading').html(LOADING_HTML).hide();
      this.content = null;
      this.collapsedContent.after(this.loadingContent);
      this.$chevronRightIcon.removeClass('gl-display-none');
    } else {
      this.collapsedContent = $(WRAPPER).html(COLLAPSED_HTML).hide();
      this.content.after(this.collapsedContent);
      this.$chevronDownIcon.removeClass('gl-display-none');
    }
 
    $('.js-file-title', this.file).on('click', (e) => {
      this.toggleDiff($(e.target));
    });
    $('.click-to-expand', this.file).on('click', (e) => {
      this.toggleDiff($(e.currentTarget));
    });
  }
 
  toggleDiff($target, cb) {
    Iif (
      !$target.hasClass('js-file-title') &&
      !$target.hasClass('click-to-expand') &&
      !$target.closest('.diff-toggle-caret').length > 0
    )
      return;
    this.isOpen = !this.isOpen;
    if (!this.isOpen && !this.hasError) {
      this.content.hide();
      this.$chevronRightIcon.removeClass('gl-display-none');
      this.$chevronDownIcon.addClass('gl-display-none');
      this.collapsedContent.show();
    } else if (this.content) {
      this.collapsedContent.hide();
      this.content.show();
      this.$chevronDownIcon.removeClass('gl-display-none');
      this.$chevronRightIcon.addClass('gl-display-none');
    } else {
      this.$chevronDownIcon.removeClass('gl-display-none');
      this.$chevronRightIcon.addClass('gl-display-none');
      return this.getContentHTML(cb); // eslint-disable-line consistent-return
    }
  }
 
  getContentHTML(cb) {
    this.collapsedContent.hide();
    this.loadingContent.show();
 
    return axios
      .get(this.diffForPath)
      .then(({ data }) => {
        this.loadingContent.hide();
        if (data.html) {
          this.content = $(data.html);
          syntaxHighlight(this.content);
        } else E{
          this.hasError = true;
          this.content = $(ERROR_HTML);
        }
        this.collapsedContent.after(this.content);
 
        const $file = $(this.file);
        FilesCommentButton.init($file);
 
        const canCreateNote = $file.closest('.files').is('[data-can-create-note]');
        initImageDiffHelper.initImageDiff($file[0], canCreateNote);
 
        Iif (cb) cb();
      })
      .catch(() => {
        createAlert({
          message: __('An error occurred while retrieving diff'),
        });
      });
  }
}