diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-03-19 21:09:17 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-03-19 21:09:17 +0300 |
commit | 0eb4fd2f32e6804bc85868ba167170238e346279 (patch) | |
tree | c020e787ea29c77e1e9f53c21940f88a87a6e905 /app | |
parent | 78d8830cec030ff12afed3c8ae1dddec454d0a24 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
10 files changed, 205 insertions, 92 deletions
diff --git a/app/assets/javascripts/registry/explorer/components/project_empty_state.vue b/app/assets/javascripts/registry/explorer/components/project_empty_state.vue index 556df10ea5b..0ce38c4a9ec 100644 --- a/app/assets/javascripts/registry/explorer/components/project_empty_state.vue +++ b/app/assets/javascripts/registry/explorer/components/project_empty_state.vue @@ -1,7 +1,9 @@ <script> import { GlEmptyState, GlSprintf, GlLink } from '@gitlab/ui'; +import { mapState, mapGetters } from 'vuex'; +import { s__ } from '~/locale'; import ClipboardButton from '~/vue_shared/components/clipboard_button.vue'; -import { mapState } from 'vuex'; +import { COPY_LOGIN_TITLE, COPY_BUILD_TITLE, COPY_PUSH_TITLE, QUICK_START } from '../constants'; export default { name: 'ProjectEmptyState', @@ -11,20 +13,24 @@ export default { GlSprintf, GlLink, }, + i18n: { + quickStart: QUICK_START, + copyLoginTitle: COPY_LOGIN_TITLE, + copyBuildTitle: COPY_BUILD_TITLE, + copyPushTitle: COPY_PUSH_TITLE, + introText: s__( + `ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}`, + ), + notLoggedInMessage: 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.`, + ), + addImageText: s__( + 'ContainerRegistry|You can add an image to this registry with the following commands:', + ), + }, computed: { ...mapState(['config']), - dockerBuildCommand() { - // eslint-disable-next-line @gitlab/require-i18n-strings - return `docker build -t ${this.config.repositoryUrl} .`; - }, - dockerPushCommand() { - // eslint-disable-next-line @gitlab/require-i18n-strings - return `docker push ${this.config.repositoryUrl}`; - }, - dockerLoginCommand() { - // eslint-disable-next-line @gitlab/require-i18n-strings - return `docker login ${this.config.registryHostUrlWithPort}`; - }, + ...mapGetters(['dockerBuildCommand', 'dockerPushCommand', 'dockerLoginCommand']), }, }; </script> @@ -36,28 +42,15 @@ export default { > <template #description> <p class="js-no-container-images-text"> - <gl-sprintf - :message=" - s__(`ContainerRegistry|With the Container Registry, every project can have its own space to - store its Docker images. %{docLinkStart}More Information%{docLinkEnd}`) - " - > + <gl-sprintf :message="$options.i18n.introText"> <template #docLink="{content}"> <gl-link :href="config.helpPagePath" target="_blank">{{ content }}</gl-link> </template> </gl-sprintf> </p> - <h5>{{ s__('ContainerRegistry|Quick Start') }}</h5> + <h5>{{ $options.i18n.quickStart }}</h5> <p class="js-not-logged-in-to-registry-text"> - <gl-sprintf - :message=" - 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.`) - " - > + <gl-sprintf :message="$options.i18n.notLoggedInMessage"> <template #twofaDocLink="{content}"> <gl-link :href="config.twoFactorAuthHelpLink" target="_blank">{{ content }}</gl-link> </template> @@ -73,18 +66,14 @@ export default { <span class="input-group-append"> <clipboard-button :text="dockerLoginCommand" - :title="s__('ContainerRegistry|Copy login command')" + :title="$options.i18n.copyLoginTitle" class="input-group-text" /> </span> </div> <p></p> <p> - {{ - s__( - 'ContainerRegistry|You can add an image to this registry with the following commands:', - ) - }} + {{ $options.i18n.addImageText }} </p> <div class="input-group append-bottom-10"> @@ -92,7 +81,7 @@ export default { <span class="input-group-append"> <clipboard-button :text="dockerBuildCommand" - :title="s__('ContainerRegistry|Copy build command')" + :title="$options.i18n.copyBuildTitle" class="input-group-text" /> </span> @@ -103,7 +92,7 @@ export default { <span class="input-group-append"> <clipboard-button :text="dockerPushCommand" - :title="s__('ContainerRegistry|Copy push command')" + :title="$options.i18n.copyPushTitle" class="input-group-text" /> </span> diff --git a/app/assets/javascripts/registry/explorer/components/quickstart_dropdown.vue b/app/assets/javascripts/registry/explorer/components/quickstart_dropdown.vue new file mode 100644 index 00000000000..99361b6e08d --- /dev/null +++ b/app/assets/javascripts/registry/explorer/components/quickstart_dropdown.vue @@ -0,0 +1,92 @@ +<script> +import { GlDropdown, GlFormGroup, GlFormInputGroup } from '@gitlab/ui'; +import { mapGetters } from 'vuex'; +import ClipboardButton from '~/vue_shared/components/clipboard_button.vue'; +import { + QUICK_START, + LOGIN_COMMAND_LABEL, + COPY_LOGIN_TITLE, + BUILD_COMMAND_LABEL, + COPY_BUILD_TITLE, + PUSH_COMMAND_LABEL, + COPY_PUSH_TITLE, +} from '../constants'; + +export default { + components: { + GlDropdown, + GlFormGroup, + GlFormInputGroup, + ClipboardButton, + }, + i18n: { + dropdownTitle: QUICK_START, + loginCommandLabel: LOGIN_COMMAND_LABEL, + copyLoginTitle: COPY_LOGIN_TITLE, + buildCommandLabel: BUILD_COMMAND_LABEL, + copyBuildTitle: COPY_BUILD_TITLE, + pushCommandLabel: PUSH_COMMAND_LABEL, + copyPushTitle: COPY_PUSH_TITLE, + }, + computed: { + ...mapGetters(['dockerBuildCommand', 'dockerPushCommand', 'dockerLoginCommand']), + }, +}; +</script> +<template> + <gl-dropdown :text="$options.i18n.dropdownTitle" variant="primary" size="sm" right> + <!-- This li is used as a container since gl-dropdown produces a root ul, this mimics the functionality exposed by b-dropdown-form --> + <li role="presentation" class="px-2 py-1 dropdown-menu-large"> + <form> + <gl-form-group + label-size="sm" + label-for="docker-login-btn" + :label="$options.i18n.loginCommandLabel" + > + <gl-form-input-group id="docker-login-btn" :value="dockerLoginCommand" readonly> + <template #append> + <clipboard-button + class="border" + :text="dockerLoginCommand" + :title="$options.i18n.copyLoginTitle" + /> + </template> + </gl-form-input-group> + </gl-form-group> + + <gl-form-group + label-size="sm" + label-for="docker-build-btn" + :label="$options.i18n.buildCommandLabel" + > + <gl-form-input-group id="docker-build-btn" :value="dockerBuildCommand" readonly> + <template #append> + <clipboard-button + class="border" + :text="dockerBuildCommand" + :title="$options.i18n.copyBuildTitle" + /> + </template> + </gl-form-input-group> + </gl-form-group> + + <gl-form-group + class="mb-0" + label-size="sm" + label-for="docker-push-btn" + :label="$options.i18n.pushCommandLabel" + > + <gl-form-input-group id="docker-push-btn" :value="dockerPushCommand" readonly> + <template #append> + <clipboard-button + class="border" + :text="dockerPushCommand" + :title="$options.i18n.copyPushTitle" + /> + </template> + </gl-form-input-group> + </gl-form-group> + </form> + </li> + </gl-dropdown> +</template> diff --git a/app/assets/javascripts/registry/explorer/constants.js b/app/assets/javascripts/registry/explorer/constants.js index ef72c085972..f5d935a2d70 100644 --- a/app/assets/javascripts/registry/explorer/constants.js +++ b/app/assets/javascripts/registry/explorer/constants.js @@ -47,3 +47,11 @@ export const EXPIRATION_POLICY_ALERT_FULL_MESSAGE = s__( export const EXPIRATION_POLICY_ALERT_SHORT_MESSAGE = s__( 'ContainerRegistry|The retention and expiration policy for this Container Registry has been enabled. For more information visit the %{linkStart}documentation%{linkEnd}', ); + +export const QUICK_START = s__('ContainerRegistry|Quick Start'); +export const LOGIN_COMMAND_LABEL = s__('ContainerRegistry|Login'); +export const COPY_LOGIN_TITLE = s__('ContainerRegistry|Copy login command'); +export const BUILD_COMMAND_LABEL = s__('ContainerRegistry|Build an image'); +export const COPY_BUILD_TITLE = s__('ContainerRegistry|Copy build command'); +export const PUSH_COMMAND_LABEL = s__('ContainerRegistry|Push an image'); +export const COPY_PUSH_TITLE = s__('ContainerRegistry|Copy push command'); diff --git a/app/assets/javascripts/registry/explorer/pages/list.vue b/app/assets/javascripts/registry/explorer/pages/list.vue index c6ba06cd68c..7e321e927d3 100644 --- a/app/assets/javascripts/registry/explorer/pages/list.vue +++ b/app/assets/javascripts/registry/explorer/pages/list.vue @@ -16,6 +16,7 @@ import ClipboardButton from '~/vue_shared/components/clipboard_button.vue'; import ProjectEmptyState from '../components/project_empty_state.vue'; import GroupEmptyState from '../components/group_empty_state.vue'; import ProjectPolicyAlert from '../components/project_policy_alert.vue'; +import QuickstartDropdown from '../components/quickstart_dropdown.vue'; export default { name: 'RegistryListApp', @@ -26,6 +27,7 @@ export default { GroupEmptyState, ProjectPolicyAlert, ClipboardButton, + QuickstartDropdown, GlButton, GlIcon, GlModal, @@ -62,6 +64,9 @@ export default { this.requestImagesList({ page }); }, }, + showQuickStartDropdown() { + return Boolean(!this.isLoading && !this.config?.isGroupPage && this.images?.length); + }, }, methods: { ...mapActions(['requestImagesList', 'requestDeleteImage']), @@ -114,7 +119,10 @@ export default { <template v-else> <div> - <h4>{{ s__('ContainerRegistry|Container Registry') }}</h4> + <div class="d-flex justify-content-between align-items-center"> + <h4>{{ s__('ContainerRegistry|Container Registry') }}</h4> + <quickstart-dropdown v-if="showQuickStartDropdown" class="d-none d-sm-block" /> + </div> <p> <gl-sprintf :message=" diff --git a/app/assets/javascripts/registry/explorer/stores/getters.js b/app/assets/javascripts/registry/explorer/stores/getters.js index 5619b73d495..1136257a024 100644 --- a/app/assets/javascripts/registry/explorer/stores/getters.js +++ b/app/assets/javascripts/registry/explorer/stores/getters.js @@ -1,6 +1,20 @@ -// eslint-disable-next-line import/prefer-default-export export const tags = state => { // to show the loader inside the table we need to pass an empty array to gl-table whenever the table is loading // this is to take in account isLoading = true and state.tags =[1,2,3] during pagination and delete return state.isLoading ? [] : state.tags; }; + +export const dockerBuildCommand = state => { + /* eslint-disable @gitlab/require-i18n-strings */ + return `docker build -t ${state.config.repositoryUrl} .`; +}; + +export const dockerPushCommand = state => { + /* eslint-disable @gitlab/require-i18n-strings */ + return `docker push ${state.config.repositoryUrl}`; +}; + +export const dockerLoginCommand = state => { + /* eslint-disable @gitlab/require-i18n-strings */ + return `docker login ${state.config.registryHostUrlWithPort}`; +}; diff --git a/app/controllers/groups/settings/ci_cd_controller.rb b/app/controllers/groups/settings/ci_cd_controller.rb index 3d347429398..ffa3f2c3364 100644 --- a/app/controllers/groups/settings/ci_cd_controller.rb +++ b/app/controllers/groups/settings/ci_cd_controller.rb @@ -7,7 +7,7 @@ module Groups before_action :authorize_admin_group! before_action :authorize_update_max_artifacts_size!, only: [:update] before_action do - push_frontend_feature_flag(:new_variables_ui, @group, default_enabled: true) + push_frontend_feature_flag(:new_variables_ui, @group) end before_action :define_variables, only: [:show, :create_deploy_token] diff --git a/app/controllers/projects/settings/ci_cd_controller.rb b/app/controllers/projects/settings/ci_cd_controller.rb index 43c798bfc6e..aac6ecb07e4 100644 --- a/app/controllers/projects/settings/ci_cd_controller.rb +++ b/app/controllers/projects/settings/ci_cd_controller.rb @@ -6,7 +6,7 @@ module Projects before_action :authorize_admin_pipeline! before_action :define_variables before_action do - push_frontend_feature_flag(:new_variables_ui, @project, default_enabled: true) + push_frontend_feature_flag(:new_variables_ui, @project) end def show diff --git a/app/views/admin/groups/show.html.haml b/app/views/admin/groups/show.html.haml index 160c3b4d06d..91ccfb07f49 100644 --- a/app/views/admin/groups/show.html.haml +++ b/app/views/admin/groups/show.html.haml @@ -78,14 +78,15 @@ .card-footer = paginate @projects, param_name: 'projects_page', theme: 'gitlab' - - if @group.shared_projects.any? + - shared_projects = @group.shared_projects.sort_by(&:name) + - unless shared_projects.empty? .card .card-header = _('Projects shared with %{group_name}') % { group_name: @group.name } %span.badge.badge-pill - #{@group.shared_projects.count} + #{shared_projects.size} %ul.content-list - - @group.shared_projects.sort_by(&:name).each do |project| + - shared_projects.each do |project| %li %strong = link_to project.full_name, [:admin, project.namespace.becomes(Namespace), project] diff --git a/app/views/admin/users/_user.html.haml b/app/views/admin/users/_user.html.haml index 978e830d0e4..440eaac1917 100644 --- a/app/views/admin/users/_user.html.haml +++ b/app/views/admin/users/_user.html.haml @@ -14,51 +14,52 @@ = _('Last activity') .table-mobile-content = user.last_activity_on.nil? ? _('Never') : l(user.last_activity_on, format: :admin) - .table-section.section-20.table-button-footer - .table-action-buttons - = link_to _('Edit'), edit_admin_user_path(user), id: "edit_#{dom_id(user)}", class: 'btn btn-default' - - unless user == current_user - %button.dropdown-new.btn.btn-default{ type: 'button', data: { toggle: 'dropdown' } } - = sprite_icon('settings') - = sprite_icon('chevron-down') - %ul.dropdown-menu.dropdown-menu-right - %li.dropdown-header - = _('Settings') - %li - - if user.ldap_blocked? - %span.small - = s_('AdminUsers|Cannot unblock LDAP blocked users') - - elsif user.blocked? - = link_to _('Unblock'), unblock_admin_user_path(user), method: :put - - else - %button.btn{ data: { 'gl-modal-action': 'block', - url: block_admin_user_path(user), - username: sanitize_name(user.name) } } - = s_('AdminUsers|Block') - - if user.can_be_deactivated? + - unless user.internal? + .table-section.section-20.table-button-footer + .table-action-buttons + = link_to _('Edit'), edit_admin_user_path(user), id: "edit_#{dom_id(user)}", class: 'btn btn-default' + - unless user == current_user + %button.dropdown-new.btn.btn-default{ type: 'button', data: { toggle: 'dropdown' } } + = sprite_icon('settings') + = sprite_icon('chevron-down') + %ul.dropdown-menu.dropdown-menu-right + %li.dropdown-header + = _('Settings') %li - %button.btn{ data: { 'gl-modal-action': 'deactivate', - url: deactivate_admin_user_path(user), - username: sanitize_name(user.name) } } - = s_('AdminUsers|Deactivate') - - elsif user.deactivated? - %li - = link_to _('Activate'), activate_admin_user_path(user), method: :put - - if user.access_locked? - %li - = link_to _('Unlock'), unlock_admin_user_path(user), method: :put, data: { confirm: _('Are you sure?') } - - if can?(current_user, :destroy_user, user) - %li.divider - - if user.can_be_removed? - %li - %button.delete-user-button.btn.text-danger{ data: { 'gl-modal-action': 'delete', - delete_user_url: admin_user_path(user), - block_user_url: block_admin_user_path(user), - username: sanitize_name(user.name) } } - = s_('AdminUsers|Delete user') - %li - %button.delete-user-button.btn.text-danger{ data: { 'gl-modal-action': 'delete-with-contributions', - delete_user_url: admin_user_path(user, hard_delete: true), - block_user_url: block_admin_user_path(user), - username: sanitize_name(user.name) } } - = s_('AdminUsers|Delete user and contributions') + - if user.ldap_blocked? + %span.small + = s_('AdminUsers|Cannot unblock LDAP blocked users') + - elsif user.blocked? + = link_to _('Unblock'), unblock_admin_user_path(user), method: :put + - else + %button.btn{ data: { 'gl-modal-action': 'block', + url: block_admin_user_path(user), + username: sanitize_name(user.name) } } + = s_('AdminUsers|Block') + - if user.can_be_deactivated? + %li + %button.btn{ data: { 'gl-modal-action': 'deactivate', + url: deactivate_admin_user_path(user), + username: sanitize_name(user.name) } } + = s_('AdminUsers|Deactivate') + - elsif user.deactivated? + %li + = link_to _('Activate'), activate_admin_user_path(user), method: :put + - if user.access_locked? + %li + = link_to _('Unlock'), unlock_admin_user_path(user), method: :put, data: { confirm: _('Are you sure?') } + - if can?(current_user, :destroy_user, user) + %li.divider + - if user.can_be_removed? + %li + %button.delete-user-button.btn.text-danger{ data: { 'gl-modal-action': 'delete', + delete_user_url: admin_user_path(user), + block_user_url: block_admin_user_path(user), + username: sanitize_name(user.name) } } + = s_('AdminUsers|Delete user') + %li + %button.delete-user-button.btn.text-danger{ data: { 'gl-modal-action': 'delete-with-contributions', + delete_user_url: admin_user_path(user, hard_delete: true), + block_user_url: block_admin_user_path(user), + username: sanitize_name(user.name) } } + = s_('AdminUsers|Delete user and contributions') diff --git a/app/views/ci/variables/_index.html.haml b/app/views/ci/variables/_index.html.haml index aadb2c62d83..f11c730eba6 100644 --- a/app/views/ci/variables/_index.html.haml +++ b/app/views/ci/variables/_index.html.haml @@ -5,7 +5,7 @@ - link_start = '<a href="%{url}">'.html_safe % { url: help_page_path('ci/variables/README', anchor: 'protected-variables') } = s_('Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default').html_safe % { link_start: link_start, link_end: '</a>'.html_safe } -- if Feature.enabled?(:new_variables_ui, @project || @group, default_enabled: true) +- if Feature.enabled?(:new_variables_ui, @project || @group) - is_group = !@group.nil? #js-ci-project-variables{ data: { endpoint: save_endpoint, project_id: @project&.id || '', group: is_group.to_s, maskable_regex: ci_variable_maskable_regex} } |