summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/project_select_combo_button.js
blob: 865dd23bd801a5953af3f77459cb50d615749e80 (plain)
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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import $ from 'jquery';
import AccessorUtilities from './lib/utils/accessor';
import { loadCSSFile } from './lib/utils/css_utils';

export default class ProjectSelectComboButton {
  constructor(select) {
    this.projectSelectInput = $(select);
    this.newItemBtn = $('.new-project-item-link');
    this.resourceType = this.newItemBtn.data('type');
    this.resourceLabel = this.newItemBtn.data('label');
    this.formattedText = this.deriveTextVariants();
    this.groupId = this.projectSelectInput.data('groupId');
    this.bindEvents();
    this.initLocalStorage();
  }

  bindEvents() {
    this.projectSelectInput
      .siblings('.new-project-item-select-button')
      .on('click', e => this.openDropdown(e));

    this.newItemBtn.on('click', e => {
      if (!this.getProjectFromLocalStorage()) {
        e.preventDefault();
        this.openDropdown(e);
      }
    });

    this.projectSelectInput.on('change', () => this.selectProject());
  }

  initLocalStorage() {
    const localStorageIsSafe = AccessorUtilities.isLocalStorageAccessSafe();

    if (localStorageIsSafe) {
      this.localStorageKey = [
        'group',
        this.groupId,
        this.formattedText.localStorageItemType,
        'recent-project',
      ].join('-');
      this.setBtnTextFromLocalStorage();
    }
  }

  // eslint-disable-next-line class-methods-use-this
  openDropdown(event) {
    import(/* webpackChunkName: 'select2' */ 'select2/select2')
      .then(() => {
        // eslint-disable-next-line promise/no-nesting
        loadCSSFile(gon.select2_css_path)
          .then(() => {
            $(event.currentTarget)
              .siblings('.project-item-select')
              .select2('open');
          })
          .catch(() => {});
      })
      .catch(() => {});
  }

  selectProject() {
    const selectedProjectData = JSON.parse(this.projectSelectInput.val());
    const projectUrl = `${selectedProjectData.url}/${this.projectSelectInput.data('relativePath')}`;
    const projectName = selectedProjectData.name;

    const projectMeta = {
      url: projectUrl,
      name: projectName,
    };

    this.setNewItemBtnAttributes(projectMeta);
    this.setProjectInLocalStorage(projectMeta);
  }

  setBtnTextFromLocalStorage() {
    const cachedProjectData = this.getProjectFromLocalStorage();

    this.setNewItemBtnAttributes(cachedProjectData);
  }

  setNewItemBtnAttributes(project) {
    if (project) {
      this.newItemBtn.attr('href', project.url);
      this.newItemBtn.text(`${this.formattedText.defaultTextPrefix} in ${project.name}`);
    } else {
      this.newItemBtn.text(`Select project to create ${this.formattedText.presetTextSuffix}`);
    }
  }

  getProjectFromLocalStorage() {
    const projectString = localStorage.getItem(this.localStorageKey);

    return JSON.parse(projectString);
  }

  setProjectInLocalStorage(projectMeta) {
    const projectString = JSON.stringify(projectMeta);

    localStorage.setItem(this.localStorageKey, projectString);
  }

  deriveTextVariants() {
    const defaultTextPrefix = this.resourceLabel;

    // the trailing slice call depluralizes each of these strings (e.g. new-issues -> new-issue)
    const localStorageItemType = `new-${this.resourceType
      .split('_')
      .join('-')
      .slice(0, -1)}`;
    const presetTextSuffix = this.resourceType
      .split('_')
      .join(' ')
      .slice(0, -1);

    return {
      localStorageItemType, // new-issue / new-merge-request
      defaultTextPrefix, // New issue / New merge request
      presetTextSuffix, // issue / merge request
    };
  }
}