diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-08-05 06:09:25 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-08-05 06:09:25 +0000 |
commit | 962fbcfb94b13668632de822e3f7a74fb5ecaf68 (patch) | |
tree | 51bebd0983aa06a72af75f7b85c05debd5169037 /app | |
parent | 24fca3804098db8d0083d35db1975d198467e9b8 (diff) | |
download | gitlab-ce-962fbcfb94b13668632de822e3f7a74fb5ecaf68.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
12 files changed, 77 insertions, 43 deletions
diff --git a/app/assets/javascripts/import_entities/import_projects/components/provider_repo_table_row.vue b/app/assets/javascripts/import_entities/import_projects/components/provider_repo_table_row.vue index e2fd608d9db..a97af5367fb 100644 --- a/app/assets/javascripts/import_entities/import_projects/components/provider_repo_table_row.vue +++ b/app/assets/javascripts/import_entities/import_projects/components/provider_repo_table_row.vue @@ -103,6 +103,7 @@ export default { <tr class="gl-h-11 gl-border-0 gl-border-solid gl-border-t-1 gl-border-gray-100 gl-h-11" data-qa-selector="project_import_row" + :data-qa-source-project="repo.importSource.fullName" > <td class="gl-p-4"> <gl-link :href="repo.importSource.providerLink" target="_blank" data-testid="providerLink" @@ -155,7 +156,7 @@ export default { </template> <template v-else-if="repo.importedProject">{{ displayFullPath }}</template> </td> - <td class="gl-p-4"> + <td class="gl-p-4" data-qa-selector="import_status_indicator"> <import-status :status="importStatus" /> </td> <td data-testid="actions"> diff --git a/app/assets/javascripts/packages_and_registries/package_registry/components/details/package_title.vue b/app/assets/javascripts/packages_and_registries/package_registry/components/details/package_title.vue index 4b287d31786..65547af3913 100644 --- a/app/assets/javascripts/packages_and_registries/package_registry/components/details/package_title.vue +++ b/app/assets/javascripts/packages_and_registries/package_registry/components/details/package_title.vue @@ -1,5 +1,5 @@ <script> -import { GlIcon, GlSprintf, GlTooltipDirective, GlBadge } from '@gitlab/ui'; +import { GlIcon, GlSprintf, GlBadge } from '@gitlab/ui'; import { GlBreakpointInstance } from '@gitlab/ui/dist/utils'; import { numberToHumanSize } from '~/lib/utils/number_utils'; import { __ } from '~/locale'; @@ -8,7 +8,7 @@ import { PACKAGE_TYPE_NUGET } from '~/packages_and_registries/package_registry/c import { getPackageTypeLabel } from '~/packages_and_registries/package_registry/utils'; import MetadataItem from '~/vue_shared/components/registry/metadata_item.vue'; import TitleArea from '~/vue_shared/components/registry/title_area.vue'; -import timeagoMixin from '~/vue_shared/mixins/timeago'; +import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue'; export default { name: 'PackageTitle', @@ -19,11 +19,8 @@ export default { PackageTags, MetadataItem, GlBadge, + TimeAgoTooltip, }, - directives: { - GlTooltip: GlTooltipDirective, - }, - mixins: [timeagoMixin], i18n: { packageInfo: __('v%{version} published %{timeAgo}'), }, @@ -77,17 +74,21 @@ export default { <title-area :title="packageEntity.name" :avatar="packageIcon" data-qa-selector="package_title"> <template #sub-header> <gl-icon name="eye" class="gl-mr-3" /> - <gl-sprintf :message="$options.i18n.packageInfo"> - <template #version> - {{ packageEntity.version }} - </template> + <span data-testid="sub-header"> + <gl-sprintf :message="$options.i18n.packageInfo"> + <template #version> + {{ packageEntity.version }} + </template> - <template #timeAgo> - <span v-gl-tooltip :title="tooltipTitle(packageEntity.created_at)"> - {{ timeFormatted(packageEntity.created_at) }} - </span> - </template> - </gl-sprintf> + <template #timeAgo> + <time-ago-tooltip + v-if="packageEntity.createdAt" + class="gl-ml-2" + :time="packageEntity.createdAt" + /> + </template> + </gl-sprintf> + </span> </template> <template v-if="packageTypeDisplay" #metadata-type> diff --git a/app/assets/javascripts/search/store/actions.js b/app/assets/javascripts/search/store/actions.js index b53557c0ec5..ee5e778f63d 100644 --- a/app/assets/javascripts/search/store/actions.js +++ b/app/assets/javascripts/search/store/actions.js @@ -46,38 +46,44 @@ export const fetchProjects = ({ commit, state }, search) => { } }; -export const loadFrequentGroups = async ({ commit }) => { - const data = loadDataFromLS(GROUPS_LOCAL_STORAGE_KEY); - commit(types.LOAD_FREQUENT_ITEMS, { key: GROUPS_LOCAL_STORAGE_KEY, data }); +export const preloadStoredFrequentItems = ({ commit }) => { + const storedGroups = loadDataFromLS(GROUPS_LOCAL_STORAGE_KEY); + commit(types.LOAD_FREQUENT_ITEMS, { key: GROUPS_LOCAL_STORAGE_KEY, data: storedGroups }); - const promises = data.map((d) => Api.group(d.id)); + const storedProjects = loadDataFromLS(PROJECTS_LOCAL_STORAGE_KEY); + commit(types.LOAD_FREQUENT_ITEMS, { key: PROJECTS_LOCAL_STORAGE_KEY, data: storedProjects }); +}; + +export const loadFrequentGroups = async ({ commit, state }) => { + const storedData = state.frequentItems[GROUPS_LOCAL_STORAGE_KEY]; + const promises = storedData.map((d) => Api.group(d.id)); try { - const inflatedData = mergeById(await Promise.all(promises), data); + const inflatedData = mergeById(await Promise.all(promises), storedData); commit(types.LOAD_FREQUENT_ITEMS, { key: GROUPS_LOCAL_STORAGE_KEY, data: inflatedData }); } catch { createFlash({ message: __('There was a problem fetching recent groups.') }); } }; -export const loadFrequentProjects = async ({ commit }) => { - const data = loadDataFromLS(PROJECTS_LOCAL_STORAGE_KEY); - commit(types.LOAD_FREQUENT_ITEMS, { key: PROJECTS_LOCAL_STORAGE_KEY, data }); - - const promises = data.map((d) => Api.project(d.id).then((res) => res.data)); +export const loadFrequentProjects = async ({ commit, state }) => { + const storedData = state.frequentItems[PROJECTS_LOCAL_STORAGE_KEY]; + const promises = storedData.map((d) => Api.project(d.id).then((res) => res.data)); try { - const inflatedData = mergeById(await Promise.all(promises), data); + const inflatedData = mergeById(await Promise.all(promises), storedData); commit(types.LOAD_FREQUENT_ITEMS, { key: PROJECTS_LOCAL_STORAGE_KEY, data: inflatedData }); } catch { createFlash({ message: __('There was a problem fetching recent projects.') }); } }; -export const setFrequentGroup = ({ state }, item) => { - setFrequentItemToLS(GROUPS_LOCAL_STORAGE_KEY, state.frequentItems, item); +export const setFrequentGroup = ({ state, commit }, item) => { + const frequentItems = setFrequentItemToLS(GROUPS_LOCAL_STORAGE_KEY, state.frequentItems, item); + commit(types.LOAD_FREQUENT_ITEMS, { key: GROUPS_LOCAL_STORAGE_KEY, data: frequentItems }); }; -export const setFrequentProject = ({ state }, item) => { - setFrequentItemToLS(PROJECTS_LOCAL_STORAGE_KEY, state.frequentItems, item); +export const setFrequentProject = ({ state, commit }, item) => { + const frequentItems = setFrequentItemToLS(PROJECTS_LOCAL_STORAGE_KEY, state.frequentItems, item); + commit(types.LOAD_FREQUENT_ITEMS, { key: PROJECTS_LOCAL_STORAGE_KEY, data: frequentItems }); }; export const setQuery = ({ commit }, { key, value }) => { diff --git a/app/assets/javascripts/search/store/utils.js b/app/assets/javascripts/search/store/utils.js index 60c09221ca9..b7d97213594 100644 --- a/app/assets/javascripts/search/store/utils.js +++ b/app/assets/javascripts/search/store/utils.js @@ -21,7 +21,7 @@ export const loadDataFromLS = (key) => { export const setFrequentItemToLS = (key, data, itemData) => { if (!AccessorUtilities.isLocalStorageAccessSafe()) { - return; + return []; } const keyList = [ @@ -66,9 +66,11 @@ export const setFrequentItemToLS = (key, data, itemData) => { // Note we do not need to commit a mutation here as immediately after this we refresh the page to // update the search results. localStorage.setItem(key, JSON.stringify(frequentItems)); + return frequentItems; } catch { // The LS got in a bad state, let's wipe it localStorage.removeItem(key); + return []; } }; diff --git a/app/assets/javascripts/search/topbar/components/app.vue b/app/assets/javascripts/search/topbar/components/app.vue index a490adbc11a..65114ee066e 100644 --- a/app/assets/javascripts/search/topbar/components/app.vue +++ b/app/assets/javascripts/search/topbar/components/app.vue @@ -39,8 +39,11 @@ export default { return !this.query.snippets || this.query.snippets === 'false'; }, }, + created() { + this.preloadStoredFrequentItems(); + }, methods: { - ...mapActions(['applyQuery', 'setQuery']), + ...mapActions(['applyQuery', 'setQuery', 'preloadStoredFrequentItems']), }, }; </script> diff --git a/app/assets/javascripts/search/topbar/components/group_filter.vue b/app/assets/javascripts/search/topbar/components/group_filter.vue index 45a6ae73fac..e5edb21792a 100644 --- a/app/assets/javascripts/search/topbar/components/group_filter.vue +++ b/app/assets/javascripts/search/topbar/components/group_filter.vue @@ -18,12 +18,18 @@ export default { }, }, computed: { - ...mapState(['groups', 'fetchingGroups']), + ...mapState(['query', 'groups', 'fetchingGroups']), ...mapGetters(['frequentGroups']), selectedGroup() { return isEmpty(this.initialData) ? ANY_OPTION : this.initialData; }, }, + created() { + // This tracks groups searched via the top nav search bar + if (this.query.nav_source === 'navbar' && this.initialData?.id) { + this.setFrequentGroup(this.initialData); + } + }, methods: { ...mapActions(['fetchGroups', 'setFrequentGroup', 'loadFrequentGroups']), handleGroupChange(group) { @@ -33,7 +39,11 @@ export default { } visitUrl( - setUrlParams({ [GROUP_DATA.queryParam]: group.id, [PROJECT_DATA.queryParam]: null }), + setUrlParams({ + [GROUP_DATA.queryParam]: group.id, + [PROJECT_DATA.queryParam]: null, + nav_source: null, + }), ); }, }, diff --git a/app/assets/javascripts/search/topbar/components/project_filter.vue b/app/assets/javascripts/search/topbar/components/project_filter.vue index 1ca31db61e5..85cf2ddbbff 100644 --- a/app/assets/javascripts/search/topbar/components/project_filter.vue +++ b/app/assets/javascripts/search/topbar/components/project_filter.vue @@ -17,12 +17,18 @@ export default { }, }, computed: { - ...mapState(['projects', 'fetchingProjects']), + ...mapState(['query', 'projects', 'fetchingProjects']), ...mapGetters(['frequentProjects']), selectedProject() { return this.initialData ? this.initialData : ANY_OPTION; }, }, + created() { + // This tracks projects searched via the top nav search bar + if (this.query.nav_source === 'navbar' && this.initialData?.id) { + this.setFrequentProject(this.initialData); + } + }, methods: { ...mapActions(['fetchProjects', 'setFrequentProject', 'loadFrequentProjects']), handleProjectChange(project) { @@ -35,6 +41,7 @@ export default { const queryParams = { ...(project.namespace?.id && { [GROUP_DATA.queryParam]: project.namespace.id }), [PROJECT_DATA.queryParam]: project.id, + nav_source: null, }; visitUrl(setUrlParams(queryParams)); diff --git a/app/assets/javascripts/search_autocomplete.js b/app/assets/javascripts/search_autocomplete.js index 4f278677c5f..b2bf913fe45 100644 --- a/app/assets/javascripts/search_autocomplete.js +++ b/app/assets/javascripts/search_autocomplete.js @@ -284,8 +284,8 @@ export class SearchAutocomplete { if (projectId) { const projectOptions = gl.projectOptions[getProjectSlug()]; const url = groupId - ? `${gon.relative_url_root}/search?search=${term}&project_id=${projectId}&group_id=${groupId}` - : `${gon.relative_url_root}/search?search=${term}&project_id=${projectId}`; + ? `${gon.relative_url_root}/search?search=${term}&project_id=${projectId}&group_id=${groupId}&nav_source=navbar` + : `${gon.relative_url_root}/search?search=${term}&project_id=${projectId}&nav_source=navbar`; options.push({ icon, @@ -313,7 +313,7 @@ export class SearchAutocomplete { }, false, ), - url: `${gon.relative_url_root}/search?search=${term}&group_id=${groupId}`, + url: `${gon.relative_url_root}/search?search=${term}&group_id=${groupId}&nav_source=navbar`, }); } @@ -321,7 +321,7 @@ export class SearchAutocomplete { icon, text: term, template: s__('SearchAutocomplete|in all GitLab'), - url: `${gon.relative_url_root}/search?search=${term}`, + url: `${gon.relative_url_root}/search?search=${term}&nav_source=navbar`, }); return options; diff --git a/app/helpers/groups_helper.rb b/app/helpers/groups_helper.rb index 18f3f153aee..45f21d4d082 100644 --- a/app/helpers/groups_helper.rb +++ b/app/helpers/groups_helper.rb @@ -143,7 +143,7 @@ module GroupsHelper end def remove_group_message(group) - _("You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?") % + _("You are going to remove %{group_name}. This will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?") % { group_name: group.name } end diff --git a/app/services/projects/create_service.rb b/app/services/projects/create_service.rb index 261c82df02d..a810993f622 100644 --- a/app/services/projects/create_service.rb +++ b/app/services/projects/create_service.rb @@ -101,6 +101,8 @@ module Projects @project.track_project_repository @project.create_project_setting unless @project.project_setting + yield if block_given? + event_service.create_project(@project, current_user) system_hook_service.execute_hooks_for(@project, :create) diff --git a/app/views/groups/settings/_advanced.html.haml b/app/views/groups/settings/_advanced.html.haml index e1ffefa8031..cdff533e3c7 100644 --- a/app/views/groups/settings/_advanced.html.haml +++ b/app/views/groups/settings/_advanced.html.haml @@ -28,3 +28,4 @@ = render 'groups/settings/transfer', group: @group = render 'groups/settings/remove', group: @group = render_if_exists 'groups/settings/restore', group: @group += render_if_exists 'groups/settings/immediately_remove', group: @group diff --git a/app/views/search/show.html.haml b/app/views/search/show.html.haml index d54310bfa82..5c78f9bcc8c 100644 --- a/app/views/search/show.html.haml +++ b/app/views/search/show.html.haml @@ -5,6 +5,7 @@ = hidden_field_tag :group_id, params[:group_id] - if params[:project_id].present? = hidden_field_tag :project_id, params[:project_id] +- group_attributes = @group&.attributes&.slice('id', 'name')&.merge(full_name: @group&.full_name) - project_attributes = @project&.attributes&.slice('id', 'namespace_id', 'name')&.merge(name_with_namespace: @project&.name_with_namespace) - if @search_results @@ -16,7 +17,7 @@ = render_if_exists 'search/form_elasticsearch', attrs: { class: 'mb-2 mb-sm-0 align-self-center' } .gl-mt-3 - #js-search-topbar{ data: { "group-initial-data": @group.to_json, "project-initial-data": project_attributes.to_json } } + #js-search-topbar{ data: { "group-initial-data": group_attributes.to_json, "project-initial-data": project_attributes.to_json } } - if @search_term = render 'search/category' = render 'search/results' |