2020-05-24 23:13:21 +05:30
|
|
|
import { escape } from 'lodash';
|
2020-01-01 13:55:28 +05:30
|
|
|
import { USER_TOKEN_TYPES } from 'ee_else_ce/filtered_search/constants';
|
2019-07-07 11:18:12 +05:30
|
|
|
import FilteredSearchContainer from '~/filtered_search/container';
|
|
|
|
import FilteredSearchVisualTokens from '~/filtered_search/filtered_search_visual_tokens';
|
|
|
|
import AjaxCache from '~/lib/utils/ajax_cache';
|
|
|
|
import DropdownUtils from '~/filtered_search/dropdown_utils';
|
|
|
|
import Flash from '~/flash';
|
|
|
|
import UsersCache from '~/lib/utils/users_cache';
|
2019-07-31 22:56:46 +05:30
|
|
|
import { __ } from '~/locale';
|
2019-07-07 11:18:12 +05:30
|
|
|
|
|
|
|
export default class VisualTokenValue {
|
2020-03-13 15:44:24 +05:30
|
|
|
constructor(tokenValue, tokenType, tokenOperator) {
|
2019-07-07 11:18:12 +05:30
|
|
|
this.tokenValue = tokenValue;
|
|
|
|
this.tokenType = tokenType;
|
2020-03-13 15:44:24 +05:30
|
|
|
this.tokenOperator = tokenOperator;
|
2019-07-07 11:18:12 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
render(tokenValueContainer, tokenValueElement) {
|
|
|
|
const { tokenType, tokenValue } = this;
|
|
|
|
|
|
|
|
if (['none', 'any'].includes(tokenValue.toLowerCase())) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tokenType === 'label') {
|
|
|
|
this.updateLabelTokenColor(tokenValueContainer);
|
2019-09-30 21:07:59 +05:30
|
|
|
} else if (USER_TOKEN_TYPES.includes(tokenType)) {
|
2019-07-07 11:18:12 +05:30
|
|
|
this.updateUserTokenAppearance(tokenValueContainer, tokenValueElement);
|
|
|
|
} else if (tokenType === 'my-reaction') {
|
|
|
|
this.updateEmojiTokenAppearance(tokenValueContainer, tokenValueElement);
|
2020-04-08 14:13:33 +05:30
|
|
|
} else if (tokenType === 'epic') {
|
|
|
|
this.updateEpicLabel(tokenValueContainer, tokenValueElement);
|
2019-07-07 11:18:12 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
updateUserTokenAppearance(tokenValueContainer, tokenValueElement) {
|
|
|
|
const { tokenValue } = this;
|
|
|
|
const username = this.tokenValue.replace(/^@/, '');
|
|
|
|
|
|
|
|
return (
|
|
|
|
UsersCache.retrieve(username)
|
|
|
|
.then(user => {
|
|
|
|
if (!user) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* eslint-disable no-param-reassign */
|
|
|
|
tokenValueContainer.dataset.originalValue = tokenValue;
|
|
|
|
tokenValueElement.innerHTML = `
|
|
|
|
<img class="avatar s20" src="${user.avatar_url}" alt="">
|
2020-05-24 23:13:21 +05:30
|
|
|
${escape(user.name)}
|
2019-07-07 11:18:12 +05:30
|
|
|
`;
|
|
|
|
/* eslint-enable no-param-reassign */
|
|
|
|
})
|
|
|
|
// ignore error and leave username in the search bar
|
|
|
|
.catch(() => {})
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
updateLabelTokenColor(tokenValueContainer) {
|
|
|
|
const { tokenValue } = this;
|
|
|
|
const filteredSearchInput = FilteredSearchContainer.container.querySelector('.filtered-search');
|
2019-09-04 21:01:54 +05:30
|
|
|
const { labelsEndpoint } = filteredSearchInput.dataset;
|
|
|
|
const labelsEndpointWithParams = FilteredSearchVisualTokens.getEndpointWithQueryParams(
|
|
|
|
`${labelsEndpoint}.json`,
|
2019-07-07 11:18:12 +05:30
|
|
|
filteredSearchInput.dataset.endpointQueryParams,
|
|
|
|
);
|
|
|
|
|
2019-09-04 21:01:54 +05:30
|
|
|
return AjaxCache.retrieve(labelsEndpointWithParams)
|
2019-07-07 11:18:12 +05:30
|
|
|
.then(labels => {
|
|
|
|
const matchingLabel = (labels || []).find(
|
|
|
|
label => `~${DropdownUtils.getEscapedText(label.title)}` === tokenValue,
|
|
|
|
);
|
|
|
|
|
|
|
|
if (!matchingLabel) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
VisualTokenValue.setTokenStyle(
|
|
|
|
tokenValueContainer,
|
|
|
|
matchingLabel.color,
|
|
|
|
matchingLabel.text_color,
|
|
|
|
);
|
|
|
|
})
|
2019-07-31 22:56:46 +05:30
|
|
|
.catch(() => new Flash(__('An error occurred while fetching label colors.')));
|
2019-07-07 11:18:12 +05:30
|
|
|
}
|
|
|
|
|
2020-04-08 14:13:33 +05:30
|
|
|
updateEpicLabel(tokenValueContainer) {
|
|
|
|
const tokenValue = this.tokenValue.replace(/^&/, '');
|
|
|
|
const filteredSearchInput = FilteredSearchContainer.container.querySelector('.filtered-search');
|
|
|
|
const { epicsEndpoint } = filteredSearchInput.dataset;
|
|
|
|
const epicsEndpointWithParams = FilteredSearchVisualTokens.getEndpointWithQueryParams(
|
|
|
|
`${epicsEndpoint}.json`,
|
|
|
|
filteredSearchInput.dataset.endpointQueryParams,
|
|
|
|
);
|
|
|
|
|
|
|
|
return AjaxCache.retrieve(epicsEndpointWithParams)
|
|
|
|
.then(epics => {
|
|
|
|
const matchingEpic = (epics || []).find(epic => epic.id === Number(tokenValue));
|
|
|
|
|
|
|
|
if (!matchingEpic) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
VisualTokenValue.replaceEpicTitle(tokenValueContainer, matchingEpic.title, matchingEpic.id);
|
|
|
|
})
|
|
|
|
.catch(() => new Flash(__('An error occurred while adding formatted title for epic')));
|
|
|
|
}
|
|
|
|
|
|
|
|
static replaceEpicTitle(tokenValueContainer, epicTitle, epicId) {
|
|
|
|
const tokenContainer = tokenValueContainer;
|
|
|
|
|
|
|
|
const valueContainer = tokenContainer.querySelector('.value');
|
|
|
|
|
|
|
|
if (valueContainer) {
|
|
|
|
tokenContainer.dataset.originalValue = valueContainer.innerText;
|
|
|
|
valueContainer.innerText = `"${epicTitle}"::&${epicId}`;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-07 11:18:12 +05:30
|
|
|
static setTokenStyle(tokenValueContainer, backgroundColor, textColor) {
|
|
|
|
const token = tokenValueContainer;
|
|
|
|
|
|
|
|
token.style.backgroundColor = backgroundColor;
|
|
|
|
token.style.color = textColor;
|
|
|
|
|
|
|
|
if (textColor === '#FFFFFF') {
|
|
|
|
const removeToken = token.querySelector('.remove-token');
|
|
|
|
removeToken.classList.add('inverted');
|
|
|
|
}
|
|
|
|
|
|
|
|
return token;
|
|
|
|
}
|
|
|
|
|
|
|
|
updateEmojiTokenAppearance(tokenValueContainer, tokenValueElement) {
|
|
|
|
const container = tokenValueContainer;
|
|
|
|
const element = tokenValueElement;
|
|
|
|
const value = this.tokenValue;
|
|
|
|
|
|
|
|
return (
|
|
|
|
import(/* webpackChunkName: 'emoji' */ '../emoji')
|
|
|
|
.then(Emoji => {
|
|
|
|
if (!Emoji.isEmojiNameValid(value)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
container.dataset.originalValue = value;
|
|
|
|
element.innerHTML = Emoji.glEmojiTag(value);
|
|
|
|
})
|
|
|
|
// ignore error and leave emoji name in the search bar
|
|
|
|
.catch(() => {})
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|