All files / app/assets/javascripts/filtered_search dropdown_hint.js

0% Statements 0/34
0% Branches 0/15
0% Functions 0/6
0% Lines 0/34

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                                                                                                                                                                                                                 
import { __ } from '~/locale';
import Filter from './droplab/plugins/filter';
import DropdownUtils from './dropdown_utils';
import FilteredSearchDropdown from './filtered_search_dropdown';
import FilteredSearchDropdownManager from './filtered_search_dropdown_manager';
import FilteredSearchVisualTokens from './filtered_search_visual_tokens';
 
export default class DropdownHint extends FilteredSearchDropdown {
  constructor(options = {}) {
    const { input, tokenKeys } = options;
    super(options);
    this.config = {
      Filter: {
        template: 'hint',
        filterFunction: DropdownUtils.filterHint.bind(null, {
          input,
          allowedKeys: tokenKeys.getKeys(),
        }),
      },
    };
    this.tokenKeys = tokenKeys;
  }
 
  itemClicked(e) {
    const { selected } = e.detail;
 
    if (selected.tagName === 'LI') {
      if (Object.prototype.hasOwnProperty.call(selected.dataset, 'value')) {
        this.dismissDropdown();
      } else if (selected.dataset.action === 'submit') {
        this.dismissDropdown();
        this.dispatchFormSubmitEvent();
      } else {
        const filterItemEl = selected.closest('.filter-dropdown-item');
        const { hint: token, tag } = filterItemEl.dataset;
 
        if (tag.length) {
          // Get previous input values in the input field and convert them into visual tokens
          const previousInputValues = this.input.value.split(' ');
          const searchTerms = [];
 
          previousInputValues.forEach((value, index) => {
            searchTerms.push(value);
 
            if (
              index === previousInputValues.length - 1 &&
              token.indexOf(value.toLowerCase()) !== -1
            ) {
              searchTerms.pop();
            }
          });
 
          if (searchTerms.length > 0) {
            FilteredSearchVisualTokens.addSearchVisualToken(searchTerms.join(' '));
          }
 
          const key = token.replace(':', '');
          const { uppercaseTokenName } = this.tokenKeys.searchByKey(key);
 
          FilteredSearchDropdownManager.addWordToInput({
            tokenName: key,
            clicked: false,
            options: {
              uppercaseTokenName,
            },
          });
        }
        this.dismissDropdown();
        this.dispatchInputEvent();
      }
    }
  }
 
  renderContent() {
    const searchItem = [
      {
        hint: 'search',
        tag: 'search',
        formattedKey: __('Search for this text'),
        icon: `${gon.sprite_icons}#search`,
      },
    ];
 
    const dropdownData = this.tokenKeys
      .get()
      .map((tokenKey) => ({
        icon: `${gon.sprite_icons}#${tokenKey.icon}`,
        hint: tokenKey.key,
        tag: `:${tokenKey.tag}`,
        type: tokenKey.type,
        formattedKey: tokenKey.formattedKey,
      }))
      .concat(searchItem);
 
    this.droplab.changeHookList(this.hookId, this.dropdown, [Filter], this.config);
    this.droplab.setData(this.hookId, dropdownData);
 
    super.renderContent();
  }
 
  init() {
    this.droplab.addHook(this.input, this.dropdown, [Filter], this.config).init();
  }
}