summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-08-05 06:09:25 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2021-08-05 06:09:25 +0000
commit962fbcfb94b13668632de822e3f7a74fb5ecaf68 (patch)
tree51bebd0983aa06a72af75f7b85c05debd5169037 /app
parent24fca3804098db8d0083d35db1975d198467e9b8 (diff)
downloadgitlab-ce-962fbcfb94b13668632de822e3f7a74fb5ecaf68.tar.gz
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/import_entities/import_projects/components/provider_repo_table_row.vue3
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/components/details/package_title.vue33
-rw-r--r--app/assets/javascripts/search/store/actions.js36
-rw-r--r--app/assets/javascripts/search/store/utils.js4
-rw-r--r--app/assets/javascripts/search/topbar/components/app.vue5
-rw-r--r--app/assets/javascripts/search/topbar/components/group_filter.vue14
-rw-r--r--app/assets/javascripts/search/topbar/components/project_filter.vue9
-rw-r--r--app/assets/javascripts/search_autocomplete.js8
-rw-r--r--app/helpers/groups_helper.rb2
-rw-r--r--app/services/projects/create_service.rb2
-rw-r--r--app/views/groups/settings/_advanced.html.haml1
-rw-r--r--app/views/search/show.html.haml3
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)">
- &nbsp;{{ 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'