search_input.js 3.8 KB
Newer Older
F
Fatih Acet 已提交
1 2
const vscode = require('vscode');
const gitLabService = require('./gitlab_service');
3
const openers = require('./openers');
F
Fatih Acet 已提交
4 5 6

const parseQuery = (query, noteableType) => {
  const params = {};
7 8
  const tokens = query
    .replace(/: /g, ':') // Normalize spaces after tokens.
F
Fatih Acet 已提交
9 10
    .replace(/\s[a-z]*:/gi, t => `\n${t}`) // Get tokens and add new line.
    .split('\n') // Create array from tokens.
11
    .map(t => t.trim().split(':')); // Return new array with token and value arrays.
F
Fatih Acet 已提交
12 13 14

  // If there is no token it's a basic text search.
  if (tokens.length === 1 && tokens[0][1] === undefined) {
A
alpcanaydin 已提交
15
    // eslint-disable-next-line prefer-destructuring
F
Fatih Acet 已提交
16 17
    params.search = tokens[0][0];
  } else {
18
    tokens.forEach(t => {
F
Fatih Acet 已提交
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
      const [token, value] = t;

      switch (token) {
        // Merge value of `labels` token with previous labels.
        // By doing this we will be able to use `labels` and `label` token together.
        case 'labels':
          params.labels = (params.labels || []).concat(value.replace(/, /g, ',').split(','));
          break;

        // Labels can be multiple and should be comma separated.
        case 'label':
          params.labels = params.labels || [];
          params.labels.push(value);
          break;

34
        // GitLab requires Title and Description in `search` query param.
F
Fatih Acet 已提交
35 36 37 38 39
        // Since we are passing this as search query, GL will also search in issue descriptions too.
        case 'title':
          params.search = value;
          break;

40 41 42 43 44 45 46
        // GitLab UI requires milestone as milestone_title.
        case 'milestone':
          delete params.milestone;
          params.milestone_title = value;
          break;

        // GitLab requires author name as author_username.
F
Fatih Acet 已提交
47 48 49 50 51 52 53 54 55 56 57
        // `author` is syntatic sugar of extension.
        case 'author':
          delete params.author;

          if (value === 'me') {
            params.scope = 'created-by-me';
          } else {
            params.author_username = value;
          }
          break;

58
        // GitLab requires assignee name as assignee_username[] for issues.
F
Fatih Acet 已提交
59 60 61 62 63 64 65 66
        // and as assignee_username for merge requests `assignee` is syntatic sugar of extension.
        // We currently don't support multiple assignees for issues.
        case 'assignee':
          delete params.assignee;

          if (value === 'me') {
            params.scope = 'assigned-to-me';
          } else {
67 68
            const key =
              noteableType === 'merge_requests' ? 'assignee_username' : 'assignee_username[]';
F
Fatih Acet 已提交
69 70 71 72 73 74 75 76 77 78 79 80 81
            params[key] = value;
          }
          break;

        // Add other tokens. If there is a typo in token name GL either ignore it or won't find any issue.
        default:
          params[token] = value;
          break;
      }
    });
  }

  // URL encode keys and values and return a new array to build actual query string.
F
Fatih Acet 已提交
82 83
  const queryParams = Object.keys(params).map(k =>
    params[k] ? `${encodeURIComponent(k)}=${encodeURIComponent(params[k])}` : '',
F
Fatih Acet 已提交
84 85 86
  );

  return queryParams.length ? `?${queryParams.join('&')}` : '';
87
};
F
Fatih Acet 已提交
88

A
alpcanaydin 已提交
89 90 91 92 93 94 95 96 97 98
async function showSearchInputFor(noteableType) {
  const query = await vscode.window.showInputBox({
    ignoreFocusOut: true,
    placeHolder: 'Search in title or description. (Check project page for advanced usage)',
  });

  const queryString = await parseQuery(query, noteableType);
  const project = await gitLabService.fetchCurrentProject();

  if (project) {
99
    openers.openUrl(`${project.web_url}/${noteableType}${queryString}`);
A
alpcanaydin 已提交
100 101 102 103 104 105 106 107 108 109 110 111 112
  } else {
    vscode.window.showErrorMessage('GitLab Workflow: No project found to search issues');
  }
}

async function showIssueSearchInput() {
  showSearchInputFor('issues');
}

async function showMergeRequestSearchInput() {
  showSearchInputFor('merge_requests');
}

F
Fatih Acet 已提交
113 114
exports.showIssueSearchInput = showIssueSearchInput;
exports.showMergeRequestSearchInput = showMergeRequestSearchInput;