Skip to content
Snippets Groups Projects
Commit 52646106 authored by Tim Zallmann's avatar Tim Zallmann
Browse files

Merge branch 'ce-port-3959-mirroring-interface-improvements' into 'master'

port "Resolve "Mirroring interface improvements""

See merge request gitlab-org/gitlab-ce!20837
parents e5c0f495 641d8ec7
No related branches found
No related tags found
1 merge request!10495Merge Requests - Assignee
Showing
with 300 additions and 80 deletions
import initForm from '../form';
import MirrorRepos from './mirror_repos';
 
document.addEventListener('DOMContentLoaded', initForm);
document.addEventListener('DOMContentLoaded', () => {
initForm();
const mirrorReposContainer = document.querySelector('.js-mirror-settings');
if (mirrorReposContainer) new MirrorRepos(mirrorReposContainer).init();
});
import $ from 'jquery';
import _ from 'underscore';
import { __ } from '~/locale';
import Flash from '~/flash';
import axios from '~/lib/utils/axios_utils';
export default class MirrorRepos {
constructor(container) {
this.$container = $(container);
this.$form = $('.js-mirror-form', this.$container);
this.$urlInput = $('.js-mirror-url', this.$form);
this.$protectedBranchesInput = $('.js-mirror-protected', this.$form);
this.$table = $('.js-mirrors-table-body', this.$container);
this.mirrorEndpoint = this.$form.data('projectMirrorEndpoint');
}
init() {
this.initMirrorPush();
this.registerUpdateListeners();
}
initMirrorPush() {
this.$passwordGroup = $('.js-password-group', this.$container);
this.$password = $('.js-password', this.$passwordGroup);
this.$authMethod = $('.js-auth-method', this.$form);
this.$authMethod.on('change', () => this.togglePassword());
this.$password.on('input.updateUrl', () => this.debouncedUpdateUrl());
}
updateUrl() {
let val = this.$urlInput.val();
if (this.$password) {
const password = this.$password.val();
if (password) val = val.replace('@', `:${password}@`);
}
$('.js-mirror-url-hidden', this.$form).val(val);
}
updateProtectedBranches() {
const val = this.$protectedBranchesInput.get(0).checked
? this.$protectedBranchesInput.val()
: '0';
$('.js-mirror-protected-hidden', this.$form).val(val);
}
registerUpdateListeners() {
this.debouncedUpdateUrl = _.debounce(() => this.updateUrl(), 200);
this.$urlInput.on('input', () => this.debouncedUpdateUrl());
this.$protectedBranchesInput.on('change', () => this.updateProtectedBranches());
this.$table.on('click', '.js-delete-mirror', event => this.deleteMirror(event));
}
togglePassword() {
const isPassword = this.$authMethod.val() === 'password';
if (!isPassword) {
this.$password.val('');
this.updateUrl();
}
this.$passwordGroup.collapse(isPassword ? 'show' : 'hide');
}
deleteMirror(event, existingPayload) {
const $target = $(event.currentTarget);
let payload = existingPayload;
if (!payload) {
payload = {
project: {
remote_mirrors_attributes: {
id: $target.data('mirrorId'),
enabled: 0,
},
},
};
}
return axios
.put(this.mirrorEndpoint, payload)
.then(() => this.removeRow($target))
.catch(() => Flash(__('Failed to remove mirror.')));
}
/* eslint-disable class-methods-use-this */
removeRow($target) {
const row = $target.closest('tr');
$('.js-delete-mirror', row).tooltip('hide');
row.remove();
}
/* eslint-enable class-methods-use-this */
}
Loading
Loading
@@ -201,7 +201,7 @@ label {
}
 
.gl-show-field-errors {
.form-control {
.form-control:not(textarea) {
height: 34px;
}
 
Loading
Loading
Loading
Loading
@@ -301,3 +301,17 @@
margin-bottom: 0;
}
}
.mirror-error-badge {
background-color: $error-bg;
border-radius: $border-radius-default;
color: $white-light;
}
.push-pull-table {
margin-top: 1em;
.mirror-action-buttons {
padding-right: 0;
}
}
module MirrorHelper
def mirrors_form_data_attributes
{ project_mirror_endpoint: project_mirror_path(@project) }
end
end
class ProjectMirrorSerializer < BaseSerializer
entity ProjectMirrorEntity
end
.account-well.prepend-top-default.append-bottom-default
%ul
%li
The repository must be accessible over <code>http://</code>, <code>https://</code>, <code>ssh://</code> or <code>git://</code>.
%li
Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>.
%li
The update action will time out after 10 minutes. For big repositories, use a clone/push combination.
%li
The Git LFS objects will <strong>not</strong> be synced.
= _('The repository must be accessible over <code>http://</code>,
<code>https://</code>, <code>ssh://</code> and <code>git://</code>.').html_safe
%li= _('Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>.').html_safe
%li= _('The update action will time out after 15 minutes. For big repositories, use a clone/push combination.')
%li= _('The Git LFS objects will <strong>not</strong> be synced.').html_safe
%li
= _('This user will be the author of all events in the activity feed that are the result of an update,
like new branches being created or new commits being pushed to existing branches.')
- expanded = Rails.env.test?
- protocols = Gitlab::UrlSanitizer::ALLOWED_SCHEMES.join('|')
%section.settings.project-mirror-settings.js-mirror-settings.no-animate{ class: ('expanded' if expanded) }
.settings-header
%h4= _('Mirroring repositories')
%button.btn.js-settings-toggle
= expanded ? _('Collapse') : _('Expand')
%p
= _('Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically.')
= link_to _('Read more'), help_page_path('workflow/repository_mirroring'), target: '_blank'
.settings-content
= form_for @project, url: project_mirror_path(@project), html: { class: 'gl-show-field-errors js-mirror-form', autocomplete: 'false', data: mirrors_form_data_attributes } do |f|
.panel.panel-default
.panel-heading
%h3.panel-title= _('Mirror a repository')
.panel-body
%div= form_errors(@project)
.form-group.has-feedback
= label_tag :url, _('Git repository URL'), class: 'label-light'
= text_field_tag :url, nil, class: 'form-control js-mirror-url js-repo-url', placeholder: _('Input your repository URL'), required: true, pattern: "(#{protocols}):\/\/.+"
= render 'projects/mirrors/instructions'
= render 'projects/mirrors/mirror_repos_form', f: f
.form-check.append-bottom-10
= check_box_tag :only_protected_branches, '1', false, class: 'js-mirror-protected form-check-input'
= label_tag :only_protected_branches, _('Only mirror protected branches'), class: 'form-check-label'
= link_to icon('question-circle'), help_page_path('user/project/protected_branches')
.panel-footer
= f.submit _('Mirror repository'), class: 'btn btn-create', name: :update_remote_mirror
.panel.panel-default
.table-responsive
%table.table.push-pull-table
%thead
%tr
%th
= _('Mirrored repositories')
= render_if_exists 'projects/mirrors/mirrored_repositories_count'
%th= _('Direction')
%th= _('Last update')
%th
%th
%tbody.js-mirrors-table-body
= render_if_exists 'projects/mirrors/table_pull_row'
- @project.remote_mirrors.each_with_index do |mirror, index|
- if mirror.enabled
%tr
%td= mirror.safe_url
%td= _('Push')
%td= mirror.last_update_at.present? ? time_ago_with_tooltip(mirror.last_update_at) : _('Never')
%td
- if mirror.last_error.present?
.badge.mirror-error-badge{ data: { toggle: 'tooltip', html: 'true' }, title: html_escape(mirror.last_error.try(:strip)) }= _('Error')
%td.mirror-action-buttons
.btn-group.mirror-actions-group.pull-right{ role: 'group' }
= render 'shared/remote_mirror_update_button', remote_mirror: mirror
%button.js-delete-mirror.btn.btn-danger{ type: 'button', data: { mirror_id: mirror.id, toggle: 'tooltip', container: 'body' }, title: _('Remove') }= icon('trash-o')
- protocols = Gitlab::UrlSanitizer::ALLOWED_SCHEMES.join('|')
.form-group
= label_tag :mirror_direction, _('Mirror direction'), class: 'label-light'
= select_tag :mirror_direction, options_for_select([[_('Push'), 'push']]), class: 'form-control js-mirror-direction', disabled: true
= f.fields_for :remote_mirrors, @project.remote_mirrors.build do |rm_f|
= rm_f.hidden_field :enabled, value: '1'
= rm_f.hidden_field :url, class: 'js-mirror-url-hidden', required: true, pattern: "(#{protocols}):\/\/.+"
= rm_f.hidden_field :only_protected_branches, class: 'js-mirror-protected-hidden'
.form-group
= label_tag :auth_method, _('Authentication method'), class: 'label-bold'
= select_tag :auth_method, options_for_select([[_('None'), 'none'], [_('Password'), 'password']], 'none'), { class: "form-control js-auth-method" }
.form-group.js-password-group.collapse
= label_tag :password, _('Password'), class: 'label-bold'
= text_field_tag :password, '', class: 'form-control js-password'
- expanded = Rails.env.test?
%section.settings.no-animate#js-push-remote-settings{ class: ('expanded' if expanded) }
.settings-header
%h4
Push to a remote repository
%button.btn.js-settings-toggle
= expanded ? 'Collapse' : 'Expand'
%p
Set up the remote repository that you want to update with the content of the current repository
every time someone pushes to it.
= link_to 'Read more', help_page_path('workflow/repository_mirroring', anchor: 'pushing-to-a-remote-repository'), target: '_blank'
.settings-content
= form_for @project, url: project_mirror_path(@project) do |f|
%div
= form_errors(@project)
= render "shared/remote_mirror_update_button", remote_mirror: @remote_mirror
- if @remote_mirror.last_error.present?
.panel.panel-danger
.panel-heading
- if @remote_mirror.last_update_at
The remote repository failed to update #{time_ago_with_tooltip(@remote_mirror.last_update_at)}.
- else
The remote repository failed to update.
- if @remote_mirror.last_successful_update_at
Last successful update #{time_ago_with_tooltip(@remote_mirror.last_successful_update_at)}.
.panel-body
%pre
:preserve
#{h(@remote_mirror.last_error.strip)}
= f.fields_for :remote_mirrors, @remote_mirror do |rm_form|
.form-group
= rm_form.check_box :enabled, class: "float-left"
.prepend-left-20
= rm_form.label :enabled, "Remote mirror repository", class: "label-bold append-bottom-0"
%p.light.append-bottom-0
Automatically update the remote mirror's branches, tags, and commits from this repository every time someone pushes to it.
.form-group.has-feedback
= rm_form.label :url, "Git repository URL", class: "label-bold"
= rm_form.text_field :url, class: "form-control", placeholder: 'https://username:password@gitlab.company.com/group/project.git'
= render "projects/mirrors/instructions"
.form-group
= rm_form.check_box :only_protected_branches, class: 'float-left'
.prepend-left-20
= rm_form.label :only_protected_branches, class: 'label-bold'
= link_to icon('question-circle'), help_page_path('user/project/protected_branches')
= f.submit 'Save changes', class: 'btn btn-create', name: 'update_remote_mirror'
- if can?(current_user, :admin_remote_mirror, @project)
= render 'projects/mirrors/push'
= render 'projects/mirrors/mirror_repos'
- if @project.has_remote_mirror?
.append-bottom-default
- if remote_mirror.update_in_progress?
%span.btn.disabled
= icon("refresh spin")
Updating&hellip;
- else
= link_to update_now_project_mirror_path(@project, sync_remote: true), method: :post, class: "btn" do
= icon("refresh")
Update Now
- if @remote_mirror.last_successful_update_at
%p.inline.prepend-left-10
Successfully updated #{time_ago_with_tooltip(@remote_mirror.last_successful_update_at)}.
- if remote_mirror.update_in_progress?
%button.btn.disabled{ type: 'button', data: { toggle: 'tooltip', container: 'body' }, title: _('Updating') }
= icon("refresh spin")
- else
= link_to update_now_project_mirror_path(@project, sync_remote: true), method: :post, class: "btn", data: { toggle: 'tooltip', container: 'body' }, title: _('Update now') do
= icon("refresh")
Loading
Loading
@@ -640,6 +640,9 @@ msgstr ""
msgid "Authentication log"
msgstr ""
 
msgid "Authentication method"
msgstr ""
msgid "Author"
msgstr ""
 
Loading
Loading
@@ -2169,6 +2172,9 @@ msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
msgstr ""
 
msgid "Direction"
msgstr ""
msgid "Directory name"
msgstr ""
 
Loading
Loading
@@ -2391,6 +2397,9 @@ msgstr ""
msgid "Environments|You don't have any environments right now."
msgstr ""
 
msgid "Error"
msgstr ""
msgid "Error Reporting and Logging"
msgstr ""
 
Loading
Loading
@@ -2517,6 +2526,9 @@ msgstr ""
msgid "Failed to remove issue from board, please try again."
msgstr ""
 
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
 
Loading
Loading
@@ -3031,12 +3043,18 @@ msgstr ""
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
 
msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
msgstr ""
msgid "Incompatible Project"
msgstr ""
 
msgid "Inline"
msgstr ""
 
msgid "Input your repository URL"
msgstr ""
msgid "Install GitLab Runner"
msgstr ""
 
Loading
Loading
@@ -3468,6 +3486,21 @@ msgstr ""
msgid "Milestones|Promote Milestone"
msgstr ""
 
msgid "Mirror a repository"
msgstr ""
msgid "Mirror direction"
msgstr ""
msgid "Mirror repository"
msgstr ""
msgid "Mirrored repositories"
msgstr ""
msgid "Mirroring repositories"
msgstr ""
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr ""
 
Loading
Loading
@@ -3528,6 +3561,9 @@ msgstr ""
msgid "Network"
msgstr ""
 
msgid "Never"
msgstr ""
msgid "New"
msgstr ""
 
Loading
Loading
@@ -3791,6 +3827,9 @@ msgstr ""
msgid "Only comments from the following commit are shown below"
msgstr ""
 
msgid "Only mirror protected branches"
msgstr ""
msgid "Only project members can comment."
msgstr ""
 
Loading
Loading
@@ -4379,6 +4418,9 @@ msgstr ""
msgid "Public pipelines"
msgstr ""
 
msgid "Push"
msgstr ""
msgid "Push events"
msgstr ""
 
Loading
Loading
@@ -4780,6 +4822,9 @@ msgstr ""
msgid "Set up Koding"
msgstr ""
 
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
 
Loading
Loading
@@ -5189,6 +5234,9 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
 
msgid "The Git LFS objects will <strong>not</strong> be synced."
msgstr ""
msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project"
msgstr ""
 
Loading
Loading
@@ -5246,6 +5294,9 @@ msgstr ""
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
msgstr ""
 
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code>, <code>ssh://</code> and <code>git://</code>."
msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr ""
 
Loading
Loading
@@ -5270,6 +5321,9 @@ msgstr ""
msgid "The time taken by each data entry gathered by that stage."
msgstr ""
 
msgid "The update action will time out after 15 minutes. For big repositories, use a clone/push combination."
msgstr ""
msgid "The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of <code>:</code>. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side."
msgstr ""
 
Loading
Loading
@@ -5408,6 +5462,9 @@ msgstr ""
msgid "This user has no identities"
msgstr ""
 
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
msgid "Time before an issue gets scheduled"
msgstr ""
 
Loading
Loading
@@ -5721,9 +5778,15 @@ msgstr ""
msgid "Update"
msgstr ""
 
msgid "Update now"
msgstr ""
msgid "Update your group name, description, avatar, and other general settings."
msgstr ""
 
msgid "Updating"
msgstr ""
msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
msgstr ""
 
Loading
Loading
Loading
Loading
@@ -17,7 +17,7 @@ describe 'Project remote mirror', :feature do
 
visit project_mirror_path(project)
 
expect(page).to have_content('The remote repository failed to update.')
expect_mirror_to_have_error_and_timeago('Never')
end
end
 
Loading
Loading
@@ -27,8 +27,14 @@ describe 'Project remote mirror', :feature do
 
visit project_mirror_path(project)
 
expect(page).to have_content('The remote repository failed to update 5 minutes ago.')
expect_mirror_to_have_error_and_timeago('5 minutes ago')
end
end
def expect_mirror_to_have_error_and_timeago(timeago)
row = first('.js-mirrors-table-body tr')
expect(row).to have_content('Error')
expect(row).to have_content(timeago)
end
end
end
Loading
Loading
@@ -129,9 +129,8 @@ describe 'Projects > Settings > Repository settings' do
visit project_settings_repository_path(project)
end
 
it 'shows push mirror settings' do
expect(page).to have_selector('#project_remote_mirrors_attributes_0_enabled')
expect(page).to have_selector('#project_remote_mirrors_attributes_0_url')
it 'shows push mirror settings', :js do
expect(page).to have_selector('#mirror_direction')
end
end
end
Loading
Loading
require 'spec_helper'
describe ProjectMirrorSerializer do
it 'represents ProjectMirror entities' do
expect(described_class.entity_class).to eq(ProjectMirrorEntity)
end
end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment