summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/registry/components/app.vue109
-rw-r--r--app/assets/javascripts/registry/components/svg_message.vue24
-rw-r--r--app/assets/javascripts/registry/index.js10
-rw-r--r--app/assets/stylesheets/pages/container_registry.scss6
-rw-r--r--app/controllers/projects/registry/repositories_controller.rb2
-rw-r--r--app/views/projects/registry/repositories/index.html.haml54
6 files changed, 145 insertions, 60 deletions
diff --git a/app/assets/javascripts/registry/components/app.vue b/app/assets/javascripts/registry/components/app.vue
index ee973017387..7752723baac 100644
--- a/app/assets/javascripts/registry/components/app.vue
+++ b/app/assets/javascripts/registry/components/app.vue
@@ -3,22 +3,81 @@ import { mapGetters, mapActions } from 'vuex';
import { GlLoadingIcon } from '@gitlab/ui';
import store from '../stores';
import CollapsibleContainer from './collapsible_container.vue';
+import SvgMessage from './svg_message.vue';
+import { s__, sprintf } from '../../locale';
export default {
name: 'RegistryListApp',
components: {
CollapsibleContainer,
GlLoadingIcon,
+ SvgMessage,
},
props: {
endpoint: {
type: String,
required: true,
},
+ characterError: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ helpPagePath: {
+ type: String,
+ required: true,
+ },
+ noContainersImage: {
+ type: String,
+ required: true,
+ },
+ containersErrorImage: {
+ type: String,
+ required: true,
+ },
+ repositoryUrl: {
+ type: String,
+ required: true,
+ },
},
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. For more information, please review the
+ %{docLinkStart}Container Registry documentation%{docLinkEnd}.`),
+ {
+ docLinkStart: `<a href="${this.helpPagePath}#docker-connection-error">`,
+ 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. Learn more about the
+ %{docLinkStart}Container Registry%{docLinkEnd}.`),
+ {
+ docLinkStart: `<a href="${this.helpPagePath}">`,
+ docLinkEnd: '</a>',
+ },
+ false,
+ );
+ },
+ noContainerImagesText() {
+ return sprintf(
+ s__(`ContainerRegistry|With the Container Registry, every project can have its own space to
+ store its Docker images. Learn more about the %{docLinkStart}Container Registry%{docLinkEnd}.`),
+ {
+ docLinkStart: `<a href="${this.helpPagePath}">`,
+ docLinkEnd: '</a>',
+ },
+ false,
+ );
+ },
},
created() {
this.setMainEndpoint(this.endpoint);
@@ -33,20 +92,44 @@ export default {
</script>
<template>
<div>
- <gl-loading-icon v-if="isLoading" size="md" />
+ <svg-message v-if="characterError" id="invalid-characters" :svg-path="containersErrorImage">
+ <h4>
+ {{ s__('ContainerRegistry|Docker connection error') }}
+ </h4>
+ <p v-html="dockerConnectionErrorText"></p>
+ </svg-message>
+
+ <gl-loading-icon v-else-if="isLoading" size="md" class="prepend-top-16" />
+
+ <div v-else-if="!isLoading && !characterError && 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>
+
+ <svg-message
+ v-else-if="!isLoading && !characterError && !repos.length"
+ id="no-container-images"
+ :svg-path="noContainersImage"
+ >
+ <h4>
+ {{ s__('ContainerRegistry|There are no container images stored for this project') }}
+ </h4>
+ <p v-html="noContainerImagesText"></p>
- <collapsible-container
- v-for="item in repos"
- v-else-if="!isLoading && repos.length"
- :key="item.id"
- :repo="item"
- />
+ <h5>{{ s__('ContainerRegistry|Quick Start') }}</h5>
+ <p>
+ {{
+ s__(
+ 'ContainerRegistry|You can add an image to this registry with the following commands:',
+ )
+ }}
+ </p>
- <p v-else-if="!isLoading && !repos.length">
- {{
- __(`No container images stored for this project.
- Add one by following the instructions above.`)
- }}
- </p>
+ <pre>
+ docker build -t {{ repositoryUrl }} .
+ docker push {{ repositoryUrl }}
+ </pre>
+ </svg-message>
</div>
</template>
diff --git a/app/assets/javascripts/registry/components/svg_message.vue b/app/assets/javascripts/registry/components/svg_message.vue
new file mode 100644
index 00000000000..d0d44bf2d14
--- /dev/null
+++ b/app/assets/javascripts/registry/components/svg_message.vue
@@ -0,0 +1,24 @@
+<script>
+export default {
+ name: 'RegistrySvgMessage',
+ props: {
+ id: {
+ type: String,
+ required: true,
+ },
+ svgPath: {
+ type: String,
+ required: true,
+ },
+ },
+};
+</script>
+
+<template>
+ <div :id="id" class="empty-state container-message mw-70p">
+ <div class="svg-content">
+ <img :src="svgPath" class="flex-align-self-center" />
+ </div>
+ <slot></slot>
+ </div>
+</template>
diff --git a/app/assets/javascripts/registry/index.js b/app/assets/javascripts/registry/index.js
index 025afefe7f0..d8daec29fda 100644
--- a/app/assets/javascripts/registry/index.js
+++ b/app/assets/javascripts/registry/index.js
@@ -14,12 +14,22 @@ export default () =>
const { dataset } = document.querySelector(this.$options.el);
return {
endpoint: dataset.endpoint,
+ characterError: Boolean(dataset.characterError),
+ helpPagePath: dataset.helpPagePath,
+ noContainersImage: dataset.noContainersImage,
+ containersErrorImage: dataset.containersErrorImage,
+ repositoryUrl: dataset.repositoryUrl,
};
},
render(createElement) {
return createElement('registry-app', {
props: {
endpoint: this.endpoint,
+ characterError: this.characterError,
+ helpPagePath: this.helpPagePath,
+ noContainersImage: this.noContainersImage,
+ containersErrorImage: this.containersErrorImage,
+ repositoryUrl: this.repositoryUrl,
},
});
},
diff --git a/app/assets/stylesheets/pages/container_registry.scss b/app/assets/stylesheets/pages/container_registry.scss
index dfff3e15556..cca5214a508 100644
--- a/app/assets/stylesheets/pages/container_registry.scss
+++ b/app/assets/stylesheets/pages/container_registry.scss
@@ -2,6 +2,12 @@
* Container Registry
*/
+.container-message {
+ pre {
+ white-space: pre-line;
+ }
+}
+
.container-image {
border-bottom: 1px solid $white-normal;
}
diff --git a/app/controllers/projects/registry/repositories_controller.rb b/app/controllers/projects/registry/repositories_controller.rb
index 6d60117c37d..e205e2fd4f8 100644
--- a/app/controllers/projects/registry/repositories_controller.rb
+++ b/app/controllers/projects/registry/repositories_controller.rb
@@ -46,6 +46,8 @@ module Projects
repository.save! if repository.has_tags?
end
end
+ rescue ContainerRegistry::Path::InvalidRegistryPathError
+ @character_error = true
end
end
end
diff --git a/app/views/projects/registry/repositories/index.html.haml b/app/views/projects/registry/repositories/index.html.haml
index db1f15f96b8..e34973f1f43 100644
--- a/app/views/projects/registry/repositories/index.html.haml
+++ b/app/views/projects/registry/repositories/index.html.haml
@@ -1,49 +1,9 @@
-- page_title "Container Registry"
-
%section
- .settings-header
- %h4
- = page_title
- %p
- = s_('ContainerRegistry|With the Docker Container Registry integrated into GitLab, every project can have its own space to store its Docker images.')
- %p.append-bottom-0
- = succeed '.' do
- = s_('ContainerRegistry|Learn more about')
- = link_to _('Container Registry'), help_page_path('user/project/container_registry'), target: '_blank'
.row.registry-placeholder.prepend-bottom-10
- .col-lg-12
- #js-vue-registry-images{ data: { endpoint: project_container_registry_index_path(@project, format: :json) } }
-
- .row.prepend-top-10
- .col-lg-12
- .card
- .card-header
- = s_('ContainerRegistry|How to use the Container Registry')
- .card-body
- %p
- - link_token = link_to(_('personal access token'), help_page_path('user/profile/account/two_factor_authentication', anchor: 'personal-access-tokens'), target: '_blank')
- - link_2fa = link_to(_('2FA enabled'), help_page_path('user/profile/account/two_factor_authentication'), target: '_blank')
- = s_('ContainerRegistry|First log in to GitLab&rsquo;s Container Registry using your GitLab username and password. If you have %{link_2fa} you need to use a %{link_token}:').html_safe % { link_2fa: link_2fa, link_token: link_token }
- %pre
- docker login #{Gitlab.config.registry.host_port}
- %br
- %p
- - deploy_token = link_to(_('deploy token'), help_page_path('user/project/deploy_tokens/index', anchor: 'read-container-registry-images'), target: '_blank')
- = s_('ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images.').html_safe % { deploy_token: deploy_token }
- %br
- %p
- = s_('ContainerRegistry|Once you log in, you&rsquo;re free to create and upload a container image using the common %{build} and %{push} commands').html_safe % { build: "<code>build</code>".html_safe, push: "<code>push</code>".html_safe }
- %pre
- :plain
- docker build -t #{escape_once(@project.container_registry_url)} .
- docker push #{escape_once(@project.container_registry_url)}
- %hr
- %h5.prepend-top-default
- = s_('ContainerRegistry|Use different image names')
- %p.light
- = s_('ContainerRegistry|GitLab supports up to 3 levels of image names. The following examples of images are valid for your project:')
- %pre
- :plain
- #{escape_once(@project.container_registry_url)}:tag
- #{escape_once(@project.container_registry_url)}/optional-image-name:tag
- #{escape_once(@project.container_registry_url)}/optional-name/optional-image-name:tag
+ .col-12
+ #js-vue-registry-images{ data: { endpoint: project_container_registry_index_path(@project, format: :json),
+ "help_page_path" => help_page_path('user/project/container_registry'),
+ "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),
+ character_error: @character_error.to_s } }