diff options
author | Mike Greiling <mike@pixelcog.com> | 2018-10-10 09:18:49 +0300 |
---|---|---|
committer | Mike Greiling <mike@pixelcog.com> | 2018-10-16 19:52:35 +0300 |
commit | 8b090caf82fedbb5b4ffa8169dfd8774c2416b2c (patch) | |
tree | f814c596665fb70f0c6c3d3c4e08edfdbc5cd6d7 /app | |
parent | 4d0db16f9712f0adbe36b992c28f9d2ec20c301e (diff) |
Prettify environments feature_highlight and filtered_search modules
Diffstat (limited to 'app')
22 files changed, 459 insertions, 405 deletions
diff --git a/app/assets/javascripts/environments/components/container.vue b/app/assets/javascripts/environments/components/container.vue index 9de851c9409..00d197d294f 100644 --- a/app/assets/javascripts/environments/components/container.vue +++ b/app/assets/javascripts/environments/components/container.vue @@ -1,40 +1,40 @@ <script> - import tablePagination from '../../vue_shared/components/table_pagination.vue'; - import environmentTable from '../components/environments_table.vue'; +import tablePagination from '../../vue_shared/components/table_pagination.vue'; +import environmentTable from '../components/environments_table.vue'; - export default { - components: { - environmentTable, - tablePagination, +export default { + components: { + environmentTable, + tablePagination, + }, + props: { + isLoading: { + type: Boolean, + required: true, }, - props: { - isLoading: { - type: Boolean, - required: true, - }, - environments: { - type: Array, - required: true, - }, - pagination: { - type: Object, - required: true, - }, - canCreateDeployment: { - type: Boolean, - required: true, - }, - canReadEnvironment: { - type: Boolean, - required: true, - }, + environments: { + type: Array, + required: true, }, - methods: { - onChangePage(page) { - this.$emit('onChangePage', page); - }, + pagination: { + type: Object, + required: true, }, - }; + canCreateDeployment: { + type: Boolean, + required: true, + }, + canReadEnvironment: { + type: Boolean, + required: true, + }, + }, + methods: { + onChangePage(page) { + this.$emit('onChangePage', page); + }, + }, +}; </script> <template> diff --git a/app/assets/javascripts/environments/components/empty_state.vue b/app/assets/javascripts/environments/components/empty_state.vue index cf78f89981e..28d2dda9e43 100644 --- a/app/assets/javascripts/environments/components/empty_state.vue +++ b/app/assets/javascripts/environments/components/empty_state.vue @@ -1,21 +1,21 @@ <script> - export default { - name: 'EnvironmentsEmptyState', - props: { - newPath: { - type: String, - required: true, - }, - canCreateEnvironment: { - type: Boolean, - required: true, - }, - helpPath: { - type: String, - required: true, - }, +export default { + name: 'EnvironmentsEmptyState', + props: { + newPath: { + type: String, + required: true, }, - }; + canCreateEnvironment: { + type: Boolean, + required: true, + }, + helpPath: { + type: String, + required: true, + }, + }, +}; </script> <template> <div class="blank-state-row"> diff --git a/app/assets/javascripts/environments/components/environment_rollback.vue b/app/assets/javascripts/environments/components/environment_rollback.vue index efbf88d0f11..9e137f79dcc 100644 --- a/app/assets/javascripts/environments/components/environment_rollback.vue +++ b/app/assets/javascripts/environments/components/environment_rollback.vue @@ -38,7 +38,9 @@ export default { computed: { title() { - return this.isLastDeployment ? s__('Environments|Re-deploy to environment') : s__('Environments|Rollback environment'); + return this.isLastDeployment + ? s__('Environments|Re-deploy to environment') + : s__('Environments|Rollback environment'); }, }, diff --git a/app/assets/javascripts/environments/folder/environments_folder_bundle.js b/app/assets/javascripts/environments/folder/environments_folder_bundle.js index de0fbdb2e91..f044d31c776 100644 --- a/app/assets/javascripts/environments/folder/environments_folder_bundle.js +++ b/app/assets/javascripts/environments/folder/environments_folder_bundle.js @@ -5,31 +5,32 @@ import Translate from '../../vue_shared/translate'; Vue.use(Translate); -export default () => new Vue({ - el: '#environments-folder-list-view', - components: { - environmentsFolderApp, - }, - data() { - const environmentsData = document.querySelector(this.$options.el).dataset; +export default () => + new Vue({ + el: '#environments-folder-list-view', + components: { + environmentsFolderApp, + }, + data() { + const environmentsData = document.querySelector(this.$options.el).dataset; - return { - endpoint: environmentsData.endpoint, - folderName: environmentsData.folderName, - cssContainerClass: environmentsData.cssClass, - canCreateDeployment: convertPermissionToBoolean(environmentsData.canCreateDeployment), - canReadEnvironment: convertPermissionToBoolean(environmentsData.canReadEnvironment), - }; - }, - render(createElement) { - return createElement('environments-folder-app', { - props: { - endpoint: this.endpoint, - folderName: this.folderName, - cssContainerClass: this.cssContainerClass, - canCreateDeployment: this.canCreateDeployment, - canReadEnvironment: this.canReadEnvironment, - }, - }); - }, -}); + return { + endpoint: environmentsData.endpoint, + folderName: environmentsData.folderName, + cssContainerClass: environmentsData.cssClass, + canCreateDeployment: convertPermissionToBoolean(environmentsData.canCreateDeployment), + canReadEnvironment: convertPermissionToBoolean(environmentsData.canReadEnvironment), + }; + }, + render(createElement) { + return createElement('environments-folder-app', { + props: { + endpoint: this.endpoint, + folderName: this.folderName, + cssContainerClass: this.cssContainerClass, + canCreateDeployment: this.canCreateDeployment, + canReadEnvironment: this.canReadEnvironment, + }, + }); + }, + }); diff --git a/app/assets/javascripts/environments/folder/environments_folder_view.vue b/app/assets/javascripts/environments/folder/environments_folder_view.vue index e69bfa0b2cc..6be4845fe4c 100644 --- a/app/assets/javascripts/environments/folder/environments_folder_view.vue +++ b/app/assets/javascripts/environments/folder/environments_folder_view.vue @@ -1,46 +1,43 @@ <script> - import environmentsMixin from '../mixins/environments_mixin'; - import CIPaginationMixin from '../../vue_shared/mixins/ci_pagination_api_mixin'; - import StopEnvironmentModal from '../components/stop_environment_modal.vue'; +import environmentsMixin from '../mixins/environments_mixin'; +import CIPaginationMixin from '../../vue_shared/mixins/ci_pagination_api_mixin'; +import StopEnvironmentModal from '../components/stop_environment_modal.vue'; - export default { - components: { - StopEnvironmentModal, - }, +export default { + components: { + StopEnvironmentModal, + }, - mixins: [ - environmentsMixin, - CIPaginationMixin, - ], + mixins: [environmentsMixin, CIPaginationMixin], - props: { - endpoint: { - type: String, - required: true, - }, - folderName: { - type: String, - required: true, - }, - cssContainerClass: { - type: String, - required: true, - }, - canCreateDeployment: { - type: Boolean, - required: true, - }, - canReadEnvironment: { - type: Boolean, - required: true, - }, + props: { + endpoint: { + type: String, + required: true, + }, + folderName: { + type: String, + required: true, + }, + cssContainerClass: { + type: String, + required: true, + }, + canCreateDeployment: { + type: Boolean, + required: true, + }, + canReadEnvironment: { + type: Boolean, + required: true, }, - methods: { - successCallback(resp) { - this.saveData(resp); - }, + }, + methods: { + successCallback(resp) { + this.saveData(resp); }, - }; + }, +}; </script> <template> <div :class="cssContainerClass"> diff --git a/app/assets/javascripts/environments/index.js b/app/assets/javascripts/environments/index.js index afc4aba6554..5b6833fb15d 100644 --- a/app/assets/javascripts/environments/index.js +++ b/app/assets/javascripts/environments/index.js @@ -5,35 +5,36 @@ import Translate from '../vue_shared/translate'; Vue.use(Translate); -export default () => new Vue({ - el: '#environments-list-view', - components: { - environmentsComponent, - }, - data() { - const environmentsData = document.querySelector(this.$options.el).dataset; +export default () => + new Vue({ + el: '#environments-list-view', + components: { + environmentsComponent, + }, + data() { + const environmentsData = document.querySelector(this.$options.el).dataset; - return { - endpoint: environmentsData.environmentsDataEndpoint, - newEnvironmentPath: environmentsData.newEnvironmentPath, - helpPagePath: environmentsData.helpPagePath, - cssContainerClass: environmentsData.cssClass, - canCreateEnvironment: convertPermissionToBoolean(environmentsData.canCreateEnvironment), - canCreateDeployment: convertPermissionToBoolean(environmentsData.canCreateDeployment), - canReadEnvironment: convertPermissionToBoolean(environmentsData.canReadEnvironment), - }; - }, - render(createElement) { - return createElement('environments-component', { - props: { - endpoint: this.endpoint, - newEnvironmentPath: this.newEnvironmentPath, - helpPagePath: this.helpPagePath, - cssContainerClass: this.cssContainerClass, - canCreateEnvironment: this.canCreateEnvironment, - canCreateDeployment: this.canCreateDeployment, - canReadEnvironment: this.canReadEnvironment, - }, - }); - }, -}); + return { + endpoint: environmentsData.environmentsDataEndpoint, + newEnvironmentPath: environmentsData.newEnvironmentPath, + helpPagePath: environmentsData.helpPagePath, + cssContainerClass: environmentsData.cssClass, + canCreateEnvironment: convertPermissionToBoolean(environmentsData.canCreateEnvironment), + canCreateDeployment: convertPermissionToBoolean(environmentsData.canCreateDeployment), + canReadEnvironment: convertPermissionToBoolean(environmentsData.canReadEnvironment), + }; + }, + render(createElement) { + return createElement('environments-component', { + props: { + endpoint: this.endpoint, + newEnvironmentPath: this.newEnvironmentPath, + helpPagePath: this.helpPagePath, + cssContainerClass: this.cssContainerClass, + canCreateEnvironment: this.canCreateEnvironment, + canCreateDeployment: this.canCreateDeployment, + canReadEnvironment: this.canReadEnvironment, + }, + }); + }, + }); diff --git a/app/assets/javascripts/environments/mixins/environments_mixin.js b/app/assets/javascripts/environments/mixins/environments_mixin.js index d71964612c5..96dc1f07cb9 100644 --- a/app/assets/javascripts/environments/mixins/environments_mixin.js +++ b/app/assets/javascripts/environments/mixins/environments_mixin.js @@ -4,9 +4,7 @@ import _ from 'underscore'; import Visibility from 'visibilityjs'; import Poll from '../../lib/utils/poll'; -import { - getParameterByName, -} from '../../lib/utils/common_utils'; +import { getParameterByName } from '../../lib/utils/common_utils'; import { s__ } from '../../locale'; import Flash from '../../flash'; import eventHub from '../event_hub'; @@ -19,7 +17,6 @@ import tabs from '../../vue_shared/components/navigation_tabs.vue'; import container from '../components/container.vue'; export default { - components: { environmentTable, container, @@ -65,7 +62,8 @@ export default { updateContent(parameters) { this.updateInternalState(parameters); // fetch new data - return this.service.fetchEnvironments(this.requestData) + return this.service + .fetchEnvironments(this.requestData) .then(response => this.successCallback(response)) .then(() => { // restart polling @@ -88,7 +86,8 @@ export default { if (!this.isMakingRequest) { this.isLoading = true; - this.service.postAction(endpoint) + this.service + .postAction(endpoint) .then(() => this.fetchEnvironments()) .catch(() => { this.isLoading = false; @@ -100,7 +99,8 @@ export default { fetchEnvironments() { this.isLoading = true; - return this.service.fetchEnvironments(this.requestData) + return this.service + .fetchEnvironments(this.requestData) .then(this.successCallback) .catch(this.errorCallback); }, @@ -111,7 +111,9 @@ export default { stopEnvironment(environment) { const endpoint = environment.stop_path; - const errorMessage = s__('Environments|An error occurred while stopping the environment, please try again'); + const errorMessage = s__( + 'Environments|An error occurred while stopping the environment, please try again', + ); this.postAction({ endpoint, errorMessage }); }, }, @@ -149,7 +151,7 @@ export default { data: this.requestData, successCallback: this.successCallback, errorCallback: this.errorCallback, - notificationCallback: (isMakingRequest) => { + notificationCallback: isMakingRequest => { this.isMakingRequest = isMakingRequest; }, }); diff --git a/app/assets/javascripts/feature_highlight/feature_highlight.js b/app/assets/javascripts/feature_highlight/feature_highlight.js index 03dfa942d69..173fe7c69de 100644 --- a/app/assets/javascripts/feature_highlight/feature_highlight.js +++ b/app/assets/javascripts/feature_highlight/feature_highlight.js @@ -1,13 +1,6 @@ import $ from 'jquery'; -import { - getSelector, - inserted, -} from './feature_highlight_helper'; -import { - togglePopover, - mouseenter, - debouncedMouseleave, -} from '../shared/popover'; +import { getSelector, inserted } from './feature_highlight_helper'; +import { togglePopover, mouseenter, debouncedMouseleave } from '../shared/popover'; export function setupFeatureHighlightPopover(id, debounceTimeout = 300) { const $selector = $(getSelector(id)); @@ -41,8 +34,9 @@ export function setupFeatureHighlightPopover(id, debounceTimeout = 300) { export function findHighestPriorityFeature() { let priorityFeature; - const sortedFeatureEls = [].slice.call(document.querySelectorAll('.js-feature-highlight')).sort((a, b) => - (a.dataset.highlightPriority || 0) < (b.dataset.highlightPriority || 0)); + const sortedFeatureEls = [].slice + .call(document.querySelectorAll('.js-feature-highlight')) + .sort((a, b) => (a.dataset.highlightPriority || 0) < (b.dataset.highlightPriority || 0)); const [priorityFeatureEl] = sortedFeatureEls; if (priorityFeatureEl) { diff --git a/app/assets/javascripts/feature_highlight/feature_highlight_helper.js b/app/assets/javascripts/feature_highlight/feature_highlight_helper.js index d5b97ebb264..fd9433b625c 100644 --- a/app/assets/javascripts/feature_highlight/feature_highlight_helper.js +++ b/app/assets/javascripts/feature_highlight/feature_highlight_helper.js @@ -8,10 +8,17 @@ import { togglePopover } from '../shared/popover'; export const getSelector = highlightId => `.js-feature-highlight[data-highlight=${highlightId}]`; export function dismiss(highlightId) { - axios.post(this.attr('data-dismiss-endpoint'), { - feature_name: highlightId, - }) - .catch(() => Flash(__('An error occurred while dismissing the feature highlight. Refresh the page and try dismissing again.'))); + axios + .post(this.attr('data-dismiss-endpoint'), { + feature_name: highlightId, + }) + .catch(() => + Flash( + __( + 'An error occurred while dismissing the feature highlight. Refresh the page and try dismissing again.', + ), + ), + ); togglePopover.call(this, false); this.hide(); @@ -23,8 +30,7 @@ export function inserted() { const $popover = $(this); const dismissWrapper = dismiss.bind($popover, highlightId); - $(`#${popoverId} .dismiss-feature-highlight`) - .on('click', dismissWrapper); + $(`#${popoverId} .dismiss-feature-highlight`).on('click', dismissWrapper); const lazyImg = $(`#${popoverId} .feature-highlight-illustration`)[0]; if (lazyImg) { diff --git a/app/assets/javascripts/filtered_search/admin_runners_filtered_search_token_keys.js b/app/assets/javascripts/filtered_search/admin_runners_filtered_search_token_keys.js index d7aa4ce597f..934375023ba 100644 --- a/app/assets/javascripts/filtered_search/admin_runners_filtered_search_token_keys.js +++ b/app/assets/javascripts/filtered_search/admin_runners_filtered_search_token_keys.js @@ -1,20 +1,23 @@ import FilteredSearchTokenKeys from './filtered_search_token_keys'; -const tokenKeys = [{ - key: 'status', - type: 'string', - param: 'status', - symbol: '', - icon: 'messages', - tag: 'status', -}, { - key: 'type', - type: 'string', - param: 'type', - symbol: '', - icon: 'cube', - tag: 'type', -}]; +const tokenKeys = [ + { + key: 'status', + type: 'string', + param: 'status', + symbol: '', + icon: 'messages', + tag: 'status', + }, + { + key: 'type', + type: 'string', + param: 'type', + symbol: '', + icon: 'cube', + tag: 'type', + }, +]; const AdminRunnersFilteredSearchTokenKeys = new FilteredSearchTokenKeys(tokenKeys); diff --git a/app/assets/javascripts/filtered_search/components/recent_searches_dropdown_content.vue b/app/assets/javascripts/filtered_search/components/recent_searches_dropdown_content.vue index 21b5ccdb613..b9bc5e6ed7f 100644 --- a/app/assets/javascripts/filtered_search/components/recent_searches_dropdown_content.vue +++ b/app/assets/javascripts/filtered_search/components/recent_searches_dropdown_content.vue @@ -21,9 +21,11 @@ export default { }, computed: { processedItems() { - return this.items.map((item) => { - const { tokens, searchToken } - = FilteredSearchTokenizer.processTokens(item, this.allowedKeys); + return this.items.map(item => { + const { tokens, searchToken } = FilteredSearchTokenizer.processTokens( + item, + this.allowedKeys, + ); const resultantTokens = tokens.map(token => ({ prefix: `${token.key}:`, diff --git a/app/assets/javascripts/filtered_search/dropdown_emoji.js b/app/assets/javascripts/filtered_search/dropdown_emoji.js index 5ddd0e5e690..af7936a92fb 100644 --- a/app/assets/javascripts/filtered_search/dropdown_emoji.js +++ b/app/assets/javascripts/filtered_search/dropdown_emoji.js @@ -24,8 +24,12 @@ export default class DropdownEmoji extends FilteredSearchDropdown { }; import(/* webpackChunkName: 'emoji' */ '~/emoji') - .then(({ glEmojiTag }) => { this.glEmojiTag = glEmojiTag; }) - .catch(() => { /* ignore error and leave emoji name in the search bar */ }); + .then(({ glEmojiTag }) => { + this.glEmojiTag = glEmojiTag; + }) + .catch(() => { + /* ignore error and leave emoji name in the search bar */ + }); this.unbindEvents(); this.bindEvents(); @@ -48,7 +52,7 @@ export default class DropdownEmoji extends FilteredSearchDropdown { } itemClicked(e) { - super.itemClicked(e, (selected) => { + super.itemClicked(e, selected => { const name = selected.querySelector('.js-data-value').innerText.trim(); return DropdownUtils.getEscapedText(name); }); @@ -64,7 +68,7 @@ export default class DropdownEmoji extends FilteredSearchDropdown { // Replace empty gl-emoji tag to real content const dropdownItems = [...this.dropdown.querySelectorAll('.filter-dropdown-item')]; - dropdownItems.forEach((dropdownItem) => { + dropdownItems.forEach(dropdownItem => { const name = dropdownItem.querySelector('.js-data-value').innerText; const emojiTag = this.glEmojiTag(name); const emojiElement = dropdownItem.querySelector('gl-emoji'); @@ -73,7 +77,6 @@ export default class DropdownEmoji extends FilteredSearchDropdown { } init() { - this.droplab - .addHook(this.input, this.dropdown, [Ajax, Filter], this.config).init(); + this.droplab.addHook(this.input, this.dropdown, [Ajax, Filter], this.config).init(); } } diff --git a/app/assets/javascripts/filtered_search/dropdown_hint.js b/app/assets/javascripts/filtered_search/dropdown_hint.js index c568f4e4ebf..1a1135ae929 100644 --- a/app/assets/javascripts/filtered_search/dropdown_hint.js +++ b/app/assets/javascripts/filtered_search/dropdown_hint.js @@ -41,8 +41,10 @@ export default class DropdownHint extends FilteredSearchDropdown { previousInputValues.forEach((value, index) => { searchTerms.push(value); - if (index === previousInputValues.length - 1 - && token.indexOf(value.toLowerCase()) !== -1) { + if ( + index === previousInputValues.length - 1 && + token.indexOf(value.toLowerCase()) !== -1 + ) { searchTerms.pop(); } }); @@ -64,13 +66,12 @@ export default class DropdownHint extends FilteredSearchDropdown { } renderContent() { - const dropdownData = this.tokenKeys.get() - .map(tokenKey => ({ - icon: `${gon.sprite_icons}#${tokenKey.icon}`, - hint: tokenKey.key, - tag: `:${tokenKey.tag}`, - type: tokenKey.type, - })); + const dropdownData = this.tokenKeys.get().map(tokenKey => ({ + icon: `${gon.sprite_icons}#${tokenKey.icon}`, + hint: tokenKey.key, + tag: `:${tokenKey.tag}`, + type: tokenKey.type, + })); this.droplab.changeHookList(this.hookId, this.dropdown, [Filter], this.config); this.droplab.setData(this.hookId, dropdownData); diff --git a/app/assets/javascripts/filtered_search/dropdown_non_user.js b/app/assets/javascripts/filtered_search/dropdown_non_user.js index 2ffda7e2037..0264f934914 100644 --- a/app/assets/javascripts/filtered_search/dropdown_non_user.js +++ b/app/assets/javascripts/filtered_search/dropdown_non_user.js @@ -29,20 +29,18 @@ export default class DropdownNonUser extends FilteredSearchDropdown { } itemClicked(e) { - super.itemClicked(e, (selected) => { + super.itemClicked(e, selected => { const title = selected.querySelector('.js-data-value').innerText.trim(); return `${this.symbol}${DropdownUtils.getEscapedText(title)}`; }); } renderContent(forceShowList = false) { - this.droplab - .changeHookList(this.hookId, this.dropdown, [Ajax, Filter], this.config); + this.droplab.changeHookList(this.hookId, this.dropdown, [Ajax, Filter], this.config); super.renderContent(forceShowList); } init() { - this.droplab - .addHook(this.input, this.dropdown, [Ajax, Filter], this.config).init(); + this.droplab.addHook(this.input, this.dropdown, [Ajax, Filter], this.config).init(); } } diff --git a/app/assets/javascripts/filtered_search/dropdown_utils.js b/app/assets/javascripts/filtered_search/dropdown_utils.js index 6da6ca10008..1b79a3320c6 100644 --- a/app/assets/javascripts/filtered_search/dropdown_utils.js +++ b/app/assets/javascripts/filtered_search/dropdown_utils.js @@ -41,7 +41,7 @@ export default class DropdownUtils { // Removes the first character if it is a quotation so that we can search // with multiple words - if ((value[0] === '"' || value[0] === '\'') && title.indexOf(' ') !== -1) { + if ((value[0] === '"' || value[0] === "'") && title.indexOf(' ') !== -1) { value = value.slice(1); } @@ -82,11 +82,13 @@ export default class DropdownUtils { // Reduce the colors to 4 colors.length = Math.min(colors.length, 4); - const color = colors.map((c, i) => { - const percentFirst = Math.floor(spacing * i); - const percentSecond = Math.floor(spacing * (i + 1)); - return `${c} ${percentFirst}%, ${c} ${percentSecond}%`; - }).join(', '); + const color = colors + .map((c, i) => { + const percentFirst = Math.floor(spacing * i); + const percentSecond = Math.floor(spacing * (i + 1)); + return `${c} ${percentFirst}%, ${c} ${percentSecond}%`; + }) + .join(', '); return `linear-gradient(${color})`; } @@ -97,17 +99,16 @@ export default class DropdownUtils { data.forEach(DropdownUtils.mergeDuplicateLabels.bind(null, dataMap)); - Object.keys(dataMap) - .forEach((key) => { - const label = dataMap[key]; + Object.keys(dataMap).forEach(key => { + const label = dataMap[key]; - if (label.multipleColors) { - label.color = DropdownUtils.duplicateLabelColor(label.multipleColors); - label.text_color = '#000000'; - } + if (label.multipleColors) { + label.color = DropdownUtils.duplicateLabelColor(label.multipleColors); + label.text_color = '#000000'; + } - results.push(label); - }); + results.push(label); + }); results.preprocessed = true; @@ -118,8 +119,7 @@ export default class DropdownUtils { const { input, allowedKeys } = config; const updatedItem = item; const searchInput = DropdownUtils.getSearchQuery(input); - const { lastToken, tokens } = - FilteredSearchTokenizer.processTokens(searchInput, allowedKeys); + const { lastToken, tokens } = FilteredSearchTokenizer.processTokens(searchInput, allowedKeys); const lastKey = lastToken.key || lastToken || ''; const allowMultiple = item.type === 'array'; const itemInExistingTokens = tokens.some(t => t.key === item.hint); @@ -154,7 +154,10 @@ export default class DropdownUtils { static getVisualTokenValues(visualToken) { const tokenName = visualToken && visualToken.querySelector('.name').textContent.trim(); - let tokenValue = visualToken && visualToken.querySelector('.value') && visualToken.querySelector('.value').textContent.trim(); + let tokenValue = + visualToken && + visualToken.querySelector('.value') && + visualToken.querySelector('.value').textContent.trim(); if (tokenName === 'label' && tokenValue) { // remove leading symbol and wrapping quotes tokenValue = tokenValue.replace(/^~("|')?(.*)/, '$2').replace(/("|')$/, ''); @@ -174,7 +177,7 @@ export default class DropdownUtils { tokens.splice(inputIndex + 1); } - tokens.forEach((token) => { + tokens.forEach(token => { if (token.classList.contains('js-visual-token')) { const name = token.querySelector('.name'); const value = token.querySelector('.value'); @@ -194,8 +197,9 @@ export default class DropdownUtils { values.push(name.innerText); } } else if (token.classList.contains('input-token')) { - const { isLastVisualTokenValid } = - FilteredSearchVisualTokens.getLastVisualTokenBeforeInput(); + const { + isLastVisualTokenValid, + } = FilteredSearchVisualTokens.getLastVisualTokenBeforeInput(); const input = FilteredSearchContainer.container.querySelector('.filtered-search'); const inputValue = input && input.value; @@ -209,9 +213,7 @@ export default class DropdownUtils { } }); - return values - .map(value => value.trim()) - .join(' '); + return values.map(value => value.trim()).join(' '); } static getSearchInput(filteredSearchInput) { @@ -227,7 +229,9 @@ export default class DropdownUtils { // Replace all spaces inside quote marks with underscores // (will continue to match entire string until an end quote is found if any) // This helps with matching the beginning & end of a token:key - inputValue = inputValue.replace(/(('[^']*'{0,1})|("[^"]*"{0,1})|:\s+)/g, str => str.replace(/\s/g, '_')); + inputValue = inputValue.replace(/(('[^']*'{0,1})|("[^"]*"{0,1})|:\s+)/g, str => + str.replace(/\s/g, '_'), + ); // Get the right position for the word selected // Regex matches first space diff --git a/app/assets/javascripts/filtered_search/filtered_search_dropdown.js b/app/assets/javascripts/filtered_search/filtered_search_dropdown.js index fb4ae1d17dd..4eb67ff7649 100644 --- a/app/assets/javascripts/filtered_search/filtered_search_dropdown.js +++ b/app/assets/javascripts/filtered_search/filtered_search_dropdown.js @@ -87,10 +87,12 @@ export default class FilteredSearchDropdown { dispatchInputEvent() { // Propogate input change to FilteredSearchDropdownManager // so that it can determine which dropdowns to open - this.input.dispatchEvent(new CustomEvent('input', { - bubbles: true, - cancelable: true, - })); + this.input.dispatchEvent( + new CustomEvent('input', { + bubbles: true, + cancelable: true, + }), + ); } dispatchFormSubmitEvent() { @@ -114,7 +116,7 @@ export default class FilteredSearchDropdown { if (!data) return; - const results = data.map((o) => { + const results = data.map(o => { const updated = o; updated.droplab_hidden = false; return updated; diff --git a/app/assets/javascripts/filtered_search/filtered_search_token_keys.js b/app/assets/javascripts/filtered_search/filtered_search_token_keys.js index a09ad3e4758..e01dedbb57c 100644 --- a/app/assets/javascripts/filtered_search/filtered_search_token_keys.js +++ b/app/assets/javascripts/filtered_search/filtered_search_token_keys.js @@ -42,19 +42,21 @@ export default class FilteredSearchTokenKeys { } searchByKeyParam(keyParam) { - return this.tokenKeysWithAlternative.find((tokenKey) => { - let tokenKeyParam = tokenKey.key; + return ( + this.tokenKeysWithAlternative.find(tokenKey => { + let tokenKeyParam = tokenKey.key; - // Replace hyphen with underscore to compare keyParam with tokenKeyParam - // e.g. 'my-reaction' => 'my_reaction' - tokenKeyParam = tokenKeyParam.replace('-', '_'); + // Replace hyphen with underscore to compare keyParam with tokenKeyParam + // e.g. 'my-reaction' => 'my_reaction' + tokenKeyParam = tokenKeyParam.replace('-', '_'); - if (tokenKey.param) { - tokenKeyParam += `_${tokenKey.param}`; - } + if (tokenKey.param) { + tokenKeyParam += `_${tokenKey.param}`; + } - return keyParam === tokenKeyParam; - }) || null; + return keyParam === tokenKeyParam; + }) || null + ); } searchByConditionUrl(url) { @@ -62,8 +64,10 @@ export default class FilteredSearchTokenKeys { } searchByConditionKeyValue(key, value) { - return this.conditions - .find(condition => condition.tokenKey === key && condition.value === value) || null; + return ( + this.conditions.find(condition => condition.tokenKey === key && condition.value === value) || + null + ); } addExtraTokensForMergeRequests() { diff --git a/app/assets/javascripts/filtered_search/filtered_search_tokenizer.js b/app/assets/javascripts/filtered_search/filtered_search_tokenizer.js index d75610f6d68..b5c4cb15aac 100644 --- a/app/assets/javascripts/filtered_search/filtered_search_tokenizer.js +++ b/app/assets/javascripts/filtered_search/filtered_search_tokenizer.js @@ -4,41 +4,48 @@ export default class FilteredSearchTokenizer { static processTokens(input, allowedKeys) { // Regex extracts `(token):(symbol)(value)` // Values that start with a double quote must end in a double quote (same for single) - const tokenRegex = new RegExp(`(${allowedKeys.join('|')}):([~%@]?)(?:('[^']*'{0,1})|("[^"]*"{0,1})|(\\S+))`, 'g'); + const tokenRegex = new RegExp( + `(${allowedKeys.join('|')}):([~%@]?)(?:('[^']*'{0,1})|("[^"]*"{0,1})|(\\S+))`, + 'g', + ); const tokens = []; const tokenIndexes = []; // stores key+value for simple search let lastToken = null; - const searchToken = input.replace(tokenRegex, (match, key, symbol, v1, v2, v3) => { - let tokenValue = v1 || v2 || v3; - let tokenSymbol = symbol; - let tokenIndex = ''; - - if (tokenValue === '~' || tokenValue === '%' || tokenValue === '@') { - tokenSymbol = tokenValue; - tokenValue = ''; - } - - tokenIndex = `${key}:${tokenValue}`; - - // Prevent adding duplicates - if (tokenIndexes.indexOf(tokenIndex) === -1) { - tokenIndexes.push(tokenIndex); - - tokens.push({ - key, - value: tokenValue || '', - symbol: tokenSymbol || '', - }); - } - - return ''; - }).replace(/\s{2,}/g, ' ').trim() || ''; + const searchToken = + input + .replace(tokenRegex, (match, key, symbol, v1, v2, v3) => { + let tokenValue = v1 || v2 || v3; + let tokenSymbol = symbol; + let tokenIndex = ''; + + if (tokenValue === '~' || tokenValue === '%' || tokenValue === '@') { + tokenSymbol = tokenValue; + tokenValue = ''; + } + + tokenIndex = `${key}:${tokenValue}`; + + // Prevent adding duplicates + if (tokenIndexes.indexOf(tokenIndex) === -1) { + tokenIndexes.push(tokenIndex); + + tokens.push({ + key, + value: tokenValue || '', + symbol: tokenSymbol || '', + }); + } + + return ''; + }) + .replace(/\s{2,}/g, ' ') + .trim() || ''; if (tokens.length > 0) { const last = tokens[tokens.length - 1]; const lastString = `${last.key}:${last.symbol}${last.value}`; - lastToken = input.lastIndexOf(lastString) === - input.length - lastString.length ? last : searchToken; + lastToken = + input.lastIndexOf(lastString) === input.length - lastString.length ? last : searchToken; } else { lastToken = searchToken; } diff --git a/app/assets/javascripts/filtered_search/filtered_search_visual_tokens.js b/app/assets/javascripts/filtered_search/filtered_search_visual_tokens.js index 0854c1822fb..c23d4c484a5 100644 --- a/app/assets/javascripts/filtered_search/filtered_search_visual_tokens.js +++ b/app/assets/javascripts/filtered_search/filtered_search_visual_tokens.js @@ -13,7 +13,10 @@ export default class FilteredSearchVisualTokens { return { lastVisualToken, - isLastVisualTokenValid: lastVisualToken === null || lastVisualToken.className.indexOf('filtered-search-term') !== -1 || (lastVisualToken && lastVisualToken.querySelector('.value') !== null), + isLastVisualTokenValid: + lastVisualToken === null || + lastVisualToken.className.indexOf('filtered-search-term') !== -1 || + (lastVisualToken && lastVisualToken.querySelector('.value') !== null), }; } @@ -33,7 +36,9 @@ export default class FilteredSearchVisualTokens { } static unselectTokens() { - const otherTokens = FilteredSearchContainer.container.querySelectorAll('.js-visual-token .selectable.selected'); + const otherTokens = FilteredSearchContainer.container.querySelectorAll( + '.js-visual-token .selectable.selected', + ); [].forEach.call(otherTokens, t => t.classList.remove('selected')); } @@ -56,11 +61,7 @@ export default class FilteredSearchVisualTokens { } static createVisualTokenElementHTML(options = {}) { - const { - canEdit = true, - uppercaseTokenName = false, - capitalizeTokenValue = false, - } = options; + const { canEdit = true, uppercaseTokenName = false, capitalizeTokenValue = false } = options; return ` <div class="${canEdit ? 'selectable' : 'hidden'}" role="button"> @@ -115,15 +116,20 @@ export default class FilteredSearchVisualTokens { return AjaxCache.retrieve(labelsEndpoint) .then(FilteredSearchVisualTokens.preprocessLabel.bind(null, labelsEndpoint)) - .then((labels) => { - const matchingLabel = (labels || []).find(label => `~${DropdownUtils.getEscapedText(label.title)}` === tokenValue); + .then(labels => { + const matchingLabel = (labels || []).find( + label => `~${DropdownUtils.getEscapedText(label.title)}` === tokenValue, + ); if (!matchingLabel) { return; } - FilteredSearchVisualTokens - .setTokenStyle(tokenValueContainer, matchingLabel.color, matchingLabel.text_color); + FilteredSearchVisualTokens.setTokenStyle( + tokenValueContainer, + matchingLabel.color, + matchingLabel.text_color, + ); }) .catch(() => new Flash('An error occurred while fetching label colors.')); } @@ -134,39 +140,43 @@ export default class FilteredSearchVisualTokens { } const username = tokenValue.replace(/^@/, ''); - return UsersCache.retrieve(username) - .then((user) => { - if (!user) { - return; - } - - /* eslint-disable no-param-reassign */ - tokenValueContainer.dataset.originalValue = tokenValue; - tokenValueElement.innerHTML = ` + 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=""> ${_.escape(user.name)} `; - /* eslint-enable no-param-reassign */ - }) - // ignore error and leave username in the search bar - .catch(() => { }); + /* eslint-enable no-param-reassign */ + }) + // ignore error and leave username in the search bar + .catch(() => {}) + ); } static updateEmojiTokenAppearance(tokenValueContainer, tokenValueElement, tokenValue) { const container = tokenValueContainer; const element = tokenValueElement; - return import(/* webpackChunkName: 'emoji' */ '../emoji') - .then((Emoji) => { - if (!Emoji.isEmojiNameValid(tokenValue)) { - return; - } - - container.dataset.originalValue = tokenValue; - element.innerHTML = Emoji.glEmojiTag(tokenValue); - }) - // ignore error and leave emoji name in the search bar - .catch(() => { }); + return ( + import(/* webpackChunkName: 'emoji' */ '../emoji') + .then(Emoji => { + if (!Emoji.isEmojiNameValid(tokenValue)) { + return; + } + + container.dataset.originalValue = tokenValue; + element.innerHTML = Emoji.glEmojiTag(tokenValue); + }) + // ignore error and leave emoji name in the search bar + .catch(() => {}) + ); } static renderVisualTokenValue(parentElement, tokenName, tokenValue) { @@ -177,24 +187,23 @@ export default class FilteredSearchVisualTokens { const tokenType = tokenName.toLowerCase(); if (tokenType === 'label') { FilteredSearchVisualTokens.updateLabelTokenColor(tokenValueContainer, tokenValue); - } else if ((tokenType === 'author') || (tokenType === 'assignee')) { + } else if (tokenType === 'author' || tokenType === 'assignee') { FilteredSearchVisualTokens.updateUserTokenAppearance( - tokenValueContainer, tokenValueElement, tokenValue, + tokenValueContainer, + tokenValueElement, + tokenValue, ); } else if (tokenType === 'my-reaction') { FilteredSearchVisualTokens.updateEmojiTokenAppearance( - tokenValueContainer, tokenValueElement, tokenValue, + tokenValueContainer, + tokenValueElement, + tokenValue, ); } } static addVisualTokenElement(name, value, options = {}) { - const { - isSearchTerm = false, - canEdit, - uppercaseTokenName, - capitalizeTokenValue, - } = options; + const { isSearchTerm = false, canEdit, uppercaseTokenName, capitalizeTokenValue } = options; const li = document.createElement('li'); li.classList.add('js-visual-token'); li.classList.add(isSearchTerm ? 'filtered-search-term' : 'filtered-search-token'); @@ -217,8 +226,10 @@ export default class FilteredSearchVisualTokens { } static addValueToPreviousVisualTokenElement(value) { - const { lastVisualToken, isLastVisualTokenValid } = - FilteredSearchVisualTokens.getLastVisualTokenBeforeInput(); + const { + lastVisualToken, + isLastVisualTokenValid, + } = FilteredSearchVisualTokens.getLastVisualTokenBeforeInput(); if (!isLastVisualTokenValid && lastVisualToken.classList.contains('filtered-search-token')) { const name = FilteredSearchVisualTokens.getLastTokenPartial(); @@ -228,13 +239,15 @@ export default class FilteredSearchVisualTokens { } } - static addFilterVisualToken(tokenName, tokenValue, { - canEdit, - uppercaseTokenName = false, - capitalizeTokenValue = false, - } = {}) { - const { lastVisualToken, isLastVisualTokenValid } - = FilteredSearchVisualTokens.getLastVisualTokenBeforeInput(); + static addFilterVisualToken( + tokenName, + tokenValue, + { canEdit, uppercaseTokenName = false, capitalizeTokenValue = false } = {}, + ) { + const { + lastVisualToken, + isLastVisualTokenValid, + } = FilteredSearchVisualTokens.getLastVisualTokenBeforeInput(); const { addVisualTokenElement } = FilteredSearchVisualTokens; if (isLastVisualTokenValid) { @@ -308,8 +321,7 @@ export default class FilteredSearchVisualTokens { static tokenizeInput() { const input = FilteredSearchContainer.container.querySelector('.filtered-search'); - const { isLastVisualTokenValid } = - FilteredSearchVisualTokens.getLastVisualTokenBeforeInput(); + const { isLastVisualTokenValid } = FilteredSearchVisualTokens.getLastVisualTokenBeforeInput(); if (input.value) { if (isLastVisualTokenValid) { @@ -375,8 +387,7 @@ export default class FilteredSearchVisualTokens { FilteredSearchVisualTokens.tokenizeInput(); if (!tokenContainer.lastElementChild.isEqualNode(inputLi)) { - const { isLastVisualTokenValid } = - FilteredSearchVisualTokens.getLastVisualTokenBeforeInput(); + const { isLastVisualTokenValid } = FilteredSearchVisualTokens.getLastVisualTokenBeforeInput(); if (!isLastVisualTokenValid) { const lastPartial = FilteredSearchVisualTokens.getLastTokenPartial(); diff --git a/app/assets/javascripts/filtered_search/issuable_filtered_search_token_keys.js b/app/assets/javascripts/filtered_search/issuable_filtered_search_token_keys.js index cc7291c9f59..c4f0c41d3a8 100644 --- a/app/assets/javascripts/filtered_search/issuable_filtered_search_token_keys.js +++ b/app/assets/javascripts/filtered_search/issuable_filtered_search_token_keys.js @@ -1,34 +1,39 @@ import FilteredSearchTokenKeys from './filtered_search_token_keys'; -export const tokenKeys = [{ - key: 'author', - type: 'string', - param: 'username', - symbol: '@', - icon: 'pencil', - tag: '@author', -}, { - key: 'assignee', - type: 'string', - param: 'username', - symbol: '@', - icon: 'user', - tag: '@assignee', -}, { - key: 'milestone', - type: 'string', - param: 'title', - symbol: '%', - icon: 'clock', - tag: '%milestone', -}, { - key: 'label', - type: 'array', - param: 'name[]', - symbol: '~', - icon: 'labels', - tag: '~label', -}]; +export const tokenKeys = [ + { + key: 'author', + type: 'string', + param: 'username', + symbol: '@', + icon: 'pencil', + tag: '@author', + }, + { + key: 'assignee', + type: 'string', + param: 'username', + symbol: '@', + icon: 'user', + tag: '@assignee', + }, + { + key: 'milestone', + type: 'string', + param: 'title', + symbol: '%', + icon: 'clock', + tag: '%milestone', + }, + { + key: 'label', + type: 'array', + param: 'name[]', + symbol: '~', + icon: 'labels', + tag: '~label', + }, +]; if (gon.current_user_id) { // Appending tokenkeys only logged-in @@ -42,36 +47,47 @@ if (gon.current_user_id) { }); } -export const alternativeTokenKeys = [{ - key: 'label', - type: 'string', - param: 'name', - symbol: '~', -}]; +export const alternativeTokenKeys = [ + { + key: 'label', + type: 'string', + param: 'name', + symbol: '~', + }, +]; -export const conditions = [{ - url: 'assignee_id=0', - tokenKey: 'assignee', - value: 'none', -}, { - url: 'milestone_title=No+Milestone', - tokenKey: 'milestone', - value: 'none', -}, { - url: 'milestone_title=%23upcoming', - tokenKey: 'milestone', - value: 'upcoming', -}, { - url: 'milestone_title=%23started', - tokenKey: 'milestone', - value: 'started', -}, { - url: 'label_name[]=No+Label', - tokenKey: 'label', - value: 'none', -}]; +export const conditions = [ + { + url: 'assignee_id=0', + tokenKey: 'assignee', + value: 'none', + }, + { + url: 'milestone_title=No+Milestone', + tokenKey: 'milestone', + value: 'none', + }, + { + url: 'milestone_title=%23upcoming', + tokenKey: 'milestone', + value: 'upcoming', + }, + { + url: 'milestone_title=%23started', + tokenKey: 'milestone', + value: 'started', + }, + { + url: 'label_name[]=No+Label', + tokenKey: 'label', + value: 'none', + }, +]; -const IssuableFilteredSearchTokenKeys = - new FilteredSearchTokenKeys(tokenKeys, alternativeTokenKeys, conditions); +const IssuableFilteredSearchTokenKeys = new FilteredSearchTokenKeys( + tokenKeys, + alternativeTokenKeys, + conditions, +); export default IssuableFilteredSearchTokenKeys; diff --git a/app/assets/javascripts/filtered_search/recent_searches_root.js b/app/assets/javascripts/filtered_search/recent_searches_root.js index c1efa9c86f4..6c8e77a7fe5 100644 --- a/app/assets/javascripts/filtered_search/recent_searches_root.js +++ b/app/assets/javascripts/filtered_search/recent_searches_root.js @@ -3,11 +3,7 @@ import RecentSearchesDropdownContent from './components/recent_searches_dropdown import eventHub from './event_hub'; class RecentSearchesRoot { - constructor( - recentSearchesStore, - recentSearchesService, - wrapperElement, - ) { + constructor(recentSearchesStore, recentSearchesService, wrapperElement) { this.store = recentSearchesStore; this.service = recentSearchesService; this.wrapperElement = wrapperElement; @@ -35,7 +31,9 @@ class RecentSearchesRoot { components: { RecentSearchesDropdownContent, }, - data() { return state; }, + data() { + return state; + }, template: ` <recent-searches-dropdown-content :items="recentSearches" @@ -57,7 +55,6 @@ class RecentSearchesRoot { this.vm.$destroy(); } } - } export default RecentSearchesRoot; diff --git a/app/assets/javascripts/filtered_search/stores/recent_searches_store.js b/app/assets/javascripts/filtered_search/stores/recent_searches_store.js index aaa0c349d93..76d40bfdaf8 100644 --- a/app/assets/javascripts/filtered_search/stores/recent_searches_store.js +++ b/app/assets/javascripts/filtered_search/stores/recent_searches_store.js @@ -2,11 +2,14 @@ import _ from 'underscore'; class RecentSearchesStore { constructor(initialState = {}, allowedKeys) { - this.state = Object.assign({ - isLocalStorageAvailable: true, - recentSearches: [], - allowedKeys, - }, initialState); + this.state = Object.assign( + { + isLocalStorageAvailable: true, + recentSearches: [], + allowedKeys, + }, + initialState, + ); } addRecentSearch(newSearch) { |