diff --git a/.gitlab/ci/qa-common/main.gitlab-ci.yml b/.gitlab/ci/qa-common/main.gitlab-ci.yml index ab3cc773a09..5d9438cc5e6 100644 --- a/.gitlab/ci/qa-common/main.gitlab-ci.yml +++ b/.gitlab/ci/qa-common/main.gitlab-ci.yml @@ -5,7 +5,7 @@ workflow: name: $PIPELINE_NAME include: - - component: "gitlab.com/gitlab-org/quality/pipeline-common/allure-report@7.13.1" + - component: "gitlab.com/gitlab-org/quality/pipeline-common/allure-report@7.13.2" inputs: job_name: "e2e-test-report" job_stage: "report" diff --git a/.rubocop_todo/rspec/feature_category.yml b/.rubocop_todo/rspec/feature_category.yml index 5cf13baf9e5..320b311e6cd 100644 --- a/.rubocop_todo/rspec/feature_category.yml +++ b/.rubocop_todo/rspec/feature_category.yml @@ -2427,7 +2427,6 @@ RSpec/FeatureCategory: - 'spec/helpers/invite_members_helper_spec.rb' - 'spec/helpers/issuables_description_templates_helper_spec.rb' - 'spec/helpers/issues_helper_spec.rb' - - 'spec/helpers/json_helper_spec.rb' - 'spec/helpers/keyset_helper_spec.rb' - 'spec/helpers/labels_helper_spec.rb' - 'spec/helpers/lazy_image_tag_helper_spec.rb' diff --git a/.rubocop_todo/rspec/named_subject.yml b/.rubocop_todo/rspec/named_subject.yml index 9ee86882271..20e43b25c1e 100644 --- a/.rubocop_todo/rspec/named_subject.yml +++ b/.rubocop_todo/rspec/named_subject.yml @@ -1612,7 +1612,6 @@ RSpec/NamedSubject: - 'spec/helpers/hooks_helper_spec.rb' - 'spec/helpers/integrations_helper_spec.rb' - 'spec/helpers/jira_connect_helper_spec.rb' - - 'spec/helpers/json_helper_spec.rb' - 'spec/helpers/labels_helper_spec.rb' - 'spec/helpers/listbox_helper_spec.rb' - 'spec/helpers/markup_helper_spec.rb' diff --git a/GITLAB_PAGES_VERSION b/GITLAB_PAGES_VERSION index e347135ff4a..d35f1128be3 100644 --- a/GITLAB_PAGES_VERSION +++ b/GITLAB_PAGES_VERSION @@ -1 +1 @@ -6cb3173f9a1468c93d5c3fa9327e9b560de1329b +38a79230add5dc453d8fafa48f7f3e218a70f0be diff --git a/app/assets/javascripts/ci/job_details/components/log/log.vue b/app/assets/javascripts/ci/job_details/components/log/log.vue index fb6a6a58074..433d1b3579b 100644 --- a/app/assets/javascripts/ci/job_details/components/log/log.vue +++ b/app/assets/javascripts/ci/job_details/components/log/log.vue @@ -20,23 +20,11 @@ export default { }, }, computed: { - ...mapState([ - 'jobLogEndpoint', - 'jobLog', - 'isJobLogComplete', - 'isScrolledToBottomBeforeReceivingJobLog', - ]), + ...mapState(['jobLogEndpoint', 'jobLog', 'isJobLogComplete']), highlightedLines() { return this.searchResults.map((result) => result.lineNumber); }, }, - updated() { - this.$nextTick(() => { - if (!window.location.hash) { - this.handleScrollDown(); - } - }); - }, mounted() { if (window.location.hash) { const lineNumber = getLocationHash(); @@ -57,20 +45,6 @@ export default { handleOnClickCollapsibleLine(section) { this.toggleCollapsibleLine(section); }, - /** - * The job log is sent in HTML, which means we need to use `v-html` to render it - * Using the updated hook with $nextTick is not enough to wait for the DOM to be updated - * in this case because it runs before `v-html` has finished running, since there's no - * Vue binding. - * In order to scroll the page down after `v-html` has finished, we need to use setTimeout - */ - handleScrollDown() { - if (this.isScrolledToBottomBeforeReceivingJobLog) { - setTimeout(() => { - this.scrollBottom(); - }, 0); - } - }, isHighlighted({ lineNumber }) { return this.highlightedLines.includes(lineNumber); }, diff --git a/app/assets/javascripts/ci/job_details/job_app.vue b/app/assets/javascripts/ci/job_details/job_app.vue index e0708289b43..1c581a2df78 100644 --- a/app/assets/javascripts/ci/job_details/job_app.vue +++ b/app/assets/javascripts/ci/job_details/job_app.vue @@ -88,7 +88,6 @@ export default { 'isJobLogSizeVisible', 'isScrollBottomDisabled', 'isScrollTopDisabled', - 'isScrolledToBottomBeforeReceivingJobLog', 'hasError', 'selectedStage', ]), diff --git a/app/assets/javascripts/ci/job_details/store/actions.js b/app/assets/javascripts/ci/job_details/store/actions.js index adcba0f2409..a54dbf2e7b1 100644 --- a/app/assets/javascripts/ci/job_details/store/actions.js +++ b/app/assets/javascripts/ci/job_details/store/actions.js @@ -150,40 +150,47 @@ export const enableScrollTop = ({ commit }) => commit(types.ENABLE_SCROLL_TOP); export const toggleScrollAnimation = ({ commit }, toggle) => commit(types.TOGGLE_SCROLL_ANIMATION, toggle); -/** - * Responsible to handle automatic scroll - */ -export const toggleScrollisInBottom = ({ commit }, toggle) => { - commit(types.TOGGLE_IS_SCROLL_IN_BOTTOM_BEFORE_UPDATING_JOB_LOG, toggle); -}; - export const requestJobLog = ({ commit }) => commit(types.REQUEST_JOB_LOG); -export const fetchJobLog = ({ dispatch, state }) => - // update trace endpoint once BE compeletes trace re-naming in #340626 - axios - .get(`${state.jobLogEndpoint}/trace.json`, { - params: { state: state.jobLogState }, - }) - .then(({ data }) => { - dispatch('toggleScrollisInBottom', isScrolledToBottom()); - dispatch('receiveJobLogSuccess', data); +export const fetchJobLog = ({ commit, dispatch, state }) => { + let isScrolledToBottomBeforeReceivingJobLog; - if (data.complete) { - dispatch('stopPollingJobLog'); - dispatch('requestTestSummary'); - } else if (!state.jobLogTimeout) { - dispatch('startPollingJobLog'); - } - }) - .catch((e) => { - if (e.response?.status === HTTP_STATUS_FORBIDDEN) { - dispatch('receiveJobLogUnauthorizedError'); - } else { - reportToSentry('job_actions', e); - dispatch('receiveJobLogError'); - } - }); + // update trace endpoint once BE completes trace re-naming in #340626 + return ( + axios + .get(`${state.jobLogEndpoint}/trace.json`, { + params: { state: state.jobLogState }, + }) + .then(({ data }) => { + isScrolledToBottomBeforeReceivingJobLog = isScrolledToBottom(); + + commit(types.RECEIVE_JOB_LOG_SUCCESS, data); + + if (data.complete) { + dispatch('stopPollingJobLog'); + dispatch('requestTestSummary'); + } else if (!state.jobLogTimeout) { + dispatch('startPollingJobLog'); + } + }) + // place `scrollBottom` in a separate `then()` block + // to wait on related components to update + // after the RECEIVE_JOB_LOG_SUCCESS commit + .then(() => { + if (isScrolledToBottomBeforeReceivingJobLog) { + dispatch('scrollBottom'); + } + }) + .catch((e) => { + if (e.response?.status === HTTP_STATUS_FORBIDDEN) { + dispatch('receiveJobLogUnauthorizedError'); + } else { + reportToSentry('job_actions', e); + dispatch('receiveJobLogError'); + } + }) + ); +}; export const startPollingJobLog = ({ dispatch, commit }) => { const jobLogTimeout = setTimeout(() => { @@ -200,8 +207,6 @@ export const stopPollingJobLog = ({ state, commit }) => { commit(types.STOP_POLLING_JOB_LOG); }; -export const receiveJobLogSuccess = ({ commit }, log) => commit(types.RECEIVE_JOB_LOG_SUCCESS, log); - export const receiveJobLogError = ({ dispatch }) => { dispatch('stopPollingJobLog'); createAlert({ diff --git a/app/assets/javascripts/ci/job_details/store/mutation_types.js b/app/assets/javascripts/ci/job_details/store/mutation_types.js index 86ebbe57714..1feb35c51d8 100644 --- a/app/assets/javascripts/ci/job_details/store/mutation_types.js +++ b/app/assets/javascripts/ci/job_details/store/mutation_types.js @@ -11,8 +11,6 @@ export const ENABLE_SCROLL_BOTTOM = 'ENABLE_SCROLL_BOTTOM'; export const ENABLE_SCROLL_TOP = 'ENABLE_SCROLL_TOP'; export const TOGGLE_SCROLL_ANIMATION = 'TOGGLE_SCROLL_ANIMATION'; -export const TOGGLE_IS_SCROLL_IN_BOTTOM_BEFORE_UPDATING_JOB_LOG = 'TOGGLE_IS_SCROLL_IN_BOTTOM'; - export const REQUEST_JOB = 'REQUEST_JOB'; export const RECEIVE_JOB_SUCCESS = 'RECEIVE_JOB_SUCCESS'; export const RECEIVE_JOB_ERROR = 'RECEIVE_JOB_ERROR'; diff --git a/app/assets/javascripts/ci/job_details/store/mutations.js b/app/assets/javascripts/ci/job_details/store/mutations.js index ad0603c050e..72f9a86c4a9 100644 --- a/app/assets/javascripts/ci/job_details/store/mutations.js +++ b/app/assets/javascripts/ci/job_details/store/mutations.js @@ -111,11 +111,6 @@ export default { [types.TOGGLE_SCROLL_ANIMATION](state, toggle) { state.isScrollingDown = toggle; }, - - [types.TOGGLE_IS_SCROLL_IN_BOTTOM_BEFORE_UPDATING_JOB_LOG](state, toggle) { - state.isScrolledToBottomBeforeReceivingJobLog = toggle; - }, - [types.REQUEST_JOBS_FOR_STAGE](state, stage = {}) { state.isLoadingJobs = true; state.selectedStage = stage.name; diff --git a/app/assets/javascripts/ci/job_details/store/state.js b/app/assets/javascripts/ci/job_details/store/state.js index aa4497d0e37..512b8b115b7 100644 --- a/app/assets/javascripts/ci/job_details/store/state.js +++ b/app/assets/javascripts/ci/job_details/store/state.js @@ -16,9 +16,6 @@ export default () => ({ isScrollBottomDisabled: true, isScrollTopDisabled: true, - // Used to check if we should keep the automatic scroll - isScrolledToBottomBeforeReceivingJobLog: true, - jobLog: [], isJobLogComplete: false, jobLogSize: 0, diff --git a/app/assets/javascripts/frequent_items/components/app.vue b/app/assets/javascripts/frequent_items/components/app.vue deleted file mode 100644 index 947d3053094..00000000000 --- a/app/assets/javascripts/frequent_items/components/app.vue +++ /dev/null @@ -1,183 +0,0 @@ - - - diff --git a/app/assets/javascripts/frequent_items/components/frequent_items_list.vue b/app/assets/javascripts/frequent_items/components/frequent_items_list.vue deleted file mode 100644 index da1d3bedaf4..00000000000 --- a/app/assets/javascripts/frequent_items/components/frequent_items_list.vue +++ /dev/null @@ -1,90 +0,0 @@ - - - diff --git a/app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue b/app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue deleted file mode 100644 index 056dedf8757..00000000000 --- a/app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue +++ /dev/null @@ -1,132 +0,0 @@ - - - diff --git a/app/assets/javascripts/frequent_items/components/frequent_items_mixin.js b/app/assets/javascripts/frequent_items/components/frequent_items_mixin.js deleted file mode 100644 index 704dc83ca8e..00000000000 --- a/app/assets/javascripts/frequent_items/components/frequent_items_mixin.js +++ /dev/null @@ -1,23 +0,0 @@ -import { TRANSLATION_KEYS } from '../constants'; - -export default { - props: { - namespace: { - type: String, - required: true, - }, - }, - methods: { - getTranslations(keys) { - const translationStrings = keys.reduce( - (acc, key) => ({ - ...acc, - [key]: TRANSLATION_KEYS[this.namespace][key], - }), - {}, - ); - - return translationStrings; - }, - }, -}; diff --git a/app/assets/javascripts/frequent_items/components/frequent_items_search_input.vue b/app/assets/javascripts/frequent_items/components/frequent_items_search_input.vue deleted file mode 100644 index 023245f050b..00000000000 --- a/app/assets/javascripts/frequent_items/components/frequent_items_search_input.vue +++ /dev/null @@ -1,63 +0,0 @@ - - - diff --git a/app/assets/javascripts/frequent_items/constants.js b/app/assets/javascripts/frequent_items/constants.js deleted file mode 100644 index a7c27abf58e..00000000000 --- a/app/assets/javascripts/frequent_items/constants.js +++ /dev/null @@ -1,54 +0,0 @@ -import { s__ } from '~/locale'; - -export const FREQUENT_ITEMS = { - MAX_COUNT: 20, - LIST_COUNT_DESKTOP: 5, - LIST_COUNT_MOBILE: 3, - ELIGIBLE_FREQUENCY: 3, -}; - -export const FIFTEEN_MINUTES_IN_MS = 900000; - -export const STORAGE_KEY = { - projects: 'frequent-projects', - groups: 'frequent-groups', -}; - -export const TRANSLATION_KEYS = { - projects: { - loadingMessage: s__('ProjectsDropdown|Loading projects'), - header: s__('ProjectsDropdown|Frequently visited'), - headerEditToggle: s__('ProjectsDropdown|Toggle edit mode'), - itemListErrorMessage: s__( - 'ProjectsDropdown|This feature requires browser localStorage support', - ), - itemListEmptyMessage: s__('ProjectsDropdown|Projects you visit often will appear here'), - searchListErrorMessage: s__('ProjectsDropdown|Something went wrong on our end.'), - searchListEmptyMessage: s__('ProjectsDropdown|Sorry, no projects matched your search'), - searchInputPlaceholder: s__('ProjectsDropdown|Search your projects'), - }, - groups: { - loadingMessage: s__('GroupsDropdown|Loading groups'), - header: s__('GroupsDropdown|Frequently visited'), - headerEditToggle: s__('GroupsDropdown|Toggle edit mode'), - itemListErrorMessage: s__('GroupsDropdown|This feature requires browser localStorage support'), - itemListEmptyMessage: s__('GroupsDropdown|Groups you visit often will appear here'), - searchListErrorMessage: s__('GroupsDropdown|Something went wrong on our end.'), - searchListEmptyMessage: s__('GroupsDropdown|Sorry, no groups matched your search'), - searchInputPlaceholder: s__('GroupsDropdown|Search your groups'), - }, -}; - -export const FREQUENT_ITEMS_PROJECTS = { - namespace: 'projects', - key: 'project', - vuexModule: 'frequentProjects', -}; - -export const FREQUENT_ITEMS_GROUPS = { - namespace: 'groups', - key: 'group', - vuexModule: 'frequentGroups', -}; - -export const FREQUENT_ITEMS_DROPDOWNS = [FREQUENT_ITEMS_PROJECTS, FREQUENT_ITEMS_GROUPS]; diff --git a/app/assets/javascripts/frequent_items/event_hub.js b/app/assets/javascripts/frequent_items/event_hub.js deleted file mode 100644 index e31806ad199..00000000000 --- a/app/assets/javascripts/frequent_items/event_hub.js +++ /dev/null @@ -1,3 +0,0 @@ -import createEventHub from '~/helpers/event_hub_factory'; - -export default createEventHub(); diff --git a/app/assets/javascripts/frequent_items/store/actions.js b/app/assets/javascripts/frequent_items/store/actions.js deleted file mode 100644 index e5ef49ec402..00000000000 --- a/app/assets/javascripts/frequent_items/store/actions.js +++ /dev/null @@ -1,112 +0,0 @@ -import AccessorUtilities from '~/lib/utils/accessor'; -import { isLoggedIn } from '~/lib/utils/common_utils'; -import { getGroups, getProjects } from '~/rest_api'; -import { getTopFrequentItems } from '../utils'; -import * as types from './mutation_types'; - -export const setNamespace = ({ commit }, namespace) => { - commit(types.SET_NAMESPACE, namespace); -}; - -export const setStorageKey = ({ commit }, key) => { - commit(types.SET_STORAGE_KEY, key); -}; - -export const toggleItemsListEditablity = ({ commit }) => { - commit(types.TOGGLE_ITEMS_LIST_EDITABILITY); -}; - -export const requestFrequentItems = ({ commit }) => { - commit(types.REQUEST_FREQUENT_ITEMS); -}; -export const receiveFrequentItemsSuccess = ({ commit }, data) => { - commit(types.RECEIVE_FREQUENT_ITEMS_SUCCESS, data); -}; -export const receiveFrequentItemsError = ({ commit }) => { - commit(types.RECEIVE_FREQUENT_ITEMS_ERROR); -}; - -export const fetchFrequentItems = ({ state, dispatch }) => { - dispatch('requestFrequentItems'); - - if (AccessorUtilities.canUseLocalStorage()) { - const storedFrequentItems = JSON.parse(localStorage.getItem(state.storageKey)); - - dispatch( - 'receiveFrequentItemsSuccess', - !storedFrequentItems ? [] : getTopFrequentItems(storedFrequentItems), - ); - } else { - dispatch('receiveFrequentItemsError'); - } -}; - -export const requestSearchedItems = ({ commit }) => { - commit(types.REQUEST_SEARCHED_ITEMS); -}; -export const receiveSearchedItemsSuccess = ({ commit }, data) => { - commit(types.RECEIVE_SEARCHED_ITEMS_SUCCESS, data); -}; -export const receiveSearchedItemsError = ({ commit }) => { - commit(types.RECEIVE_SEARCHED_ITEMS_ERROR); -}; -export const fetchSearchedItems = ({ state, dispatch }, searchQuery) => { - dispatch('requestSearchedItems'); - - const params = { - simple: true, - per_page: 20, - membership: isLoggedIn(), - }; - - let searchFunction; - if (state.namespace === 'projects') { - searchFunction = getProjects; - params.order_by = 'last_activity_at'; - } else { - searchFunction = getGroups; - } - - return searchFunction(searchQuery, params) - .then((results) => { - dispatch('receiveSearchedItemsSuccess', results); - }) - .catch(() => { - dispatch('receiveSearchedItemsError'); - }); -}; - -export const setSearchQuery = ({ commit, dispatch }, query) => { - commit(types.SET_SEARCH_QUERY, query); - - if (query) { - dispatch('fetchSearchedItems', query); - } else { - dispatch('fetchFrequentItems'); - } -}; - -export const removeFrequentItemSuccess = ({ commit }, itemId) => { - commit(types.RECEIVE_REMOVE_FREQUENT_ITEM_SUCCESS, itemId); -}; - -export const removeFrequentItemError = ({ commit }) => { - commit(types.RECEIVE_REMOVE_FREQUENT_ITEM_ERROR); -}; - -export const removeFrequentItem = ({ state, dispatch }, itemId) => { - if (AccessorUtilities.canUseLocalStorage()) { - try { - const storedRawItems = JSON.parse(localStorage.getItem(state.storageKey)); - localStorage.setItem( - state.storageKey, - JSON.stringify(storedRawItems.filter((item) => item.id !== itemId)), - ); - dispatch('removeFrequentItemSuccess', itemId); - } catch { - dispatch('removeFrequentItemError'); - } - } else { - dispatch('removeFrequentItemError'); - } -}; diff --git a/app/assets/javascripts/frequent_items/store/getters.js b/app/assets/javascripts/frequent_items/store/getters.js deleted file mode 100644 index e52678dbec2..00000000000 --- a/app/assets/javascripts/frequent_items/store/getters.js +++ /dev/null @@ -1 +0,0 @@ -export const hasSearchQuery = (state) => state.searchQuery !== ''; diff --git a/app/assets/javascripts/frequent_items/store/index.js b/app/assets/javascripts/frequent_items/store/index.js deleted file mode 100644 index 3e5c9618805..00000000000 --- a/app/assets/javascripts/frequent_items/store/index.js +++ /dev/null @@ -1,29 +0,0 @@ -// eslint-disable-next-line no-restricted-imports -import Vuex from 'vuex'; -import { FREQUENT_ITEMS_DROPDOWNS } from '../constants'; -import * as actions from './actions'; -import * as getters from './getters'; -import mutations from './mutations'; -import state from './state'; - -export const createFrequentItemsModule = (initState = {}) => ({ - namespaced: true, - actions, - getters, - mutations, - state: state(initState), -}); - -export const createStoreOptions = () => ({ - modules: FREQUENT_ITEMS_DROPDOWNS.reduce( - (acc, { namespace, vuexModule }) => - Object.assign(acc, { - [vuexModule]: createFrequentItemsModule({ dropdownType: namespace }), - }), - {}, - ), -}); - -export const createStore = () => { - return new Vuex.Store(createStoreOptions()); -}; diff --git a/app/assets/javascripts/frequent_items/store/mutation_types.js b/app/assets/javascripts/frequent_items/store/mutation_types.js deleted file mode 100644 index 9c9346081e9..00000000000 --- a/app/assets/javascripts/frequent_items/store/mutation_types.js +++ /dev/null @@ -1,12 +0,0 @@ -export const SET_NAMESPACE = 'SET_NAMESPACE'; -export const SET_STORAGE_KEY = 'SET_STORAGE_KEY'; -export const SET_SEARCH_QUERY = 'SET_SEARCH_QUERY'; -export const TOGGLE_ITEMS_LIST_EDITABILITY = 'TOGGLE_ITEMS_LIST_EDITABILITY'; -export const REQUEST_FREQUENT_ITEMS = 'REQUEST_FREQUENT_ITEMS'; -export const RECEIVE_FREQUENT_ITEMS_SUCCESS = 'RECEIVE_FREQUENT_ITEMS_SUCCESS'; -export const RECEIVE_FREQUENT_ITEMS_ERROR = 'RECEIVE_FREQUENT_ITEMS_ERROR'; -export const REQUEST_SEARCHED_ITEMS = 'REQUEST_SEARCHED_ITEMS'; -export const RECEIVE_SEARCHED_ITEMS_SUCCESS = 'RECEIVE_SEARCHED_ITEMS_SUCCESS'; -export const RECEIVE_SEARCHED_ITEMS_ERROR = 'RECEIVE_SEARCHED_ITEMS_ERROR'; -export const RECEIVE_REMOVE_FREQUENT_ITEM_SUCCESS = 'RECEIVE_REMOVE_FREQUENT_ITEM_SUCCESS'; -export const RECEIVE_REMOVE_FREQUENT_ITEM_ERROR = 'RECEIVE_REMOVE_FREQUENT_ITEM_ERROR'; diff --git a/app/assets/javascripts/frequent_items/store/mutations.js b/app/assets/javascripts/frequent_items/store/mutations.js deleted file mode 100644 index 9882bef444a..00000000000 --- a/app/assets/javascripts/frequent_items/store/mutations.js +++ /dev/null @@ -1,88 +0,0 @@ -import * as types from './mutation_types'; - -export default { - [types.SET_NAMESPACE](state, namespace) { - Object.assign(state, { - namespace, - }); - }, - [types.SET_STORAGE_KEY](state, storageKey) { - Object.assign(state, { - storageKey, - }); - }, - [types.SET_SEARCH_QUERY](state, searchQuery) { - const hasSearchQuery = searchQuery !== ''; - - Object.assign(state, { - searchQuery, - isLoadingItems: true, - hasSearchQuery, - }); - }, - [types.TOGGLE_ITEMS_LIST_EDITABILITY](state) { - Object.assign(state, { - isItemsListEditable: !state.isItemsListEditable, - }); - }, - [types.REQUEST_FREQUENT_ITEMS](state) { - Object.assign(state, { - isLoadingItems: true, - hasSearchQuery: false, - }); - }, - [types.RECEIVE_FREQUENT_ITEMS_SUCCESS](state, rawItems) { - Object.assign(state, { - items: rawItems, - isLoadingItems: false, - hasSearchQuery: false, - isFetchFailed: false, - }); - }, - [types.RECEIVE_FREQUENT_ITEMS_ERROR](state) { - Object.assign(state, { - isLoadingItems: false, - hasSearchQuery: false, - isFetchFailed: true, - }); - }, - [types.REQUEST_SEARCHED_ITEMS](state) { - Object.assign(state, { - isLoadingItems: true, - hasSearchQuery: true, - }); - }, - [types.RECEIVE_SEARCHED_ITEMS_SUCCESS](state, results) { - const rawItems = results.data; - Object.assign(state, { - items: rawItems.map((rawItem) => ({ - id: rawItem.id, - name: rawItem.name, - namespace: rawItem.name_with_namespace || rawItem.full_name, - webUrl: rawItem.web_url, - avatarUrl: rawItem.avatar_url, - })), - isLoadingItems: false, - hasSearchQuery: true, - isFetchFailed: false, - }); - }, - [types.RECEIVE_SEARCHED_ITEMS_ERROR](state) { - Object.assign(state, { - isLoadingItems: false, - hasSearchQuery: true, - isFetchFailed: true, - }); - }, - [types.RECEIVE_REMOVE_FREQUENT_ITEM_SUCCESS](state, itemId) { - Object.assign(state, { - items: state.items.filter((item) => item.id !== itemId), - isItemRemovalFailed: false, - }); - }, - [types.RECEIVE_REMOVE_FREQUENT_ITEM_ERROR](state) { - Object.assign(state, { - isItemRemovalFailed: true, - }); - }, -}; diff --git a/app/assets/javascripts/frequent_items/store/state.js b/app/assets/javascripts/frequent_items/store/state.js deleted file mode 100644 index ee94e9cd221..00000000000 --- a/app/assets/javascripts/frequent_items/store/state.js +++ /dev/null @@ -1,11 +0,0 @@ -export default ({ dropdownType = '' } = {}) => ({ - namespace: '', - dropdownType, - storageKey: '', - searchQuery: '', - isLoadingItems: false, - isFetchFailed: false, - isItemsListEditable: false, - isItemRemovalFailed: false, - items: [], -}); diff --git a/app/assets/javascripts/frequent_items/utils.js b/app/assets/javascripts/frequent_items/utils.js deleted file mode 100644 index f71405a5bc4..00000000000 --- a/app/assets/javascripts/frequent_items/utils.js +++ /dev/null @@ -1,67 +0,0 @@ -import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils'; -import { take } from 'lodash'; -import { sanitize } from '~/lib/dompurify'; -import { FREQUENT_ITEMS, FIFTEEN_MINUTES_IN_MS } from './constants'; - -export const isMobile = () => ['md', 'sm', 'xs'].includes(bp.getBreakpointSize()); - -export const getTopFrequentItems = (items) => { - if (!items) { - return []; - } - const frequentItemsCount = isMobile() - ? FREQUENT_ITEMS.LIST_COUNT_MOBILE - : FREQUENT_ITEMS.LIST_COUNT_DESKTOP; - - const frequentItems = items.filter((item) => item.frequency >= FREQUENT_ITEMS.ELIGIBLE_FREQUENCY); - - if (!frequentItems || frequentItems.length === 0) { - return []; - } - - frequentItems.sort((itemA, itemB) => { - // Sort all frequent items in decending order of frequency - // and then by lastAccessedOn with recent most first - if (itemA.frequency !== itemB.frequency) { - return itemB.frequency - itemA.frequency; - } - if (itemA.lastAccessedOn !== itemB.lastAccessedOn) { - return itemB.lastAccessedOn - itemA.lastAccessedOn; - } - - return 0; - }); - - return take(frequentItems, frequentItemsCount); -}; - -export const updateExistingFrequentItem = (frequentItem, item) => { - // `frequentItem` comes from localStorage and it's possible it doesn't have a `lastAccessedOn` - const neverAccessed = !frequentItem.lastAccessedOn; - const shouldUpdate = - neverAccessed || - Math.abs(item.lastAccessedOn - frequentItem.lastAccessedOn) / FIFTEEN_MINUTES_IN_MS > 1; - - return { - ...item, - frequency: shouldUpdate ? frequentItem.frequency + 1 : frequentItem.frequency, - lastAccessedOn: shouldUpdate ? Date.now() : frequentItem.lastAccessedOn, - }; -}; - -export const sanitizeItem = (item) => { - // Only sanitize if the key exists on the item - const maybeSanitize = (key) => { - if (!Object.prototype.hasOwnProperty.call(item, key)) { - return {}; - } - - return { [key]: sanitize(item[key].toString(), { ALLOWED_TAGS: [] }) }; - }; - - return { - ...item, - ...maybeSanitize('name'), - ...maybeSanitize('namespace'), - }; -}; diff --git a/app/assets/javascripts/import/details/components/bulk_import_details_app.vue b/app/assets/javascripts/import/details/components/bulk_import_details_app.vue index 5da16454032..a248dd3d2c4 100644 --- a/app/assets/javascripts/import/details/components/bulk_import_details_app.vue +++ b/app/assets/javascripts/import/details/components/bulk_import_details_app.vue @@ -1,10 +1,14 @@