Commit 9d509ee4 authored by Nate Geslin's avatar Nate Geslin Committed by Kushal Pandya

Adds login input with copy box and supporting copy to empty container registry view

Closes issue:
https://gitlab.com/gitlab-org/gitlab/issues/32866
parent f06235cc
...@@ -15,15 +15,19 @@ export default { ...@@ -15,15 +15,19 @@ export default {
GlLoadingIcon, GlLoadingIcon,
}, },
props: { props: {
endpoint: {
type: String,
required: true,
},
characterError: { characterError: {
type: Boolean, type: Boolean,
required: false, required: false,
default: false, default: false,
}, },
containersErrorImage: {
type: String,
required: true,
},
endpoint: {
type: String,
required: true,
},
helpPagePath: { helpPagePath: {
type: String, type: String,
required: true, required: true,
...@@ -32,7 +36,11 @@ export default { ...@@ -32,7 +36,11 @@ export default {
type: String, type: String,
required: true, required: true,
}, },
containersErrorImage: { personalAccessTokensHelpLink: {
type: String,
required: true,
},
registryHostUrlWithPort: {
type: String, type: String,
required: true, required: true,
}, },
...@@ -40,6 +48,10 @@ export default { ...@@ -40,6 +48,10 @@ export default {
type: String, type: String,
required: true, required: true,
}, },
twoFactorAuthHelpLink: {
type: String,
required: true,
},
}, },
store, store,
computed: { computed: {
...@@ -79,6 +91,26 @@ export default { ...@@ -79,6 +91,26 @@ export default {
false, 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,
);
},
dockerLoginCommand() {
// eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings
return `docker login ${this.registryHostUrlWithPort}`;
},
dockerBuildCommand() { dockerBuildCommand() {
// eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings // eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings
return `docker build -t ${this.repositoryUrl} .`; return `docker build -t ${this.repositoryUrl} .`;
...@@ -130,6 +162,17 @@ export default { ...@@ -130,6 +162,17 @@ export default {
<template #description> <template #description>
<p class="js-no-container-images-text" v-html="noContainerImagesText"></p> <p class="js-no-container-images-text" v-html="noContainerImagesText"></p>
<h5>{{ s__('ContainerRegistry|Quick Start') }}</h5> <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>
{{ {{
s__( s__(
......
...@@ -13,23 +13,29 @@ export default () => ...@@ -13,23 +13,29 @@ export default () =>
data() { data() {
const { dataset } = document.querySelector(this.$options.el); const { dataset } = document.querySelector(this.$options.el);
return { return {
endpoint: dataset.endpoint,
characterError: Boolean(dataset.characterError), characterError: Boolean(dataset.characterError),
containersErrorImage: dataset.containersErrorImage,
endpoint: dataset.endpoint,
helpPagePath: dataset.helpPagePath, helpPagePath: dataset.helpPagePath,
noContainersImage: dataset.noContainersImage, noContainersImage: dataset.noContainersImage,
containersErrorImage: dataset.containersErrorImage, personalAccessTokensHelpLink: dataset.personalAccessTokensHelpLink,
registryHostUrlWithPort: dataset.registryHostUrlWithPort,
repositoryUrl: dataset.repositoryUrl, repositoryUrl: dataset.repositoryUrl,
twoFactorAuthHelpLink: dataset.twoFactorAuthHelpLink,
}; };
}, },
render(createElement) { render(createElement) {
return createElement('registry-app', { return createElement('registry-app', {
props: { props: {
endpoint: this.endpoint,
characterError: this.characterError, characterError: this.characterError,
containersErrorImage: this.containersErrorImage,
endpoint: this.endpoint,
helpPagePath: this.helpPagePath, helpPagePath: this.helpPagePath,
noContainersImage: this.noContainersImage, noContainersImage: this.noContainersImage,
containersErrorImage: this.containersErrorImage, personalAccessTokensHelpLink: this.personalAccessTokensHelpLink,
registryHostUrlWithPort: this.registryHostUrlWithPort,
repositoryUrl: this.repositoryUrl, repositoryUrl: this.repositoryUrl,
twoFactorAuthHelpLink: this.twoFactorAuthHelpLink,
}, },
}); });
}, },
......
...@@ -108,6 +108,11 @@ module ApplicationHelper ...@@ -108,6 +108,11 @@ module ApplicationHelper
Gitlab.config.extra Gitlab.config.extra
end end
# shortcut for gitlab registry config
def registry_config
Gitlab.config.registry
end
# Render a `time` element with Javascript-based relative date and tooltip # Render a `time` element with Javascript-based relative date and tooltip
# #
# time - Time object # time - Time object
......
...@@ -5,7 +5,10 @@ ...@@ -5,7 +5,10 @@
.col-12 .col-12
#js-vue-registry-images{ data: { endpoint: project_container_registry_index_path(@project, format: :json), #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'), "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'), "no_containers_image" => image_path('illustrations/docker-empty-state.svg'),
"containers_error_image" => image_path('illustrations/docker-error-state.svg'), "containers_error_image" => image_path('illustrations/docker-error-state.svg'),
"repository_url" => escape_once(@project.container_registry_url), "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 } } character_error: @character_error.to_s } }
---
title: Adds login input with copy box and supporting copy to empty container registry view
merge_request: 18244
author: nate geslin
type: added
...@@ -4349,12 +4349,18 @@ msgstr "" ...@@ -4349,12 +4349,18 @@ msgstr ""
msgid "ContainerRegistry|Copy build command" msgid "ContainerRegistry|Copy build command"
msgstr "" msgstr ""
msgid "ContainerRegistry|Copy login command"
msgstr ""
msgid "ContainerRegistry|Copy push command" msgid "ContainerRegistry|Copy push command"
msgstr "" msgstr ""
msgid "ContainerRegistry|Docker connection error" msgid "ContainerRegistry|Docker connection error"
msgstr "" msgstr ""
msgid "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."
msgstr ""
msgid "ContainerRegistry|Last Updated" msgid "ContainerRegistry|Last Updated"
msgstr "" msgstr ""
......
import registry from '~/registry/components/app.vue';
import { mount } from '@vue/test-utils'; import { mount } from '@vue/test-utils';
import registry from '~/registry/components/app.vue';
import { TEST_HOST } from '../../helpers/test_constants'; import { TEST_HOST } from '../../helpers/test_constants';
import { reposServerResponse, parsedReposServerResponse } from '../mock_data'; import { reposServerResponse, parsedReposServerResponse } from '../mock_data';
...@@ -8,6 +8,7 @@ describe('Registry List', () => { ...@@ -8,6 +8,7 @@ describe('Registry List', () => {
const findCollapsibleContainer = w => w.findAll({ name: 'CollapsibeContainerRegisty' }); const findCollapsibleContainer = w => w.findAll({ name: 'CollapsibeContainerRegisty' });
const findNoContainerImagesText = w => w.find('.js-no-container-images-text'); const findNoContainerImagesText = w => w.find('.js-no-container-images-text');
const findNotLoggedInToRegistryText = w => w.find('.js-not-logged-in-to-registry-text');
const findSpinner = w => w.find('.gl-spinner'); const findSpinner = w => w.find('.gl-spinner');
const findCharacterErrorText = w => w.find('.js-character-error-text'); const findCharacterErrorText = w => w.find('.js-character-error-text');
...@@ -17,6 +18,9 @@ describe('Registry List', () => { ...@@ -17,6 +18,9 @@ describe('Registry List', () => {
noContainersImage: 'foo', noContainersImage: 'foo',
containersErrorImage: 'foo', containersErrorImage: 'foo',
repositoryUrl: 'foo', repositoryUrl: 'foo',
registryHostUrlWithPort: 'foo',
personalAccessTokensHelpLink: 'foo',
twoFactorAuthHelpLink: 'foo',
}; };
const setMainEndpoint = jest.fn(); const setMainEndpoint = jest.fn();
...@@ -67,6 +71,13 @@ describe('Registry List', () => { ...@@ -67,6 +71,13 @@ describe('Registry List', () => {
'With the Container Registry, every project can have its own space to store its Docker images. More Information', 'With the Container Registry, every project can have its own space to store its Docker images. More Information',
); );
}); });
it('should render login help text', () => {
const notLoggedInToRegistryText = findNotLoggedInToRegistryText(localWrapper);
expect(notLoggedInToRegistryText.text()).toEqual(
'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 Two-Factor Authentication enabled, use a Personal Access Token instead of a password.',
);
});
}); });
describe('while loading data', () => { describe('while loading data', () => {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment