summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/blob/pipeline_tour_success_modal.vue17
-rw-r--r--app/assets/javascripts/pages/groups/registry/repositories/index.js11
-rw-r--r--app/assets/javascripts/pages/projects/blob/show/index.js3
-rw-r--r--app/assets/javascripts/pages/projects/registry/repositories/index.js3
-rw-r--r--app/assets/javascripts/registry/list/components/app.vue153
-rw-r--r--app/assets/javascripts/registry/list/components/collapsible_container.vue155
-rw-r--r--app/assets/javascripts/registry/list/components/group_empty_state.vue46
-rw-r--r--app/assets/javascripts/registry/list/components/project_empty_state.vue133
-rw-r--r--app/assets/javascripts/registry/list/components/table_registry.vue289
-rw-r--r--app/assets/javascripts/registry/list/constants.js8
-rw-r--r--app/assets/javascripts/registry/list/index.js44
-rw-r--r--app/assets/javascripts/registry/list/stores/actions.js46
-rw-r--r--app/assets/javascripts/registry/list/stores/getters.js6
-rw-r--r--app/assets/javascripts/registry/list/stores/index.js15
-rw-r--r--app/assets/javascripts/registry/list/stores/mutation_types.js8
-rw-r--r--app/assets/javascripts/registry/list/stores/mutations.js57
-rw-r--r--app/assets/javascripts/registry/list/stores/state.js27
-rw-r--r--app/assets/javascripts/sidebar/components/lock/lock_issue_sidebar.vue6
-rw-r--r--app/assets/javascripts/sidebar/components/participants/participants.vue2
-rw-r--r--app/assets/stylesheets/framework/buttons.scss1
-rw-r--r--app/assets/stylesheets/pages/issuable.scss13
-rw-r--r--app/controllers/boards/issues_controller.rb2
-rw-r--r--app/controllers/concerns/snippets_actions.rb8
-rw-r--r--app/controllers/groups/registry/repositories_controller.rb13
-rw-r--r--app/controllers/projects/registry/repositories_controller.rb6
-rw-r--r--app/helpers/groups_helper.rb3
-rw-r--r--app/models/concerns/has_repository.rb4
-rw-r--r--app/services/award_emojis/add_service.rb8
-rw-r--r--app/services/award_emojis/destroy_service.rb8
-rw-r--r--app/services/boards/issues/list_service.rb2
-rw-r--r--app/services/issues/close_service.rb2
-rw-r--r--app/views/groups/registry/repositories/index.html.haml31
-rw-r--r--app/views/projects/blob/_pipeline_tour_success.html.haml4
-rw-r--r--app/views/projects/registry/repositories/index.html.haml39
34 files changed, 94 insertions, 1079 deletions
diff --git a/app/assets/javascripts/blob/pipeline_tour_success_modal.vue b/app/assets/javascripts/blob/pipeline_tour_success_modal.vue
index 0739b4d5e39..179a515e5ca 100644
--- a/app/assets/javascripts/blob/pipeline_tour_success_modal.vue
+++ b/app/assets/javascripts/blob/pipeline_tour_success_modal.vue
@@ -3,6 +3,9 @@ import { GlModal, GlSprintf, GlLink } from '@gitlab/ui';
import { sprintf, s__, __ } from '~/locale';
import Cookies from 'js-cookie';
import { glEmojiTag } from '~/emoji';
+import Tracking from '~/tracking';
+
+const trackingMixin = Tracking.mixin();
export default {
beginnerLink:
@@ -23,6 +26,7 @@ export default {
GlSprintf,
GlLink,
},
+ mixins: [trackingMixin],
props: {
goToPipelinesPath: {
type: String,
@@ -32,8 +36,21 @@ export default {
type: String,
required: true,
},
+ humanAccess: {
+ type: String,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ tracking: {
+ label: 'congratulate_first_pipeline',
+ property: this.humanAccess,
+ },
+ };
},
mounted() {
+ this.track();
this.disableModalFromRenderingAgain();
},
methods: {
diff --git a/app/assets/javascripts/pages/groups/registry/repositories/index.js b/app/assets/javascripts/pages/groups/registry/repositories/index.js
index 47fea2be189..cdafe838994 100644
--- a/app/assets/javascripts/pages/groups/registry/repositories/index.js
+++ b/app/assets/javascripts/pages/groups/registry/repositories/index.js
@@ -1,9 +1,10 @@
-import initRegistryImages from '~/registry/list/index';
import registryExplorer from '~/registry/explorer/index';
document.addEventListener('DOMContentLoaded', () => {
- initRegistryImages();
- const { attachMainComponent, attachBreadcrumb } = registryExplorer();
- attachBreadcrumb();
- attachMainComponent();
+ const explorer = registryExplorer();
+
+ if (explorer) {
+ explorer.attachBreadcrumb();
+ explorer.attachMainComponent();
+ }
});
diff --git a/app/assets/javascripts/pages/projects/blob/show/index.js b/app/assets/javascripts/pages/projects/blob/show/index.js
index 4d308d6b07a..9ff68a88f95 100644
--- a/app/assets/javascripts/pages/projects/blob/show/index.js
+++ b/app/assets/javascripts/pages/projects/blob/show/index.js
@@ -45,12 +45,13 @@ document.addEventListener('DOMContentLoaded', () => {
new Vue({
el: successPipelineEl,
render(createElement) {
- const { commitCookie, pipelinesPath: goToPipelinesPath } = this.$el.dataset;
+ const { commitCookie, goToPipelinesPath, humanAccess } = this.$el.dataset;
return createElement(PipelineTourSuccessModal, {
props: {
goToPipelinesPath,
commitCookie,
+ humanAccess,
},
});
},
diff --git a/app/assets/javascripts/pages/projects/registry/repositories/index.js b/app/assets/javascripts/pages/projects/registry/repositories/index.js
index 73469e287ed..cdafe838994 100644
--- a/app/assets/javascripts/pages/projects/registry/repositories/index.js
+++ b/app/assets/javascripts/pages/projects/registry/repositories/index.js
@@ -1,9 +1,6 @@
-import initRegistryImages from '~/registry/list/index';
import registryExplorer from '~/registry/explorer/index';
document.addEventListener('DOMContentLoaded', () => {
- initRegistryImages();
-
const explorer = registryExplorer();
if (explorer) {
diff --git a/app/assets/javascripts/registry/list/components/app.vue b/app/assets/javascripts/registry/list/components/app.vue
deleted file mode 100644
index c555c2b04d1..00000000000
--- a/app/assets/javascripts/registry/list/components/app.vue
+++ /dev/null
@@ -1,153 +0,0 @@
-<script>
-import { mapGetters, mapActions } from 'vuex';
-import { GlLoadingIcon, GlEmptyState } from '@gitlab/ui';
-import store from '../stores';
-import CollapsibleContainer from './collapsible_container.vue';
-import ProjectEmptyState from './project_empty_state.vue';
-import GroupEmptyState from './group_empty_state.vue';
-import { s__, sprintf } from '~/locale';
-
-export default {
- name: 'RegistryListApp',
- components: {
- CollapsibleContainer,
- GlEmptyState,
- GlLoadingIcon,
- ProjectEmptyState,
- GroupEmptyState,
- },
- props: {
- characterError: {
- type: Boolean,
- required: false,
- default: false,
- },
- containersErrorImage: {
- type: String,
- required: true,
- },
- endpoint: {
- type: String,
- required: true,
- },
- helpPagePath: {
- type: String,
- required: true,
- },
- noContainersImage: {
- type: String,
- required: true,
- },
- personalAccessTokensHelpLink: {
- type: String,
- required: false,
- default: null,
- },
- registryHostUrlWithPort: {
- type: String,
- required: false,
- default: null,
- },
- repositoryUrl: {
- type: String,
- required: true,
- },
- isGroupPage: {
- type: Boolean,
- default: false,
- required: false,
- },
- twoFactorAuthHelpLink: {
- type: String,
- required: false,
- default: null,
- },
- },
- store,
- computed: {
- ...mapGetters(['isLoading', 'repos']),
- dockerConnectionErrorText() {
- return sprintf(
- s__(`ContainerRegistry|We are having trouble connecting to Docker, which could be due to an
- issue with your project name or path.
- %{docLinkStart}More Information%{docLinkEnd}`),
- {
- docLinkStart: `<a href="${this.helpPagePath}#docker-connection-error" target="_blank">`,
- docLinkEnd: '</a>',
- },
- false,
- );
- },
- introText() {
- return sprintf(
- s__(`ContainerRegistry|With the Docker Container Registry integrated into GitLab, every
- project can have its own space to store its Docker images.
- %{docLinkStart}More Information%{docLinkEnd}`),
- {
- docLinkStart: `<a href="${this.helpPagePath}" target="_blank">`,
- docLinkEnd: '</a>',
- },
- false,
- );
- },
- noContainerImagesText() {
- return sprintf(
- s__(`ContainerRegistry|With the Container Registry, every project can have its own space to
- store its Docker images. %{docLinkStart}More Information%{docLinkEnd}`),
- {
- docLinkStart: `<a href="${this.helpPagePath}" target="_blank">`,
- docLinkEnd: '</a>',
- },
- false,
- );
- },
- },
- created() {
- this.setMainEndpoint(this.endpoint);
- this.setIsDeleteDisabled(this.isGroupPage);
- },
- mounted() {
- if (!this.characterError) {
- this.fetchRepos();
- }
- },
- methods: {
- ...mapActions(['setMainEndpoint', 'fetchRepos', 'setIsDeleteDisabled']),
- },
-};
-</script>
-<template>
- <div>
- <gl-empty-state
- v-if="characterError"
- :title="s__('ContainerRegistry|Docker connection error')"
- :svg-path="containersErrorImage"
- >
- <template #description>
- <p class="js-character-error-text" v-html="dockerConnectionErrorText"></p>
- </template>
- </gl-empty-state>
-
- <gl-loading-icon v-else-if="isLoading" size="md" class="prepend-top-16" />
-
- <div v-else-if="!isLoading && repos.length">
- <h4>{{ s__('ContainerRegistry|Container Registry') }}</h4>
- <p v-html="introText"></p>
- <collapsible-container v-for="item in repos" :key="item.id" :repo="item" />
- </div>
- <project-empty-state
- v-else-if="!isGroupPage"
- :no-containers-image="noContainersImage"
- :help-page-path="helpPagePath"
- :repository-url="repositoryUrl"
- :two-factor-auth-help-link="twoFactorAuthHelpLink"
- :personal-access-tokens-help-link="personalAccessTokensHelpLink"
- :registry-host-url-with-port="registryHostUrlWithPort"
- />
- <group-empty-state
- v-else-if="isGroupPage"
- :no-containers-image="noContainersImage"
- :help-page-path="helpPagePath"
- />
- </div>
-</template>
diff --git a/app/assets/javascripts/registry/list/components/collapsible_container.vue b/app/assets/javascripts/registry/list/components/collapsible_container.vue
deleted file mode 100644
index 9786a1a3f75..00000000000
--- a/app/assets/javascripts/registry/list/components/collapsible_container.vue
+++ /dev/null
@@ -1,155 +0,0 @@
-<script>
-import { mapActions, mapGetters } from 'vuex';
-import {
- GlLoadingIcon,
- GlButton,
- GlTooltipDirective,
- GlModal,
- GlModalDirective,
- GlEmptyState,
-} from '@gitlab/ui';
-import createFlash from '~/flash';
-import Tracking from '~/tracking';
-import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
-import Icon from '~/vue_shared/components/icon.vue';
-import TableRegistry from './table_registry.vue';
-import { DELETE_REPO_ERROR_MESSAGE } from '../constants';
-import { __, sprintf } from '~/locale';
-
-export default {
- name: 'CollapsibeContainerRegisty',
- components: {
- ClipboardButton,
- TableRegistry,
- GlLoadingIcon,
- GlButton,
- Icon,
- GlModal,
- GlEmptyState,
- },
- directives: {
- GlTooltip: GlTooltipDirective,
- GlModal: GlModalDirective,
- },
- mixins: [Tracking.mixin()],
- props: {
- repo: {
- type: Object,
- required: true,
- },
- },
- data() {
- return {
- isOpen: false,
- modalId: `confirm-repo-deletion-modal-${this.repo.id}`,
- tracking: {
- label: 'registry_repository_delete',
- },
- };
- },
- computed: {
- ...mapGetters(['isDeleteDisabled']),
- iconName() {
- return this.isOpen ? 'angle-up' : 'angle-right';
- },
- canDeleteRepo() {
- return this.repo.canDelete && !this.isDeleteDisabled;
- },
- deleteImageConfirmationMessage() {
- return sprintf(__('Image %{imageName} was scheduled for deletion from the registry.'), {
- imageName: this.repo.name,
- });
- },
- },
- methods: {
- ...mapActions(['fetchRepos', 'fetchList', 'deleteItem']),
- toggleRepo() {
- this.isOpen = !this.isOpen;
-
- if (this.isOpen) {
- this.fetchList({ repo: this.repo });
- }
- },
- handleDeleteRepository() {
- this.track('confirm_delete');
- return this.deleteItem(this.repo)
- .then(() => {
- createFlash(this.deleteImageConfirmationMessage, 'notice');
- this.fetchRepos();
- })
- .catch(() => createFlash(DELETE_REPO_ERROR_MESSAGE));
- },
- },
-};
-</script>
-
-<template>
- <div class="container-image">
- <div class="container-image-head">
- <gl-button class="js-toggle-repo btn-link align-baseline" @click="toggleRepo">
- <icon :name="iconName" />
- {{ repo.name }}
- </gl-button>
-
- <clipboard-button
- v-if="repo.location"
- :text="repo.location"
- :title="repo.location"
- css-class="btn-default btn-transparent btn-clipboard"
- />
-
- <div class="controls d-none d-sm-block float-right">
- <gl-button
- v-if="canDeleteRepo"
- v-gl-tooltip
- v-gl-modal="modalId"
- :title="s__('ContainerRegistry|Remove repository')"
- :aria-label="s__('ContainerRegistry|Remove repository')"
- class="js-remove-repo btn-inverted"
- variant="danger"
- @click="track('click_button')"
- >
- <icon name="remove" />
- </gl-button>
- </div>
- </div>
-
- <gl-loading-icon v-if="repo.isLoading" size="md" class="append-bottom-20" />
-
- <div v-else-if="!repo.isLoading && isOpen" class="container-image-tags">
- <table-registry v-if="repo.list.length" :repo="repo" :can-delete-repo="canDeleteRepo" />
- <gl-empty-state
- v-else
- :title="s__('ContainerRegistry|This image has no active tags')"
- :description="
- s__(
- `ContainerRegistry|The last tag related to this image was recently removed.
- This empty image and any associated data will be automatically removed as part of the regular Garbage Collection process.
- If you have any questions, contact your administrator.`,
- )
- "
- class="mx-auto my-0"
- />
- </div>
- <gl-modal
- ref="deleteModal"
- :modal-id="modalId"
- ok-variant="danger"
- @ok="handleDeleteRepository"
- @cancel="track('cancel_delete')"
- >
- <template v-slot:modal-title>{{ s__('ContainerRegistry|Remove repository') }}</template>
- <p
- v-html="
- sprintf(
- s__(
- 'ContainerRegistry|You are about to remove repository <b>%{title}</b>. Once you confirm, this repository will be permanently deleted.',
- ),
- { title: repo.name },
- )
- "
- ></p>
- <template v-slot:modal-ok>{{ __('Remove') }}</template>
- </gl-modal>
- </div>
-</template>
diff --git a/app/assets/javascripts/registry/list/components/group_empty_state.vue b/app/assets/javascripts/registry/list/components/group_empty_state.vue
deleted file mode 100644
index 7885fd2146d..00000000000
--- a/app/assets/javascripts/registry/list/components/group_empty_state.vue
+++ /dev/null
@@ -1,46 +0,0 @@
-<script>
-import { GlEmptyState } from '@gitlab/ui';
-import { s__, sprintf } from '~/locale';
-
-export default {
- name: 'GroupEmptyState',
- components: {
- GlEmptyState,
- },
- props: {
- noContainersImage: {
- type: String,
- required: true,
- },
- helpPagePath: {
- type: String,
- required: true,
- },
- },
- computed: {
- noContainerImagesText() {
- return sprintf(
- s__(
- `ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. Push at least one Docker image in one of this group's projects in order to show up here. %{docLinkStart}More Information%{docLinkEnd}`,
- ),
- {
- docLinkStart: `<a href="${this.helpPagePath}" target="_blank">`,
- docLinkEnd: '</a>',
- },
- false,
- );
- },
- },
-};
-</script>
-<template>
- <gl-empty-state
- :title="s__('ContainerRegistry|There are no container images available in this group')"
- :svg-path="noContainersImage"
- class="container-message"
- >
- <template #description>
- <p class="js-no-container-images-text" v-html="noContainerImagesText"></p>
- </template>
- </gl-empty-state>
-</template>
diff --git a/app/assets/javascripts/registry/list/components/project_empty_state.vue b/app/assets/javascripts/registry/list/components/project_empty_state.vue
deleted file mode 100644
index 900498ed03d..00000000000
--- a/app/assets/javascripts/registry/list/components/project_empty_state.vue
+++ /dev/null
@@ -1,133 +0,0 @@
-<script>
-import { GlEmptyState } from '@gitlab/ui';
-import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
-import { s__, sprintf } from '~/locale';
-
-export default {
- name: 'ProjectEmptyState',
- components: {
- ClipboardButton,
- GlEmptyState,
- },
- props: {
- noContainersImage: {
- type: String,
- required: true,
- },
- repositoryUrl: {
- type: String,
- required: true,
- },
- helpPagePath: {
- type: String,
- required: true,
- },
- twoFactorAuthHelpLink: {
- type: String,
- required: true,
- },
- personalAccessTokensHelpLink: {
- type: String,
- required: true,
- },
- registryHostUrlWithPort: {
- type: String,
- required: true,
- },
- },
- computed: {
- dockerBuildCommand() {
- // eslint-disable-next-line @gitlab/require-i18n-strings
- return `docker build -t ${this.repositoryUrl} .`;
- },
- dockerPushCommand() {
- // eslint-disable-next-line @gitlab/require-i18n-strings
- return `docker push ${this.repositoryUrl}`;
- },
- dockerLoginCommand() {
- // eslint-disable-next-line @gitlab/require-i18n-strings
- return `docker login ${this.registryHostUrlWithPort}`;
- },
- noContainerImagesText() {
- return sprintf(
- s__(`ContainerRegistry|With the Container Registry, every project can have its own space to
- store its Docker images. %{docLinkStart}More Information%{docLinkEnd}`),
- {
- docLinkStart: `<a href="${this.helpPagePath}" target="_blank">`,
- docLinkEnd: '</a>',
- },
- false,
- );
- },
- notLoggedInToRegistryText() {
- return sprintf(
- s__(`ContainerRegistry|If you are not already logged in, you need to authenticate to
- the Container Registry by using your GitLab username and password. If you have
- %{twofaDocLinkStart}Two-Factor Authentication%{twofaDocLinkEnd} enabled, use a
- %{personalAccessTokensDocLinkStart}Personal Access Token%{personalAccessTokensDocLinkEnd}
- instead of a password.`),
- {
- twofaDocLinkStart: `<a href="${this.twoFactorAuthHelpLink}" target="_blank">`,
- twofaDocLinkEnd: '</a>',
- personalAccessTokensDocLinkStart: `<a href="${this.personalAccessTokensHelpLink}" target="_blank">`,
- personalAccessTokensDocLinkEnd: '</a>',
- },
- false,
- );
- },
- },
-};
-</script>
-<template>
- <gl-empty-state
- :title="s__('ContainerRegistry|There are no container images stored for this project')"
- :svg-path="noContainersImage"
- class="container-message"
- >
- <template #description>
- <p class="js-no-container-images-text" v-html="noContainerImagesText"></p>
- <h5>{{ s__('ContainerRegistry|Quick Start') }}</h5>
- <p class="js-not-logged-in-to-registry-text" v-html="notLoggedInToRegistryText"></p>
- <div class="input-group append-bottom-10">
- <input :value="dockerLoginCommand" type="text" class="form-control monospace" readonly />
- <span class="input-group-append">
- <clipboard-button
- :text="dockerLoginCommand"
- :title="s__('ContainerRegistry|Copy login command')"
- class="input-group-text"
- />
- </span>
- </div>
- <p></p>
- <p>
- {{
- s__(
- 'ContainerRegistry|You can add an image to this registry with the following commands:',
- )
- }}
- </p>
-
- <div class="input-group append-bottom-10">
- <input :value="dockerBuildCommand" type="text" class="form-control monospace" readonly />
- <span class="input-group-append">
- <clipboard-button
- :text="dockerBuildCommand"
- :title="s__('ContainerRegistry|Copy build command')"
- class="input-group-text"
- />
- </span>
- </div>
-
- <div class="input-group">
- <input :value="dockerPushCommand" type="text" class="form-control monospace" readonly />
- <span class="input-group-append">
- <clipboard-button
- :text="dockerPushCommand"
- :title="s__('ContainerRegistry|Copy push command')"
- class="input-group-text"
- />
- </span>
- </div>
- </template>
- </gl-empty-state>
-</template>
diff --git a/app/assets/javascripts/registry/list/components/table_registry.vue b/app/assets/javascripts/registry/list/components/table_registry.vue
deleted file mode 100644
index 4e14db7f578..00000000000
--- a/app/assets/javascripts/registry/list/components/table_registry.vue
+++ /dev/null
@@ -1,289 +0,0 @@
-<script>
-import { mapActions, mapGetters } from 'vuex';
-import { GlButton, GlFormCheckbox, GlTooltipDirective, GlModal } from '@gitlab/ui';
-import Tracking from '~/tracking';
-import { n__, s__, sprintf } from '~/locale';
-import createFlash from '~/flash';
-import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
-import TablePagination from '~/vue_shared/components/pagination/table_pagination.vue';
-import Icon from '~/vue_shared/components/icon.vue';
-import timeagoMixin from '~/vue_shared/mixins/timeago';
-import { numberToHumanSize } from '~/lib/utils/number_utils';
-import { FETCH_REGISTRY_ERROR_MESSAGE, DELETE_REGISTRY_ERROR_MESSAGE } from '../constants';
-
-export default {
- components: {
- ClipboardButton,
- TablePagination,
- GlFormCheckbox,
- GlButton,
- Icon,
- GlModal,
- },
- directives: {
- GlTooltip: GlTooltipDirective,
- },
- mixins: [timeagoMixin, Tracking.mixin()],
- props: {
- repo: {
- type: Object,
- required: true,
- },
- canDeleteRepo: {
- type: Boolean,
- default: false,
- required: false,
- },
- },
- data() {
- return {
- selectedItems: [],
- itemsToBeDeleted: [],
- modalId: `confirm-image-deletion-modal-${this.repo.id}`,
- selectAllChecked: false,
- modalDescription: '',
- };
- },
- computed: {
- ...mapGetters(['isDeleteDisabled']),
- bulkDeletePath() {
- return this.repo.tagsPath ? this.repo.tagsPath.replace('?format=json', '/bulk_destroy') : '';
- },
- shouldRenderPagination() {
- return this.repo.pagination.total > this.repo.pagination.perPage;
- },
- modalAction() {
- return n__(
- 'ContainerRegistry|Remove tag',
- 'ContainerRegistry|Remove tags',
- this.itemsToBeDeleted.length === 0 ? 1 : this.itemsToBeDeleted.length,
- );
- },
- isMultiDelete() {
- return this.itemsToBeDeleted.length > 1;
- },
- tracking() {
- return {
- property: this.repo.name,
- label: this.isMultiDelete ? 'bulk_registry_tag_delete' : 'registry_tag_delete',
- };
- },
- },
- methods: {
- ...mapActions(['fetchList', 'deleteItem', 'multiDeleteItems']),
- setModalDescription(itemIndex = -1) {
- if (itemIndex === -1) {
- this.modalDescription = sprintf(
- s__(`ContainerRegistry|You are about to remove <b>%{count}</b> tags. Are you sure?`),
- { count: this.itemsToBeDeleted.length },
- );
- } else {
- const { tag } = this.repo.list[itemIndex];
-
- this.modalDescription = sprintf(
- s__(`ContainerRegistry|You are about to remove <b>%{title}</b>. Are you sure?`),
- { title: `${this.repo.name}:${tag}` },
- );
- }
- },
- layers(item) {
- return item.layers ? n__('%d layer', '%d layers', item.layers) : '';
- },
- formatSize(size) {
- return numberToHumanSize(size);
- },
- deleteSingleItem(index) {
- this.setModalDescription(index);
- this.itemsToBeDeleted = [index];
- this.track('click_button');
- this.$refs.deleteModal.show();
- },
- deleteMultipleItems() {
- this.itemsToBeDeleted = [...this.selectedItems];
- if (this.selectedItems.length === 1) {
- this.setModalDescription(this.itemsToBeDeleted[0]);
- } else if (this.selectedItems.length > 1) {
- this.setModalDescription();
- }
- this.track('click_button');
- this.$refs.deleteModal.show();
- },
- handleSingleDelete(itemToDelete) {
- this.itemsToBeDeleted = [];
- this.deleteItem(itemToDelete)
- .then(() => this.fetchList({ repo: this.repo }))
- .catch(() => createFlash(DELETE_REGISTRY_ERROR_MESSAGE));
- },
- handleMultipleDelete() {
- const { itemsToBeDeleted } = this;
- this.itemsToBeDeleted = [];
- this.selectedItems = [];
-
- if (this.bulkDeletePath) {
- this.multiDeleteItems({
- path: this.bulkDeletePath,
- items: itemsToBeDeleted.map(x => this.repo.list[x].tag),
- })
- .then(() => this.fetchList({ repo: this.repo }))
- .catch(() => createFlash(DELETE_REGISTRY_ERROR_MESSAGE));
- } else {
- createFlash(DELETE_REGISTRY_ERROR_MESSAGE);
- }
- },
- onPageChange(pageNumber) {
- this.fetchList({ repo: this.repo, page: pageNumber }).catch(() =>
- createFlash(FETCH_REGISTRY_ERROR_MESSAGE),
- );
- },
- onSelectAllChange() {
- if (this.selectAllChecked) {
- this.deselectAll();
- } else {
- this.selectAll();
- }
- },
- selectAll() {
- this.selectedItems = this.repo.list.map((x, index) => index);
- this.selectAllChecked = true;
- },
- deselectAll() {
- this.selectedItems = [];
- this.selectAllChecked = false;
- },
- updateselectedItems(index) {
- const delIndex = this.selectedItems.findIndex(x => x === index);
-
- if (delIndex > -1) {
- this.selectedItems.splice(delIndex, 1);
- this.selectAllChecked = false;
- } else {
- this.selectedItems.push(index);
-
- if (this.selectedItems.length === this.repo.list.length) {
- this.selectAllChecked = true;
- }
- }
- },
- canDeleteRow(item) {
- return item && item.canDelete && !this.isDeleteDisabled;
- },
- onDeletionConfirmed() {
- this.track('confirm_delete');
- if (this.isMultiDelete) {
- this.handleMultipleDelete();
- } else {
- const index = this.itemsToBeDeleted[0];
- this.handleSingleDelete(this.repo.list[index]);
- }
- },
- },
-};
-</script>
-<template>
- <div>
- <table class="table tags">
- <thead>
- <tr>
- <th>
- <gl-form-checkbox
- v-if="canDeleteRepo"
- class="js-select-all-checkbox"
- :checked="selectAllChecked"
- @change="onSelectAllChange"
- />
- </th>
- <th>{{ s__('ContainerRegistry|Tag') }}</th>
- <th ref="imageId">{{ s__('ContainerRegistry|Image ID') }}</th>
- <th>{{ s__('ContainerRegistry|Size') }}</th>
- <th>{{ s__('ContainerRegistry|Last Updated') }}</th>
- <th>
- <gl-button
- v-if="canDeleteRepo"
- ref="bulkDeleteButton"
- v-gl-tooltip
- :disabled="!selectedItems || selectedItems.length === 0"
- class="float-right"
- variant="danger"
- :title="s__('ContainerRegistry|Remove selected tags')"
- :aria-label="s__('ContainerRegistry|Remove selected tags')"
- @click="deleteMultipleItems()"
- >
- <icon name="remove" />
- </gl-button>
- </th>
- </tr>
- </thead>
- <tbody>
- <tr v-for="(item, index) in repo.list" :key="item.tag" class="registry-image-row">
- <td class="check">
- <gl-form-checkbox
- v-if="canDeleteRow(item)"
- class="js-select-checkbox"
- :checked="selectedItems && selectedItems.includes(index)"
- @change="updateselectedItems(index)"
- />
- </td>
- <td class="monospace">
- {{ item.tag }}
- <clipboard-button
- v-if="item.location"
- :title="item.location"
- :text="item.location"
- css-class="btn-default btn-transparent btn-clipboard"
- />
- </td>
- <td>
- <span v-gl-tooltip.bottom class="monospace" :title="item.revision">{{
- item.shortRevision
- }}</span>
- </td>
- <td>
- {{ formatSize(item.size) }}
- <template v-if="item.size && item.layers"
- >&middot;</template
- >
- {{ layers(item) }}
- </td>
-
- <td>
- <span v-gl-tooltip.bottom :title="tooltipTitle(item.createdAt)">{{
- timeFormatted(item.createdAt)
- }}</span>
- </td>
-
- <td class="content action-buttons">
- <gl-button
- v-if="canDeleteRow(item)"
- :title="s__('ContainerRegistry|Remove tag')"
- :aria-label="s__('ContainerRegistry|Remove tag')"
- variant="danger"
- class="js-delete-registry-row float-right btn-inverted btn-border-color btn-icon"
- @click="deleteSingleItem(index)"
- >
- <icon name="remove" />
- </gl-button>
- </td>
- </tr>
- </tbody>
- </table>
-
- <table-pagination
- v-if="shouldRenderPagination"
- :change="onPageChange"
- :page-info="repo.pagination"
- class="js-registry-pagination"
- />
-
- <gl-modal
- ref="deleteModal"
- :modal-id="modalId"
- ok-variant="danger"
- @ok="onDeletionConfirmed"
- @cancel="track('cancel_delete')"
- >
- <template v-slot:modal-title>{{ modalAction }}</template>
- <template v-slot:modal-ok>{{ modalAction }}</template>
- <p v-html="modalDescription"></p>
- </gl-modal>
- </div>
-</template>
diff --git a/app/assets/javascripts/registry/list/constants.js b/app/assets/javascripts/registry/list/constants.js
deleted file mode 100644
index e55ea9cc9d9..00000000000
--- a/app/assets/javascripts/registry/list/constants.js
+++ /dev/null
@@ -1,8 +0,0 @@
-import { __ } from '~/locale';
-
-export const FETCH_REGISTRY_ERROR_MESSAGE = __(
- 'Something went wrong while fetching the registry list.',
-);
-export const FETCH_REPOS_ERROR_MESSAGE = __('Something went wrong while fetching the projects.');
-export const DELETE_REPO_ERROR_MESSAGE = __('Something went wrong on our end.');
-export const DELETE_REGISTRY_ERROR_MESSAGE = __('Something went wrong on our end.');
diff --git a/app/assets/javascripts/registry/list/index.js b/app/assets/javascripts/registry/list/index.js
deleted file mode 100644
index e8e54fda169..00000000000
--- a/app/assets/javascripts/registry/list/index.js
+++ /dev/null
@@ -1,44 +0,0 @@
-import Vue from 'vue';
-import registryApp from './components/app.vue';
-import Translate from '~/vue_shared/translate';
-
-Vue.use(Translate);
-
-export default () => {
- const el = document.getElementById('js-vue-registry-images');
-
- if (!el) {
- return null;
- }
-
- return new Vue({
- el,
- components: {
- registryApp,
- },
- data() {
- const { dataset } = el;
- return {
- registryData: {
- endpoint: dataset.endpoint,
- characterError: Boolean(dataset.characterError),
- helpPagePath: dataset.helpPagePath,
- noContainersImage: dataset.noContainersImage,
- containersErrorImage: dataset.containersErrorImage,
- repositoryUrl: dataset.repositoryUrl,
- isGroupPage: dataset.isGroupPage,
- personalAccessTokensHelpLink: dataset.personalAccessTokensHelpLink,
- registryHostUrlWithPort: dataset.registryHostUrlWithPort,
- twoFactorAuthHelpLink: dataset.twoFactorAuthHelpLink,
- },
- };
- },
- render(createElement) {
- return createElement('registry-app', {
- props: {
- ...this.registryData,
- },
- });
- },
- });
-};
diff --git a/app/assets/javascripts/registry/list/stores/actions.js b/app/assets/javascripts/registry/list/stores/actions.js
deleted file mode 100644
index 6afba618486..00000000000
--- a/app/assets/javascripts/registry/list/stores/actions.js
+++ /dev/null
@@ -1,46 +0,0 @@
-import axios from '~/lib/utils/axios_utils';
-import createFlash from '~/flash';
-import * as types from './mutation_types';
-import { FETCH_REPOS_ERROR_MESSAGE, FETCH_REGISTRY_ERROR_MESSAGE } from '../constants';
-
-export const fetchRepos = ({ commit, state }) => {
- commit(types.TOGGLE_MAIN_LOADING);
-
- return axios
- .get(state.endpoint)
- .then(({ data }) => {
- commit(types.TOGGLE_MAIN_LOADING);
- commit(types.SET_REPOS_LIST, data);
- })
- .catch(() => {
- commit(types.TOGGLE_MAIN_LOADING);
- createFlash(FETCH_REPOS_ERROR_MESSAGE);
- });
-};
-
-export const fetchList = ({ commit }, { repo, page }) => {
- commit(types.TOGGLE_REGISTRY_LIST_LOADING, repo);
- return axios
- .get(repo.tagsPath, { params: { page } })
- .then(response => {
- const { headers, data } = response;
-
- commit(types.TOGGLE_REGISTRY_LIST_LOADING, repo);
- commit(types.SET_REGISTRY_LIST, { repo, resp: data, headers });
- })
- .catch(() => {
- commit(types.TOGGLE_REGISTRY_LIST_LOADING, repo);
- createFlash(FETCH_REGISTRY_ERROR_MESSAGE);
- });
-};
-
-export const deleteItem = (_, item) => axios.delete(item.destroyPath);
-export const multiDeleteItems = (_, { path, items }) =>
- axios.delete(path, { params: { ids: items } });
-
-export const setMainEndpoint = ({ commit }, data) => commit(types.SET_MAIN_ENDPOINT, data);
-export const setIsDeleteDisabled = ({ commit }, data) => commit(types.SET_IS_DELETE_DISABLED, data);
-export const toggleLoading = ({ commit }) => commit(types.TOGGLE_MAIN_LOADING);
-
-// prevent babel-plugin-rewire from generating an invalid default during karma tests
-export default () => {};
diff --git a/app/assets/javascripts/registry/list/stores/getters.js b/app/assets/javascripts/registry/list/stores/getters.js
deleted file mode 100644
index ac90bde1b2a..00000000000
--- a/app/assets/javascripts/registry/list/stores/getters.js
+++ /dev/null
@@ -1,6 +0,0 @@
-export const isLoading = state => state.isLoading;
-export const repos = state => state.repos;
-export const isDeleteDisabled = state => state.isDeleteDisabled;
-
-// prevent babel-plugin-rewire from generating an invalid default during karma tests
-export default () => {};
diff --git a/app/assets/javascripts/registry/list/stores/index.js b/app/assets/javascripts/registry/list/stores/index.js
deleted file mode 100644
index 1bb06bd6e81..00000000000
--- a/app/assets/javascripts/registry/list/stores/index.js
+++ /dev/null
@@ -1,15 +0,0 @@
-import Vue from 'vue';
-import Vuex from 'vuex';
-import * as actions from './actions';
-import * as getters from './getters';
-import mutations from './mutations';
-import createState from './state';
-
-Vue.use(Vuex);
-
-export default new Vuex.Store({
- state: createState(),
- actions,
- getters,
- mutations,
-});
diff --git a/app/assets/javascripts/registry/list/stores/mutation_types.js b/app/assets/javascripts/registry/list/stores/mutation_types.js
deleted file mode 100644
index 6740bfede1a..00000000000
--- a/app/assets/javascripts/registry/list/stores/mutation_types.js
+++ /dev/null
@@ -1,8 +0,0 @@
-export const SET_MAIN_ENDPOINT = 'SET_MAIN_ENDPOINT';
-export const SET_IS_DELETE_DISABLED = 'SET_IS_DELETE_DISABLED';
-
-export const SET_REPOS_LIST = 'SET_REPOS_LIST';
-export const TOGGLE_MAIN_LOADING = 'TOGGLE_MAIN_LOADING';
-
-export const SET_REGISTRY_LIST = 'SET_REGISTRY_LIST';
-export const TOGGLE_REGISTRY_LIST_LOADING = 'TOGGLE_REGISTRY_LIST_LOADING';
diff --git a/app/assets/javascripts/registry/list/stores/mutations.js b/app/assets/javascripts/registry/list/stores/mutations.js
deleted file mode 100644
index 419de848883..00000000000
--- a/app/assets/javascripts/registry/list/stores/mutations.js
+++ /dev/null
@@ -1,57 +0,0 @@
-import * as types from './mutation_types';
-import { parseIntPagination, normalizeHeaders } from '~/lib/utils/common_utils';
-
-export default {
- [types.SET_MAIN_ENDPOINT](state, endpoint) {
- state.endpoint = endpoint;
- },
-
- [types.SET_IS_DELETE_DISABLED](state, isDeleteDisabled) {
- state.isDeleteDisabled = isDeleteDisabled;
- },
-
- [types.SET_REPOS_LIST](state, list) {
- state.repos = list.map(el => ({
- canDelete: Boolean(el.destroy_path),
- destroyPath: el.destroy_path,
- id: el.id,
- isLoading: false,
- list: [],
- location: el.location,
- name: el.path,
- tagsPath: el.tags_path,
- projectId: el.project_id,
- }));
- },
-
- [types.TOGGLE_MAIN_LOADING](state) {
- state.isLoading = !state.isLoading;
- },
-
- [types.SET_REGISTRY_LIST](state, { repo, resp, headers }) {
- const listToUpdate = state.repos.find(el => el.id === repo.id);
-
- const normalizedHeaders = normalizeHeaders(headers);
- const pagination = parseIntPagination(normalizedHeaders);
-
- listToUpdate.pagination = pagination;
-
- listToUpdate.list = resp.map(element => ({
- tag: element.name,
- revision: element.revision,
- shortRevision: element.short_revision,
- size: element.total_size,
- layers: element.layers,
- location: element.location,
- createdAt: element.created_at,
- destroyPath: element.destroy_path,
- canDelete: Boolean(element.destroy_path),
- }));
- },
-
- [types.TOGGLE_REGISTRY_LIST_LOADING](state, list) {
- const listToUpdate = state.repos.find(el => el.id === list.id);
-
- listToUpdate.isLoading = !listToUpdate.isLoading;
- },
-};
diff --git a/app/assets/javascripts/registry/list/stores/state.js b/app/assets/javascripts/registry/list/stores/state.js
deleted file mode 100644
index 724c64b4994..00000000000
--- a/app/assets/javascripts/registry/list/stores/state.js
+++ /dev/null
@@ -1,27 +0,0 @@
-export default () => ({
- isLoading: false,
- endpoint: '', // initial endpoint to fetch the repos list
- isDeleteDisabled: false, // controls the delete buttons in the registry
- /**
- * Each object in `repos` has the following strucure:
- * {
- * name: String,
- * isLoading: Boolean,
- * tagsPath: String // endpoint to request the list
- * destroyPath: String // endpoit to delete the repo
- * list: Array // List of the registry images
- * }
- *
- * Each registry image inside `list` has the following structure:
- * {
- * tag: String,
- * revision: String
- * shortRevision: String
- * size: Number
- * layers: Number
- * createdAt: String
- * destroyPath: String // endpoit to delete each image
- * }
- */
- repos: [],
-});
diff --git a/app/assets/javascripts/sidebar/components/lock/lock_issue_sidebar.vue b/app/assets/javascripts/sidebar/components/lock/lock_issue_sidebar.vue
index 012a4f4ad89..728f655d33d 100644
--- a/app/assets/javascripts/sidebar/components/lock/lock_issue_sidebar.vue
+++ b/app/assets/javascripts/sidebar/components/lock/lock_issue_sidebar.vue
@@ -106,17 +106,17 @@ export default {
<div class="title hide-collapsed">
{{ sprintf(__('Lock %{issuableDisplayName}'), { issuableDisplayName: issuableDisplayName }) }}
- <button
+ <a
v-if="isEditable"
class="float-right lock-edit"
- type="button"
+ href="#"
data-track-event="click_edit_button"
data-track-label="right_sidebar"
data-track-property="lock_issue"
@click.prevent="toggleForm"
>
{{ __('Edit') }}
- </button>
+ </a>
</div>
<div class="value sidebar-item-value hide-collapsed">
diff --git a/app/assets/javascripts/sidebar/components/participants/participants.vue b/app/assets/javascripts/sidebar/components/participants/participants.vue
index f2ef7a2268e..db2e51c3aca 100644
--- a/app/assets/javascripts/sidebar/components/participants/participants.vue
+++ b/app/assets/javascripts/sidebar/components/participants/participants.vue
@@ -127,7 +127,7 @@ export default {
<div v-if="hasMoreParticipants" class="participants-more hide-collapsed">
<button
type="button"
- class="btn-transparent btn-blank js-toggle-participants-button"
+ class="btn-transparent btn-link js-toggle-participants-button"
@click="toggleMoreParticipants"
>
{{ toggleLabel }}
diff --git a/app/assets/stylesheets/framework/buttons.scss b/app/assets/stylesheets/framework/buttons.scss
index 38cef3de777..6257ee3ae8e 100644
--- a/app/assets/stylesheets/framework/buttons.scss
+++ b/app/assets/stylesheets/framework/buttons.scss
@@ -447,6 +447,7 @@
font-weight: normal;
border-radius: 0;
border-color: transparent;
+ border-width: 0;
&:hover,
&:active,
diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss
index d61fbae81f2..c48f4b0622e 100644
--- a/app/assets/stylesheets/pages/issuable.scss
+++ b/app/assets/stylesheets/pages/issuable.scss
@@ -187,7 +187,6 @@
.btn-link {
color: inherit;
- outline: none;
}
.issuable-header-text {
@@ -261,15 +260,10 @@
color: rgba($gray-normal, 0.2);
}
- .lock-edit, // uses same style, different js behaviour
+ .confidential-edit,
+ .lock-edit,
.edit-link {
- @extend .btn-blank;
- color: $gl-text-color;
-
- &:hover {
- text-decoration: underline;
- color: $blue-800;
- }
+ @extend .btn-link;
}
}
@@ -689,7 +683,6 @@
}
.btn-link {
- outline: none;
padding: 0;
}
diff --git a/app/controllers/boards/issues_controller.rb b/app/controllers/boards/issues_controller.rb
index ccb9dd7bbf6..1bfff210ecf 100644
--- a/app/controllers/boards/issues_controller.rb
+++ b/app/controllers/boards/issues_controller.rb
@@ -21,7 +21,7 @@ module Boards
before_action :validate_id_list, only: [:bulk_move]
before_action :can_move_issues?, only: [:bulk_move]
before_action do
- push_frontend_feature_flag(:board_search_optimization, board.group)
+ push_frontend_feature_flag(:board_search_optimization, board.group, default_enabled: true)
end
def index
diff --git a/app/controllers/concerns/snippets_actions.rb b/app/controllers/concerns/snippets_actions.rb
index b12aee346ed..096c6efc0fc 100644
--- a/app/controllers/concerns/snippets_actions.rb
+++ b/app/controllers/concerns/snippets_actions.rb
@@ -4,6 +4,10 @@ module SnippetsActions
extend ActiveSupport::Concern
include SendsBlob
+ included do
+ before_action :redirect_if_binary, only: [:edit, :update]
+ end
+
def edit
# We need to load some info from the existing blob
snippet.content = blob.data
@@ -67,4 +71,8 @@ module SnippetsActions
flash.now[:alert] = repository_errors.first if repository_errors.present?
recaptcha_check_with_fallback(repository_errors.empty?) { render :edit }
end
+
+ def redirect_if_binary
+ redirect_to gitlab_snippet_path(snippet) if blob&.binary?
+ end
end
diff --git a/app/controllers/groups/registry/repositories_controller.rb b/app/controllers/groups/registry/repositories_controller.rb
index ac4ca197d72..0240c87e699 100644
--- a/app/controllers/groups/registry/repositories_controller.rb
+++ b/app/controllers/groups/registry/repositories_controller.rb
@@ -4,7 +4,6 @@ module Groups
class RepositoriesController < Groups::ApplicationController
before_action :verify_container_registry_enabled!
before_action :authorize_read_container_image!
- before_action :feature_flag_group_container_registry_browser!
def index
respond_to do |format|
@@ -17,12 +16,8 @@ module Groups
serializer = ContainerRepositoriesSerializer
.new(current_user: current_user)
- if Feature.enabled?(:vue_container_registry_explorer, group)
- render json: serializer.with_pagination(request, response)
- .represent_read_only(@images)
- else
- render json: serializer.represent_read_only(@images)
- end
+ render json: serializer.with_pagination(request, response)
+ .represent_read_only(@images)
end
end
end
@@ -34,10 +29,6 @@ module Groups
private
- def feature_flag_group_container_registry_browser!
- render_404 unless Feature.enabled?(:group_container_registry_browser, group)
- end
-
def verify_container_registry_enabled!
render_404 unless Gitlab.config.registry.enabled
end
diff --git a/app/controllers/projects/registry/repositories_controller.rb b/app/controllers/projects/registry/repositories_controller.rb
index d6d993f427d..8852ae04d5e 100644
--- a/app/controllers/projects/registry/repositories_controller.rb
+++ b/app/controllers/projects/registry/repositories_controller.rb
@@ -17,11 +17,7 @@ module Projects
serializer = ContainerRepositoriesSerializer
.new(project: project, current_user: current_user)
- if Feature.enabled?(:vue_container_registry_explorer, project.group)
- render json: serializer.with_pagination(request, response).represent(@images)
- else
- render json: serializer.represent(@images)
- end
+ render json: serializer.with_pagination(request, response).represent(@images)
end
end
end
diff --git a/app/helpers/groups_helper.rb b/app/helpers/groups_helper.rb
index 661197e84ae..5abe6a635e0 100644
--- a/app/helpers/groups_helper.rb
+++ b/app/helpers/groups_helper.rb
@@ -22,8 +22,7 @@ module GroupsHelper
def group_container_registry_nav?
Gitlab.config.registry.enabled &&
- can?(current_user, :read_container_image, @group) &&
- Feature.enabled?(:group_container_registry_browser, @group)
+ can?(current_user, :read_container_image, @group)
end
def group_sidebar_links
diff --git a/app/models/concerns/has_repository.rb b/app/models/concerns/has_repository.rb
index d50e088944e..01f1aa1758f 100644
--- a/app/models/concerns/has_repository.rb
+++ b/app/models/concerns/has_repository.rb
@@ -111,4 +111,8 @@ module HasRepository
def web_url(only_path: nil)
raise NotImplementedError
end
+
+ def repository_size_checker
+ raise NotImplementedError
+ end
end
diff --git a/app/services/award_emojis/add_service.rb b/app/services/award_emojis/add_service.rb
index eac15dabbf0..db465dcaf7e 100644
--- a/app/services/award_emojis/add_service.rb
+++ b/app/services/award_emojis/add_service.rb
@@ -16,7 +16,7 @@ module AwardEmojis
award = awardable.award_emoji.create(name: name, user: current_user)
if award.persisted?
- TodoService.new.new_award_emoji(todoable, current_user) if todoable
+ after_create(award)
success(award: award)
else
error(award.errors.full_messages, award: award)
@@ -25,6 +25,10 @@ module AwardEmojis
private
+ def after_create(award)
+ TodoService.new.new_award_emoji(todoable, current_user) if todoable
+ end
+
def todoable
strong_memoize(:todoable) do
case awardable
@@ -40,3 +44,5 @@ module AwardEmojis
end
end
end
+
+AwardEmojis::AddService.prepend_if_ee('EE::AwardEmojis::AddService')
diff --git a/app/services/award_emojis/destroy_service.rb b/app/services/award_emojis/destroy_service.rb
index 3789a8403bc..a61a7911a9d 100644
--- a/app/services/award_emojis/destroy_service.rb
+++ b/app/services/award_emojis/destroy_service.rb
@@ -14,8 +14,16 @@ module AwardEmojis
end
award = awards.destroy_all.first # rubocop: disable DestroyAll
+ after_destroy(award)
success(award: award)
end
+
+ private
+
+ def after_destroy(award)
+ end
end
end
+
+AwardEmojis::DestroyService.prepend_if_ee('EE::AwardEmojis::DestroyService')
diff --git a/app/services/boards/issues/list_service.rb b/app/services/boards/issues/list_service.rb
index 337710b60e0..9637eb1b918 100644
--- a/app/services/boards/issues/list_service.rb
+++ b/app/services/boards/issues/list_service.rb
@@ -133,7 +133,7 @@ module Boards
def can_attempt_search_optimization?
params[:search].present? &&
- Feature.enabled?(:board_search_optimization, board_group, default_enabled: false)
+ Feature.enabled?(:board_search_optimization, board_group, default_enabled: true)
end
end
end
diff --git a/app/services/issues/close_service.rb b/app/services/issues/close_service.rb
index 2cf4bbcd590..8594808cd44 100644
--- a/app/services/issues/close_service.rb
+++ b/app/services/issues/close_service.rb
@@ -59,8 +59,6 @@ module Issues
end
def store_first_mentioned_in_commit_at(issue, merge_request)
- return unless Feature.enabled?(:store_first_mentioned_in_commit_on_issue_close, issue.project, default_enabled: true)
-
metrics = issue.metrics
return if metrics.nil? || metrics.first_mentioned_in_commit_at
diff --git a/app/views/groups/registry/repositories/index.html.haml b/app/views/groups/registry/repositories/index.html.haml
index 996582e0ae8..41cb073686a 100644
--- a/app/views/groups/registry/repositories/index.html.haml
+++ b/app/views/groups/registry/repositories/index.html.haml
@@ -4,23 +4,14 @@
%section
.row.registry-placeholder.prepend-bottom-10
.col-12
- - if Feature.enabled?(:vue_container_registry_explorer, @group)
- #js-container-registry{ data: { endpoint: group_container_registries_path(@group),
- "help_page_path" => help_page_path('user/packages/container_registry/index'),
- "two_factor_auth_help_link" => help_page_path('user/profile/account/two_factor_authentication'),
- "personal_access_tokens_help_link" => help_page_path('user/profile/personal_access_tokens'),
- "no_containers_image" => image_path('illustrations/docker-empty-state.svg'),
- "containers_error_image" => image_path('illustrations/docker-error-state.svg'),
- "registry_host_url_with_port" => escape_once(registry_config.host_port),
- "garbage_collection_help_page_path" => help_page_path('administration/packages/container_registry', anchor: 'container-registry-garbage-collection'),
- "is_admin": current_user&.admin,
- is_group_page: true,
- character_error: @character_error.to_s } }
- - else
- #js-vue-registry-images{ data: { endpoint: group_container_registries_path(@group, format: :json),
- "help_page_path" => help_page_path('user/packages/container_registry/index'),
- "no_containers_image" => image_path('illustrations/docker-empty-state.svg'),
- "containers_error_image" => image_path('illustrations/docker-error-state.svg'),
- "repository_url" => "",
- is_group_page: true,
- character_error: @character_error.to_s } }
+ #js-container-registry{ data: { endpoint: group_container_registries_path(@group),
+ "help_page_path" => help_page_path('user/packages/container_registry/index'),
+ "two_factor_auth_help_link" => help_page_path('user/profile/account/two_factor_authentication'),
+ "personal_access_tokens_help_link" => help_page_path('user/profile/personal_access_tokens'),
+ "no_containers_image" => image_path('illustrations/docker-empty-state.svg'),
+ "containers_error_image" => image_path('illustrations/docker-error-state.svg'),
+ "registry_host_url_with_port" => escape_once(registry_config.host_port),
+ "garbage_collection_help_page_path" => help_page_path('administration/packages/container_registry', anchor: 'container-registry-garbage-collection'),
+ "is_admin": current_user&.admin,
+ is_group_page: true,
+ character_error: @character_error.to_s } }
diff --git a/app/views/projects/blob/_pipeline_tour_success.html.haml b/app/views/projects/blob/_pipeline_tour_success.html.haml
index 7ecbc1974ec..cf1427df044 100644
--- a/app/views/projects/blob/_pipeline_tour_success.html.haml
+++ b/app/views/projects/blob/_pipeline_tour_success.html.haml
@@ -1 +1,3 @@
-.js-success-pipeline-modal{ 'data-commit-cookie': suggest_pipeline_commit_cookie_name, 'data-pipelines-path': project_pipelines_path(@project) }
+.js-success-pipeline-modal{ data: { 'commit-cookie': suggest_pipeline_commit_cookie_name,
+ 'go-to-pipelines-path': project_pipelines_path(@project),
+ 'human-access': @project.team.human_max_access(current_user&.id) } }
diff --git a/app/views/projects/registry/repositories/index.html.haml b/app/views/projects/registry/repositories/index.html.haml
index 80dd5eaecb2..650e63eb406 100644
--- a/app/views/projects/registry/repositories/index.html.haml
+++ b/app/views/projects/registry/repositories/index.html.haml
@@ -4,28 +4,17 @@
%section
.row.registry-placeholder.prepend-bottom-10
.col-12
- - if Feature.enabled?(:vue_container_registry_explorer, @project.group)
- #js-container-registry{ data: { endpoint: project_container_registry_index_path(@project),
- settings_path: project_settings_ci_cd_path(@project),
- expiration_policy: @project.container_expiration_policy.to_json,
- "help_page_path" => help_page_path('user/packages/container_registry/index'),
- "two_factor_auth_help_link" => help_page_path('user/profile/account/two_factor_authentication'),
- "personal_access_tokens_help_link" => help_page_path('user/profile/personal_access_tokens'),
- "no_containers_image" => image_path('illustrations/docker-empty-state.svg'),
- "containers_error_image" => image_path('illustrations/docker-error-state.svg'),
- "repository_url" => escape_once(@project.container_registry_url),
- "registry_host_url_with_port" => escape_once(registry_config.host_port),
- "expiration_policy_help_page_path" => help_page_path('user/packages/container_registry/index', anchor: 'expiration-policy'),
- "garbage_collection_help_page_path" => help_page_path('administration/packages/container_registry', anchor: 'container-registry-garbage-collection'),
- "is_admin": current_user&.admin,
- character_error: @character_error.to_s } }
- - else
- #js-vue-registry-images{ data: { endpoint: project_container_registry_index_path(@project, format: :json),
- "help_page_path" => help_page_path('user/packages/container_registry/index'),
- "two_factor_auth_help_link" => help_page_path('user/profile/account/two_factor_authentication'),
- "personal_access_tokens_help_link" => help_page_path('user/profile/personal_access_tokens'),
- "no_containers_image" => image_path('illustrations/docker-empty-state.svg'),
- "containers_error_image" => image_path('illustrations/docker-error-state.svg'),
- "repository_url" => escape_once(@project.container_registry_url),
- "registry_host_url_with_port" => escape_once(registry_config.host_port),
- character_error: @character_error.to_s } }
+ #js-container-registry{ data: { endpoint: project_container_registry_index_path(@project),
+ settings_path: project_settings_ci_cd_path(@project),
+ expiration_policy: @project.container_expiration_policy.to_json,
+ "help_page_path" => help_page_path('user/packages/container_registry/index'),
+ "two_factor_auth_help_link" => help_page_path('user/profile/account/two_factor_authentication'),
+ "personal_access_tokens_help_link" => help_page_path('user/profile/personal_access_tokens'),
+ "no_containers_image" => image_path('illustrations/docker-empty-state.svg'),
+ "containers_error_image" => image_path('illustrations/docker-error-state.svg'),
+ "repository_url" => escape_once(@project.container_registry_url),
+ "registry_host_url_with_port" => escape_once(registry_config.host_port),
+ "expiration_policy_help_page_path" => help_page_path('user/packages/container_registry/index', anchor: 'expiration-policy'),
+ "garbage_collection_help_page_path" => help_page_path('administration/packages/container_registry', anchor: 'container-registry-garbage-collection'),
+ "is_admin": current_user&.admin,
+ character_error: @character_error.to_s } }