summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-01-24 15:09:00 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-01-24 15:09:00 +0000
commitc282dba898a4cb0645f88579339502a4e3778727 (patch)
tree94a6457ce4438e085c9ae43bc51a2b5a29787bf2 /app
parent2c2dd5e36c4ed5f09f488be288882d98f9124d12 (diff)
downloadgitlab-ce-c282dba898a4cb0645f88579339502a4e3778727.tar.gz
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/graphql_shared/utils.js12
-rw-r--r--app/assets/javascripts/groups/components/group_item.vue9
-rw-r--r--app/assets/javascripts/groups/store/groups_store.js2
-rw-r--r--app/assets/javascripts/monitoring/queries/getEnvironments.query.graphql10
-rw-r--r--app/assets/javascripts/monitoring/stores/actions.js28
-rw-r--r--app/assets/javascripts/monitoring/stores/utils.js33
-rw-r--r--app/assets/javascripts/registry/settings/components/registry_settings_app.vue27
-rw-r--r--app/assets/javascripts/registry/settings/store/actions.js8
-rw-r--r--app/assets/javascripts/registry/settings/store/mutation_types.js1
-rw-r--r--app/assets/javascripts/registry/settings/store/mutations.js3
-rw-r--r--app/assets/javascripts/registry/settings/store/state.js4
-rw-r--r--app/assets/stylesheets/utilities.scss1
-rw-r--r--app/controllers/admin/groups_controller.rb7
-rw-r--r--app/helpers/projects_helper.rb6
-rw-r--r--app/models/concerns/loaded_in_group_list.rb2
-rw-r--r--app/models/group.rb4
-rw-r--r--app/views/admin/groups/_group.html.haml1
-rw-r--r--app/views/groups/settings/_advanced.html.haml11
-rw-r--r--app/views/groups/settings/_permanent_deletion.html.haml9
-rw-r--r--app/views/groups/settings/_remove.html.haml5
-rw-r--r--app/views/groups/show.html.haml2
-rw-r--r--app/views/kaminari/gitlab/_first_page.html.haml9
-rw-r--r--app/views/kaminari/gitlab/_last_page.html.haml9
-rw-r--r--app/views/kaminari/gitlab/_next_page.html.haml4
-rw-r--r--app/views/kaminari/gitlab/_page.html.haml6
-rw-r--r--app/views/kaminari/gitlab/_paginator.html.haml6
-rw-r--r--app/views/kaminari/gitlab/_prev_page.html.haml4
-rw-r--r--app/views/kaminari/gitlab/_without_count.html.haml8
-rw-r--r--app/views/projects/settings/ci_cd/show.html.haml4
-rw-r--r--app/views/projects/show.html.haml1
30 files changed, 179 insertions, 57 deletions
diff --git a/app/assets/javascripts/graphql_shared/utils.js b/app/assets/javascripts/graphql_shared/utils.js
new file mode 100644
index 00000000000..a262fbd9ac3
--- /dev/null
+++ b/app/assets/javascripts/graphql_shared/utils.js
@@ -0,0 +1,12 @@
+/**
+ * Ids generated by GraphQL endpoints are usually in the format
+ * gid://gitlab/Environments/123. This method extracts Id number
+ * from the Id path
+ *
+ * @param {String} gid GraphQL global ID
+ * @returns {Number}
+ */
+export const getIdFromGraphQLId = (gid = '') =>
+ parseInt((gid || '').replace(/gid:\/\/gitlab\/.*\//g, ''), 10) || null;
+
+export default {};
diff --git a/app/assets/javascripts/groups/components/group_item.vue b/app/assets/javascripts/groups/components/group_item.vue
index af9399a37bd..b192fb78631 100644
--- a/app/assets/javascripts/groups/components/group_item.vue
+++ b/app/assets/javascripts/groups/components/group_item.vue
@@ -1,5 +1,5 @@
<script>
-import { GlLoadingIcon } from '@gitlab/ui';
+import { GlLoadingIcon, GlBadge } from '@gitlab/ui';
import { visitUrl } from '../../lib/utils/url_utility';
import tooltip from '../../vue_shared/directives/tooltip';
import identicon from '../../vue_shared/components/identicon.vue';
@@ -17,6 +17,7 @@ export default {
tooltip,
},
components: {
+ GlBadge,
GlLoadingIcon,
identicon,
itemCaret,
@@ -62,6 +63,9 @@ export default {
isGroup() {
return this.group.type === 'group';
},
+ isGroupPendingRemoval() {
+ return this.group.type === 'group' && this.group.pendingRemoval;
+ },
visibilityIcon() {
return VISIBILITY_TYPE_ICON[this.group.visibility];
},
@@ -139,6 +143,9 @@ export default {
<span v-html="group.description"> </span>
</div>
</div>
+ <div v-if="isGroupPendingRemoval">
+ <gl-badge variant="warning">{{ __('pending removal') }}</gl-badge>
+ </div>
<div
class="metadata align-items-md-center d-flex flex-grow-1 flex-shrink-0 flex-wrap justify-content-md-between"
>
diff --git a/app/assets/javascripts/groups/store/groups_store.js b/app/assets/javascripts/groups/store/groups_store.js
index 214ac5e3db5..6a1197fa163 100644
--- a/app/assets/javascripts/groups/store/groups_store.js
+++ b/app/assets/javascripts/groups/store/groups_store.js
@@ -93,7 +93,7 @@ export default class GroupsStore {
memberCount: rawGroupItem.number_users_with_delimiter,
starCount: rawGroupItem.star_count,
updatedAt: rawGroupItem.updated_at,
- pendingRemoval: rawGroupItem.marked_for_deletion_at,
+ pendingRemoval: rawGroupItem.marked_for_deletion,
};
}
diff --git a/app/assets/javascripts/monitoring/queries/getEnvironments.query.graphql b/app/assets/javascripts/monitoring/queries/getEnvironments.query.graphql
new file mode 100644
index 00000000000..fd3a4348509
--- /dev/null
+++ b/app/assets/javascripts/monitoring/queries/getEnvironments.query.graphql
@@ -0,0 +1,10 @@
+query getEnvironments($projectPath: ID!, $search: String) {
+ project(fullPath: $projectPath) {
+ data: environments(search: $search) {
+ environments: nodes {
+ name
+ id
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/monitoring/stores/actions.js b/app/assets/javascripts/monitoring/stores/actions.js
index 6303ed2b82f..e26e1457f55 100644
--- a/app/assets/javascripts/monitoring/stores/actions.js
+++ b/app/assets/javascripts/monitoring/stores/actions.js
@@ -1,7 +1,9 @@
import * as types from './mutation_types';
import axios from '~/lib/utils/axios_utils';
import createFlash from '~/flash';
+import { gqClient, parseEnvironmentsResponse, removeLeadingSlash } from './utils';
import trackDashboardLoad from '../monitoring_tracking_helper';
+import getEnvironments from '../queries/getEnvironments.query.graphql';
import statusCodes from '../../lib/utils/http_status';
import { backOff } from '../../lib/utils/common_utils';
import { s__, sprintf } from '../../locale';
@@ -187,26 +189,30 @@ export const fetchDeploymentsData = ({ state, dispatch }) => {
});
};
-export const fetchEnvironmentsData = ({ state, dispatch }) => {
- if (!state.environmentsEndpoint) {
- return Promise.resolve([]);
- }
- return axios
- .get(state.environmentsEndpoint)
- .then(resp => resp.data)
- .then(response => {
- if (!response || !response.environments) {
+export const fetchEnvironmentsData = ({ state, dispatch }) =>
+ gqClient
+ .mutate({
+ mutation: getEnvironments,
+ variables: {
+ projectPath: removeLeadingSlash(state.projectPath),
+ search: state.environmentsSearchTerm,
+ },
+ })
+ .then(resp =>
+ parseEnvironmentsResponse(resp.data?.project?.data?.environments, state.projectPath),
+ )
+ .then(environments => {
+ if (!environments) {
createFlash(
s__('Metrics|There was an error fetching the environments data, please try again'),
);
}
- dispatch('receiveEnvironmentsDataSuccess', response.environments);
+ dispatch('receiveEnvironmentsDataSuccess', environments);
})
.catch(() => {
dispatch('receiveEnvironmentsDataFailure');
createFlash(s__('Metrics|There was an error getting environments information.'));
});
-};
/**
* Set a new array of metrics to a panel group
diff --git a/app/assets/javascripts/monitoring/stores/utils.js b/app/assets/javascripts/monitoring/stores/utils.js
index 616d2e9bfd8..56244a4ca66 100644
--- a/app/assets/javascripts/monitoring/stores/utils.js
+++ b/app/assets/javascripts/monitoring/stores/utils.js
@@ -1,8 +1,41 @@
import { omit } from 'lodash';
+import createGqClient from '~/lib/graphql';
+import { getIdFromGraphQLId } from '~/graphql_shared/utils';
+
+export const gqClient = createGqClient();
export const uniqMetricsId = metric => `${metric.metric_id}_${metric.id}`;
/**
+ * Project path has a leading slash that doesn't work well
+ * with project full path resolver here
+ * https://gitlab.com/gitlab-org/gitlab/blob/5cad4bd721ab91305af4505b2abc92b36a56ad6b/app/graphql/resolvers/full_path_resolver.rb#L10
+ *
+ * @param {String} str String with leading slash
+ * @returns {String}
+ */
+export const removeLeadingSlash = str => (str || '').replace(/^\/+/, '');
+
+/**
+ * GraphQL environments API returns only id and name.
+ * For the environments dropdown we need metrics_path.
+ * This method parses the results and add neccessart attrs
+ *
+ * @param {Array} response Environments API result
+ * @param {String} projectPath Current project path
+ * @returns {Array}
+ */
+export const parseEnvironmentsResponse = (response = [], projectPath) =>
+ (response || []).map(env => {
+ const id = getIdFromGraphQLId(env.id);
+ return {
+ ...env,
+ id,
+ metrics_path: `${projectPath}/environments/${id}/metrics`,
+ };
+ });
+
+/**
* Metrics loaded from project-defined dashboards do not have a metric_id.
* This method creates a unique ID combining metric_id and id, if either is present.
* This is hopefully a temporary solution until BE processes metrics before passing to fE
diff --git a/app/assets/javascripts/registry/settings/components/registry_settings_app.vue b/app/assets/javascripts/registry/settings/components/registry_settings_app.vue
index 7530c1dfcaf..28f4ef62242 100644
--- a/app/assets/javascripts/registry/settings/components/registry_settings_app.vue
+++ b/app/assets/javascripts/registry/settings/components/registry_settings_app.vue
@@ -1,5 +1,8 @@
<script>
-import { mapActions } from 'vuex';
+import { mapActions, mapState } from 'vuex';
+import { GlAlert } from '@gitlab/ui';
+import { sprintf, s__ } from '~/locale';
+
import { FETCH_SETTINGS_ERROR_MESSAGE } from '../constants';
import SettingsForm from './settings_form.vue';
@@ -7,6 +10,23 @@ import SettingsForm from './settings_form.vue';
export default {
components: {
SettingsForm,
+ GlAlert,
+ },
+ computed: {
+ ...mapState(['isDisabled']),
+ notAvailableMessage() {
+ return sprintf(
+ s__(
+ 'ContainerRegistry|Currently, the Container Registry tag expiration feature is not available for projects created before GitLab version 12.8. For updates and more information, visit Issue %{linkStart}#196124%{linkEnd}',
+ ),
+ {
+ linkStart:
+ '<a href="https://gitlab.com/gitlab-org/gitlab/issues/196124" target="_blank" rel="noopener noreferrer">',
+ linkEnd: '</a>',
+ },
+ false,
+ );
+ },
},
mounted() {
this.fetchSettings().catch(() =>
@@ -34,6 +54,9 @@ export default {
}}
</li>
</ul>
- <settings-form ref="settings-form" />
+ <settings-form v-if="!isDisabled" />
+ <gl-alert v-else :dismissible="false">
+ <p v-html="notAvailableMessage"></p>
+ </gl-alert>
</div>
</template>
diff --git a/app/assets/javascripts/registry/settings/store/actions.js b/app/assets/javascripts/registry/settings/store/actions.js
index 21a2008fef6..d0379d05164 100644
--- a/app/assets/javascripts/registry/settings/store/actions.js
+++ b/app/assets/javascripts/registry/settings/store/actions.js
@@ -4,7 +4,13 @@ import * as types from './mutation_types';
export const setInitialState = ({ commit }, data) => commit(types.SET_INITIAL_STATE, data);
export const updateSettings = ({ commit }, data) => commit(types.UPDATE_SETTINGS, data);
export const toggleLoading = ({ commit }) => commit(types.TOGGLE_LOADING);
-export const receiveSettingsSuccess = ({ commit }, data = {}) => commit(types.SET_SETTINGS, data);
+export const receiveSettingsSuccess = ({ commit }, data) => {
+ if (data) {
+ commit(types.SET_SETTINGS, data);
+ } else {
+ commit(types.SET_IS_DISABLED, true);
+ }
+};
export const resetSettings = ({ commit }) => commit(types.RESET_SETTINGS);
export const fetchSettings = ({ dispatch, state }) => {
diff --git a/app/assets/javascripts/registry/settings/store/mutation_types.js b/app/assets/javascripts/registry/settings/store/mutation_types.js
index db499ffa761..2d071567c1f 100644
--- a/app/assets/javascripts/registry/settings/store/mutation_types.js
+++ b/app/assets/javascripts/registry/settings/store/mutation_types.js
@@ -3,3 +3,4 @@ export const UPDATE_SETTINGS = 'UPDATE_SETTINGS';
export const TOGGLE_LOADING = 'TOGGLE_LOADING';
export const SET_SETTINGS = 'SET_SETTINGS';
export const RESET_SETTINGS = 'RESET_SETTINGS';
+export const SET_IS_DISABLED = 'SET_IS_DISABLED';
diff --git a/app/assets/javascripts/registry/settings/store/mutations.js b/app/assets/javascripts/registry/settings/store/mutations.js
index 25a67cc6973..b773f2dd44c 100644
--- a/app/assets/javascripts/registry/settings/store/mutations.js
+++ b/app/assets/javascripts/registry/settings/store/mutations.js
@@ -16,6 +16,9 @@ export default {
state.settings = settings;
state.original = Object.freeze(settings);
},
+ [types.SET_IS_DISABLED](state, isDisabled) {
+ state.isDisabled = isDisabled;
+ },
[types.RESET_SETTINGS](state) {
state.settings = { ...state.original };
},
diff --git a/app/assets/javascripts/registry/settings/store/state.js b/app/assets/javascripts/registry/settings/store/state.js
index 50c882e1839..582e18e5465 100644
--- a/app/assets/javascripts/registry/settings/store/state.js
+++ b/app/assets/javascripts/registry/settings/store/state.js
@@ -8,6 +8,10 @@ export default () => ({
*/
isLoading: false,
/*
+ * Boolean to determine if the user is allowed to interact with the form
+ */
+ isDisabled: false,
+ /*
* This contains the data shown and manipulated in the UI
* Has the following structure:
* {
diff --git a/app/assets/stylesheets/utilities.scss b/app/assets/stylesheets/utilities.scss
index 1358b3aa6dd..9e99c92d3f2 100644
--- a/app/assets/stylesheets/utilities.scss
+++ b/app/assets/stylesheets/utilities.scss
@@ -56,6 +56,7 @@
.gl-bg-green-100 { @include gl-bg-green-100;}
.gl-text-blue-500 { @include gl-text-blue-500; }
+.gl-text-gray-700 { @include gl-text-gray-700; }
.gl-text-gray-900 { @include gl-text-gray-900; }
.gl-text-red-700 { @include gl-text-red-700; }
.gl-text-orange-700 { @include gl-text-orange-700; }
diff --git a/app/controllers/admin/groups_controller.rb b/app/controllers/admin/groups_controller.rb
index 5455cefdc8e..0245c00aacb 100644
--- a/app/controllers/admin/groups_controller.rb
+++ b/app/controllers/admin/groups_controller.rb
@@ -6,8 +6,7 @@ class Admin::GroupsController < Admin::ApplicationController
before_action :group, only: [:edit, :update, :destroy, :project_update, :members_update]
def index
- @groups = Group.with_statistics.with_route
- @groups = @groups.sort_by_attribute(@sort = params[:sort])
+ @groups = groups.sort_by_attribute(@sort = params[:sort])
@groups = @groups.search(params[:name]) if params[:name].present?
@groups = @groups.page(params[:page])
end
@@ -75,6 +74,10 @@ class Admin::GroupsController < Admin::ApplicationController
private
+ def groups
+ Group.with_statistics.with_route
+ end
+
def group
@group ||= Group.find_by_full_path(params[:id])
end
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index 3000cfb678e..b8d7685c2cf 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -709,4 +709,10 @@ module ProjectsHelper
def show_visibility_confirm_modal?(project)
project.unlink_forks_upon_visibility_decrease_enabled? && project.visibility_level > Gitlab::VisibilityLevel::PRIVATE && project.forks_count > 0
end
+
+ def settings_container_registry_expiration_policy_available?(project)
+ Feature.enabled?(:registry_retention_policies_settings, project) &&
+ Gitlab.config.registry.enabled &&
+ can?(current_user, :read_container_image, project)
+ end
end
diff --git a/app/models/concerns/loaded_in_group_list.rb b/app/models/concerns/loaded_in_group_list.rb
index fc15c6d55ed..79ff82d9f99 100644
--- a/app/models/concerns/loaded_in_group_list.rb
+++ b/app/models/concerns/loaded_in_group_list.rb
@@ -73,3 +73,5 @@ module LoadedInGroupList
@member_count ||= try(:preloaded_member_count) || users.count
end
end
+
+LoadedInGroupList::ClassMethods.prepend_if_ee('EE::LoadedInGroupList::ClassMethods')
diff --git a/app/models/group.rb b/app/models/group.rb
index b642b177df1..ea5d46e23f4 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -467,6 +467,10 @@ class Group < Namespace
import_export_upload&.export_file
end
+ def adjourned_deletion?
+ false
+ end
+
private
def update_two_factor_requirement
diff --git a/app/views/admin/groups/_group.html.haml b/app/views/admin/groups/_group.html.haml
index 3444e423235..855858ff929 100644
--- a/app/views/admin/groups/_group.html.haml
+++ b/app/views/admin/groups/_group.html.haml
@@ -10,6 +10,7 @@
= storage_counter(group.storage_size)
= render_if_exists 'admin/namespace_plan_badge', namespace: group
+ = render_if_exists 'admin/groups/marked_for_deletion_badge', group: group
%span
= icon('bookmark')
diff --git a/app/views/groups/settings/_advanced.html.haml b/app/views/groups/settings/_advanced.html.haml
index 307309c6ca3..2734ab538a0 100644
--- a/app/views/groups/settings/_advanced.html.haml
+++ b/app/views/groups/settings/_advanced.html.haml
@@ -39,12 +39,5 @@
%li= s_("GroupSettings|If the parent group's visibility is lower than the group current visibility, visibility levels for subgroups and projects will be changed to match the new parent group's visibility.")
= f.submit s_('GroupSettings|Transfer group'), class: 'btn btn-warning'
-.sub-section
- %h4.danger-title= _('Remove group')
- = form_tag(@group, method: :delete) do
- %p
- = _('Removing group will cause all child projects and resources to be removed.')
- %br
- %strong= _('Removed group can not be restored!')
-
- = button_to _('Remove group'), '#', class: 'btn btn-remove js-confirm-danger', data: { 'confirm-danger-message' => remove_group_message(@group) }
+= render 'groups/settings/remove', group: @group
+= render_if_exists 'groups/settings/restore', group: @group
diff --git a/app/views/groups/settings/_permanent_deletion.html.haml b/app/views/groups/settings/_permanent_deletion.html.haml
new file mode 100644
index 00000000000..31e2bac70be
--- /dev/null
+++ b/app/views/groups/settings/_permanent_deletion.html.haml
@@ -0,0 +1,9 @@
+.sub-section
+ %h4.danger-title= _('Remove group')
+ = form_tag(group, method: :delete) do
+ %p
+ = _('Removing group will cause all child projects and resources to be removed.')
+ %br
+ %strong= _('Removed group can not be restored!')
+
+ = button_to _('Remove group'), '#', class: 'btn btn-remove js-confirm-danger', data: { 'confirm-danger-message' => remove_group_message(group) }
diff --git a/app/views/groups/settings/_remove.html.haml b/app/views/groups/settings/_remove.html.haml
new file mode 100644
index 00000000000..a617467019a
--- /dev/null
+++ b/app/views/groups/settings/_remove.html.haml
@@ -0,0 +1,5 @@
+- if group.adjourned_deletion?
+ = render_if_exists 'groups/settings/adjourned_deletion', group: group
+- else
+ = render 'groups/settings/permanent_deletion', group: group
+
diff --git a/app/views/groups/show.html.haml b/app/views/groups/show.html.haml
index 457d05b4a97..4916c4651dd 100644
--- a/app/views/groups/show.html.haml
+++ b/app/views/groups/show.html.haml
@@ -9,6 +9,8 @@
= render 'groups/home_panel'
+ = render_if_exists 'groups/self_or_ancestor_marked_for_deletion_notice', group: @group
+
.groups-listing{ data: { endpoints: { default: group_children_path(@group, format: :json), shared: group_shared_projects_path(@group, format: :json) } } }
.top-area.group-nav-container.justify-content-between
.scrolling-tabs-container.inner-page-scroll-tabs
diff --git a/app/views/kaminari/gitlab/_first_page.html.haml b/app/views/kaminari/gitlab/_first_page.html.haml
deleted file mode 100644
index 3b7d4a1c578..00000000000
--- a/app/views/kaminari/gitlab/_first_page.html.haml
+++ /dev/null
@@ -1,9 +0,0 @@
--# Link to the "First" page
--# available local variables
--# url: url to the first page
--# current_page: a page object for the currently displayed page
--# total_pages: total number of pages
--# per_page: number of items to fetch per page
--# remote: data-remote
-%li.page-item.js-first-button
- = link_to_unless current_page.first?, raw(t 'views.pagination.first'), url, remote: remote, class: 'page-link'
diff --git a/app/views/kaminari/gitlab/_last_page.html.haml b/app/views/kaminari/gitlab/_last_page.html.haml
deleted file mode 100644
index 7836e17f877..00000000000
--- a/app/views/kaminari/gitlab/_last_page.html.haml
+++ /dev/null
@@ -1,9 +0,0 @@
--# Link to the "Last" page
--# available local variables
--# url: url to the last page
--# current_page: a page object for the currently displayed page
--# total_pages: total number of pages
--# per_page: number of items to fetch per page
--# remote: data-remote
-%li.page-item.js-last-button
- = link_to_unless current_page.last?, raw(t 'views.pagination.last'), url, {remote: remote, class: 'page-link'}
diff --git a/app/views/kaminari/gitlab/_next_page.html.haml b/app/views/kaminari/gitlab/_next_page.html.haml
index a7fa1a21a6c..9572dd91330 100644
--- a/app/views/kaminari/gitlab/_next_page.html.haml
+++ b/app/views/kaminari/gitlab/_next_page.html.haml
@@ -9,4 +9,6 @@
- page_url = current_page.last? ? '#' : url
%li.page-item.js-next-button{ class: ('disabled' if current_page.last?) }
- = link_to raw(t 'views.pagination.next'), page_url, rel: 'next', remote: remote, class: 'page-link'
+ = link_to page_url, rel: 'next', remote: remote, class: 'page-link' do
+ = s_('Pagination|Next')
+ = sprite_icon('angle-right', size: 8)
diff --git a/app/views/kaminari/gitlab/_page.html.haml b/app/views/kaminari/gitlab/_page.html.haml
index d0dc1784540..33e00256100 100644
--- a/app/views/kaminari/gitlab/_page.html.haml
+++ b/app/views/kaminari/gitlab/_page.html.haml
@@ -6,5 +6,9 @@
-# total_pages: total number of pages
-# per_page: number of items to fetch per page
-# remote: data-remote
-%li.page-item.js-pagination-page{ class: [active_when(page.current?), ('sibling' if page.next? || page.prev?), ('d-none d-md-block' if !page.current?) ] }
+%li.page-item.js-pagination-page{ class: [active_when(page.current?),
+ ('sibling' if page.next? || page.prev?),
+ ('js-first-button' if page.first?),
+ ('js-last-button' if page.last?),
+ ('d-none d-md-block' if !page.current?) ] }
= link_to page, url, { remote: remote, rel: page.next? ? 'next' : page.prev? ? 'prev' : nil, class: 'page-link' }
diff --git a/app/views/kaminari/gitlab/_paginator.html.haml b/app/views/kaminari/gitlab/_paginator.html.haml
index ac9e274dbc7..1b2edc0ad22 100644
--- a/app/views/kaminari/gitlab/_paginator.html.haml
+++ b/app/views/kaminari/gitlab/_paginator.html.haml
@@ -8,14 +8,10 @@
= paginator.render do
.gl-pagination.prepend-top-default
%ul.pagination.justify-content-center
- - unless current_page.first?
- = first_page_tag unless total_pages < 5 # As kaminari will always show the first 5 pages
= prev_page_tag
- each_page do |page|
- - if page.left_outer? || page.right_outer? || page.inside_window?
+ - if page.left_outer? || page.right_outer? || page.inside_window? || page.first? || page.last?
= page_tag page
- elsif !page.was_truncated?
= gap_tag
= next_page_tag
- - unless current_page.last?
- = last_page_tag unless total_pages < 5
diff --git a/app/views/kaminari/gitlab/_prev_page.html.haml b/app/views/kaminari/gitlab/_prev_page.html.haml
index 12b0e106a62..4ba7ab6488a 100644
--- a/app/views/kaminari/gitlab/_prev_page.html.haml
+++ b/app/views/kaminari/gitlab/_prev_page.html.haml
@@ -9,4 +9,6 @@
- page_url = current_page.first? ? '#' : url
%li.page-item.js-previous-button{ class: ('disabled' if current_page.first?) }
- = link_to raw(t 'views.pagination.previous'), page_url, rel: 'prev', remote: remote, class: 'page-link'
+ = link_to page_url, rel: 'prev', remote: remote, class: 'page-link' do
+ = sprite_icon('angle-left', size: 8)
+ = s_('Pagination|Prev')
diff --git a/app/views/kaminari/gitlab/_without_count.html.haml b/app/views/kaminari/gitlab/_without_count.html.haml
index f780400ebcb..d13f6ca5fa8 100644
--- a/app/views/kaminari/gitlab/_without_count.html.haml
+++ b/app/views/kaminari/gitlab/_without_count.html.haml
@@ -2,7 +2,11 @@
%ul.pagination.justify-content-center
- if previous_path
%li.page-item.prev
- = link_to(t('views.pagination.previous'), previous_path, rel: 'prev', class: 'page-link')
+ = link_to previous_path, rel: 'prev', class: 'page-link' do
+ = sprite_icon('angle-left', size: 8)
+ = s_('Pagination|Prev')
- if next_path
%li.page-item.next
- = link_to(t('views.pagination.next'), next_path, rel: 'next', class: 'page-link')
+ = link_to next_path, rel: 'next', class: 'page-link' do
+ = s_('Pagination|Next')
+ = sprite_icon('angle-right', size: 8)
diff --git a/app/views/projects/settings/ci_cd/show.html.haml b/app/views/projects/settings/ci_cd/show.html.haml
index a65afeecc17..1358077f2b2 100644
--- a/app/views/projects/settings/ci_cd/show.html.haml
+++ b/app/views/projects/settings/ci_cd/show.html.haml
@@ -62,12 +62,12 @@
.settings-content
= render 'projects/triggers/index'
-- if Feature.enabled?(:registry_retention_policies_settings, @project)
+- if settings_container_registry_expiration_policy_available?(@project)
%section.settings.no-animate#js-registry-policies{ class: ('expanded' if expanded) }
.settings-header
%h4
= _("Container Registry tag expiration policy")
- = link_to icon('question-circle'), help_page_path('user/packages/container_registry/index', anchor: 'retention-and-expiration-policy'), target: '_blank', rel: 'noopener noreferrer'
+ = link_to icon('question-circle'), help_page_path('user/packages/container_registry/index', anchor: 'expiration-policy'), target: '_blank', rel: 'noopener noreferrer'
%button.btn.js-settings-toggle{ type: 'button' }
= expanded ? _('Collapse') : _('Expand')
%p
diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml
index 8f13806e8cd..17bc10af58a 100644
--- a/app/views/projects/show.html.haml
+++ b/app/views/projects/show.html.haml
@@ -20,6 +20,7 @@
= render "archived_notice", project: @project
= render_if_exists "projects/marked_for_deletion_notice", project: @project
+ = render_if_exists "projects/ancestor_group_marked_for_deletion_notice", project: @project
- view_path = @project.default_view