diff options
161 files changed, 2008 insertions, 4439 deletions
diff --git a/.rubocop.yml b/.rubocop.yml index 8f611a96702..66a40f2cf57 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -397,7 +397,7 @@ Style/ParenthesesAroundCondition: # Configuration parameters: EnforcedStyle, SupportedStyles. # SupportedStyles: short, verbose Style/PreferredHashMethods: - Enabled: true + Enabled: false # Checks for an obsolete RuntimeException argument in raise/fail. Style/RedundantException: diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION index d9df1bbc0c7..bc859cbd6d9 100644 --- a/GITALY_SERVER_VERSION +++ b/GITALY_SERVER_VERSION @@ -1 +1 @@ -0.11.0 +0.11.2 @@ -2,6 +2,7 @@ source 'https://rubygems.org' gem 'rails', '4.2.8' gem 'rails-deprecated_sanitizer', '~> 1.0.3' +gem 'bootsnap', '~> 1.0.0' # Responders respond_to and respond_with gem 'responders', '~> 2.0' @@ -17,7 +18,7 @@ gem 'pg', '~> 0.18.2', group: :postgres gem 'rugged', '~> 0.25.1.1' -gem 'faraday', '~> 0.11.0' +gem 'faraday', '~> 0.12' # Authentication libraries gem 'devise', '~> 4.2' @@ -258,7 +259,7 @@ gem 'sentry-raven', '~> 2.4.0' gem 'premailer-rails', '~> 1.9.0' # I18n -gem 'ruby_parser', '~> 3.8.4', require: false +gem 'ruby_parser', '~> 3.8', require: false gem 'gettext_i18n_rails', '~> 1.8.0' gem 'gettext_i18n_rails_js', '~> 1.2.0' gem 'gettext', '~> 3.2.2', require: false, group: :development @@ -358,7 +359,7 @@ gem 'html2text' gem 'ruby-prof', '~> 0.16.2' # OAuth -gem 'oauth2', '~> 1.3.0' +gem 'oauth2', '~> 1.4' # Soft deletion gem 'paranoia', '~> 2.2' diff --git a/Gemfile.lock b/Gemfile.lock index b5f9c3beca7..a898c12485e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -82,6 +82,8 @@ GEM bindata (2.3.5) binding_of_caller (0.7.2) debug_inspector (>= 0.0.1) + bootsnap (1.0.0) + msgpack (~> 1.0) bootstrap-sass (3.3.6) autoprefixer-rails (>= 5.2.1) sass (>= 3.3.4) @@ -191,7 +193,7 @@ GEM factory_girl_rails (4.7.0) factory_girl (~> 4.7.0) railties (>= 3.0.0) - faraday (0.11.0) + faraday (0.12.1) multipart-post (>= 1.2, < 3) faraday_middleware (0.11.0.1) faraday (>= 0.7.4, < 1.0) @@ -459,6 +461,7 @@ GEM minitest (5.7.0) mmap2 (2.2.6) mousetrap-rails (1.4.6) + msgpack (1.1.0) multi_json (1.12.1) multi_xml (0.6.0) multipart-post (2.0.0) @@ -474,8 +477,8 @@ GEM mini_portile2 (~> 2.1.0) numerizer (0.1.1) oauth (0.5.1) - oauth2 (1.3.1) - faraday (>= 0.8, < 0.12) + oauth2 (1.4.0) + faraday (>= 0.8, < 0.13) jwt (~> 1.0) multi_json (~> 1.3) multi_xml (~> 0.5) @@ -703,7 +706,7 @@ GEM ruby-progressbar (1.8.1) ruby-saml (1.4.1) nokogiri (>= 1.5.10) - ruby_parser (3.8.4) + ruby_parser (3.9.0) sexp_processor (~> 4.1) rubyntlm (0.5.2) rubypants (0.2.0) @@ -736,7 +739,7 @@ GEM sentry-raven (2.4.0) faraday (>= 0.7.6, < 1.0) settingslogic (2.0.9) - sexp_processor (4.8.0) + sexp_processor (4.9.0) sham_rack (1.3.6) rack shoulda-matchers (2.8.0) @@ -888,6 +891,7 @@ DEPENDENCIES benchmark-ips (~> 2.3.0) better_errors (~> 2.1.0) binding_of_caller (~> 0.7.2) + bootsnap (~> 1.0.0) bootstrap-sass (~> 3.3.0) brakeman (~> 3.6.0) browser (~> 2.2) @@ -916,7 +920,7 @@ DEPENDENCIES email_reply_trimmer (~> 0.1) email_spec (~> 1.6.0) factory_girl_rails (~> 4.7.0) - faraday (~> 0.11.0) + faraday (~> 0.12) ffaker (~> 2.4) flay (~> 2.8.0) flipper (~> 0.10.2) @@ -975,7 +979,7 @@ DEPENDENCIES mysql2 (~> 0.3.16) net-ssh (~> 3.0.1) nokogiri (~> 1.6.7, >= 1.6.7.2) - oauth2 (~> 1.3.0) + oauth2 (~> 1.4) octokit (~> 4.6.2) oj (~> 2.17.4) omniauth (~> 1.4.2) @@ -1027,7 +1031,7 @@ DEPENDENCIES rubocop-rspec (~> 1.15.0) ruby-fogbugz (~> 0.2.1) ruby-prof (~> 0.16.2) - ruby_parser (~> 3.8.4) + ruby_parser (~> 3.8) rufus-scheduler (~> 3.4) rugged (~> 0.25.1.1) sanitize (~> 2.0) diff --git a/app/assets/javascripts/blob/blob_file_dropzone.js b/app/assets/javascripts/blob/blob_file_dropzone.js index 4568b86f298..dc636050221 100644 --- a/app/assets/javascripts/blob/blob_file_dropzone.js +++ b/app/assets/javascripts/blob/blob_file_dropzone.js @@ -35,7 +35,7 @@ export default class BlobFileDropzone { this.removeFile(file); }); this.on('sending', function (file, xhr, formData) { - formData.append('branch_name', form.find('input[name="branch_name"]').val()); + formData.append('branch_name', form.find('.js-branch-name').val()); formData.append('create_merge_request', form.find('.js-create-merge-request').val()); formData.append('commit_message', form.find('.js-commit-message').val()); }); diff --git a/app/assets/javascripts/blob/create_branch_dropdown.js b/app/assets/javascripts/blob/create_branch_dropdown.js deleted file mode 100644 index 95517f51b1c..00000000000 --- a/app/assets/javascripts/blob/create_branch_dropdown.js +++ /dev/null @@ -1,88 +0,0 @@ -class CreateBranchDropdown { - constructor(el, targetBranchDropdown) { - this.targetBranchDropdown = targetBranchDropdown; - this.el = el; - this.dropdownBack = this.el.closest('.dropdown').querySelector('.dropdown-menu-back'); - this.cancelButton = this.el.querySelector('.js-cancel-branch-btn'); - this.newBranchField = this.el.querySelector('#new_branch_name'); - this.newBranchCreateButton = this.el.querySelector('.js-new-branch-btn'); - - this.newBranchCreateButton.setAttribute('disabled', ''); - - this.addBindings(); - this.cleanupWrapper = this.cleanup.bind(this); - document.addEventListener('beforeunload', this.cleanupWrapper); - } - - cleanup() { - this.cleanBindings(); - document.removeEventListener('beforeunload', this.cleanupWrapper); - } - - cleanBindings() { - this.newBranchField.removeEventListener('keyup', this.enableBranchCreateButtonWrapper); - this.newBranchField.removeEventListener('change', this.enableBranchCreateButtonWrapper); - this.newBranchField.removeEventListener('keydown', this.handleNewBranchKeydownWrapper); - this.dropdownBack.removeEventListener('click', this.resetFormWrapper); - this.cancelButton.removeEventListener('click', this.handleCancelClickWrapper); - this.newBranchCreateButton.removeEventListener('click', this.createBranchWrapper); - } - - addBindings() { - this.enableBranchCreateButtonWrapper = this.enableBranchCreateButton.bind(this); - this.handleNewBranchKeydownWrapper = this.handleNewBranchKeydown.bind(this); - this.resetFormWrapper = this.resetForm.bind(this); - this.handleCancelClickWrapper = this.handleCancelClick.bind(this); - this.createBranchWrapper = this.createBranch.bind(this); - - this.newBranchField.addEventListener('keyup', this.enableBranchCreateButtonWrapper); - this.newBranchField.addEventListener('change', this.enableBranchCreateButtonWrapper); - this.newBranchField.addEventListener('keydown', this.handleNewBranchKeydownWrapper); - this.dropdownBack.addEventListener('click', this.resetFormWrapper); - this.cancelButton.addEventListener('click', this.handleCancelClickWrapper); - this.newBranchCreateButton.addEventListener('click', this.createBranchWrapper); - } - - handleCancelClick(e) { - e.preventDefault(); - e.stopPropagation(); - - this.resetForm(); - this.dropdownBack.click(); - } - - handleNewBranchKeydown(e) { - const keyCode = e.which; - const ENTER_KEYCODE = 13; - if (keyCode === ENTER_KEYCODE) { - this.createBranch(e); - } - } - - enableBranchCreateButton() { - if (this.newBranchField.value !== '') { - this.newBranchCreateButton.removeAttribute('disabled'); - } else { - this.newBranchCreateButton.setAttribute('disabled', ''); - } - } - - resetForm() { - this.newBranchField.value = ''; - this.enableBranchCreateButtonWrapper(); - } - - createBranch(e) { - e.preventDefault(); - - if (this.newBranchCreateButton.getAttribute('disabled') === '') { - return; - } - const newBranchName = this.newBranchField.value; - this.targetBranchDropdown.setNewBranch(newBranchName); - this.resetForm(); - } -} - -window.gl = window.gl || {}; -gl.CreateBranchDropdown = CreateBranchDropdown; diff --git a/app/assets/javascripts/blob/target_branch_dropdown.js b/app/assets/javascripts/blob/target_branch_dropdown.js deleted file mode 100644 index d52d69b1274..00000000000 --- a/app/assets/javascripts/blob/target_branch_dropdown.js +++ /dev/null @@ -1,152 +0,0 @@ -/* eslint-disable class-methods-use-this */ -const SELECT_ITEM_MSG = 'Select'; - -class TargetBranchDropDown { - constructor(dropdown) { - this.dropdown = dropdown; - this.$dropdown = $(dropdown); - this.fieldName = this.dropdown.getAttribute('data-field-name'); - this.form = this.dropdown.closest('form'); - this.createDropdown(); - } - - static bootstrap() { - const dropdowns = document.querySelectorAll('.js-project-branches-dropdown'); - [].forEach.call(dropdowns, dropdown => new TargetBranchDropDown(dropdown)); - } - - createDropdown() { - const self = this; - this.$dropdown.glDropdown({ - selectable: true, - filterable: true, - search: { - fields: ['title'], - }, - data: (term, callback) => $.ajax({ - url: self.dropdown.getAttribute('data-refs-url'), - data: { - ref: self.dropdown.getAttribute('data-ref'), - show_all: true, - }, - dataType: 'json', - }).done(refs => callback(self.dropdownData(refs))), - toggleLabel(item, el) { - if (el.is('.is-active')) { - return item.text; - } - return SELECT_ITEM_MSG; - }, - clicked(options) { - options.e.preventDefault(); - self.onClick.call(self); - }, - fieldName: self.fieldName, - }); - return new gl.CreateBranchDropdown(this.form.querySelector('.dropdown-new-branch'), this); - } - - onClick() { - this.enableSubmit(); - this.$dropdown.trigger('change.branch'); - } - - enableSubmit() { - const submitBtn = this.form.querySelector('[type="submit"]'); - if (this.branchInput && this.branchInput.value) { - submitBtn.removeAttribute('disabled'); - } else { - submitBtn.setAttribute('disabled', ''); - } - } - - dropdownData(refs) { - const branchList = this.dropdownItems(refs); - this.cachedRefs = refs; - this.addDefaultBranch(branchList); - this.addNewBranch(branchList); - return { Branches: branchList }; - } - - dropdownItems(refs) { - return refs.map(this.dropdownItem); - } - - dropdownItem(ref) { - return { id: ref, text: ref, title: ref }; - } - - addDefaultBranch(branchList) { - // when no branch is selected do nothing - if (!this.branchInput) { - return; - } - - const branchInputVal = this.branchInput.value; - const currentBranchIndex = this.searchBranch(branchList, branchInputVal); - - if (currentBranchIndex === -1) { - this.unshiftBranch(branchList, this.dropdownItem(branchInputVal)); - } - } - - addNewBranch(branchList) { - if (this.newBranch) { - this.unshiftBranch(branchList, this.newBranch); - } - } - - searchBranch(branchList, branchName) { - return _.findIndex(branchList, el => branchName === el.id); - } - - unshiftBranch(branchList, branch) { - const branchIndex = this.searchBranch(branchList, branch.id); - - if (branchIndex === -1) { - branchList.unshift(branch); - } - } - - setNewBranch(newBranchName) { - this.newBranch = this.dropdownItem(newBranchName); - this.refreshData(); - this.selectBranch(this.searchBranch(this.glDropdown.fullData.Branches, newBranchName)); - } - - refreshData() { - this.glDropdown.fullData = this.dropdownData(this.cachedRefs); - this.clearFilter(); - } - - clearFilter() { - // apply an empty filter in order to refresh the data - this.glDropdown.filter.filter(''); - this.dropdown.closest('.dropdown').querySelector('.dropdown-page-one .dropdown-input-field').value = ''; - } - - selectBranch(index) { - const branch = this.dropdown.closest('.dropdown').querySelectorAll('li a')[index]; - - if (!branch.classList.contains('is-active')) { - branch.click(); - } else { - this.closeDropdown(); - } - } - - closeDropdown() { - this.dropdown.closest('.dropdown').querySelector('.dropdown-menu-close').click(); - } - - get branchInput() { - return this.form.querySelector(`input[name="${this.fieldName}"]`); - } - - get glDropdown() { - return this.$dropdown.data('glDropdown'); - } -} - -window.gl = window.gl || {}; -gl.TargetBranchDropDown = TargetBranchDropDown; diff --git a/app/assets/javascripts/boards/components/board_sidebar.js b/app/assets/javascripts/boards/components/board_sidebar.js index 386102032cb..c7afd4ead6b 100644 --- a/app/assets/javascripts/boards/components/board_sidebar.js +++ b/app/assets/javascripts/boards/components/board_sidebar.js @@ -32,9 +32,6 @@ gl.issueBoards.BoardSidebar = Vue.extend({ showSidebar () { return Object.keys(this.issue).length; }, - assigneeId() { - return this.issue.assignee ? this.issue.assignee.id : 0; - }, milestoneTitle() { return this.issue.milestone ? this.issue.milestone.title : 'No Milestone'; } diff --git a/app/assets/javascripts/build.js b/app/assets/javascripts/build.js index 3b2bb6f082f..c28f6e151a0 100644 --- a/app/assets/javascripts/build.js +++ b/app/assets/javascripts/build.js @@ -20,6 +20,7 @@ window.Build = (function () { this.$document = $(document); this.logBytes = 0; this.scrollOffsetPadding = 30; + this.hasBeenScrolled = false; this.updateDropdown = this.updateDropdown.bind(this); this.getBuildTrace = this.getBuildTrace.bind(this); @@ -62,6 +63,15 @@ window.Build = (function () { .off('click') .on('click', this.scrollToBottom.bind(this)); + const scrollThrottled = _.throttle(this.toggleScroll.bind(this), 100); + + this.$scrollContainer + .off('scroll') + .on('scroll', () => { + this.hasBeenScrolled = true; + scrollThrottled(); + }); + $(window) .off('resize.build') .on('resize.build', _.throttle(this.sidebarOnResize.bind(this), 100)); @@ -70,25 +80,16 @@ window.Build = (function () { // eslint-disable-next-line this.getBuildTrace() - .then(() => this.makeTraceScrollable()) - .then(() => this.scrollToBottom()); + .then(() => this.toggleScroll()) + .then(() => { + if (!this.hasBeenScrolled) { + this.scrollToBottom(); + } + }); this.verifyTopPosition(); } - Build.prototype.makeTraceScrollable = function () { - this.$scrollContainer.niceScroll({ - cursorcolor: '#fff', - cursoropacitymin: 1, - cursorwidth: '7px', - railpadding: { top: 5, bottom: 5, right: 5 }, - }); - - this.$scrollContainer.on('scroll', _.throttle(this.toggleScroll.bind(this), 100)); - - this.toggleScroll(); - }; - Build.prototype.canScroll = function () { return (this.$scrollContainer.prop('scrollHeight') - this.scrollOffsetPadding) > this.$scrollContainer.height(); }; @@ -104,12 +105,11 @@ window.Build = (function () { * */ Build.prototype.toggleScroll = function () { - const bottomScroll = this.$scrollContainer.scrollTop() + - this.scrollOffsetPadding + - this.$scrollContainer.height(); + const currentPosition = this.$scrollContainer.scrollTop(); + const bottomScroll = currentPosition + this.$scrollContainer.innerHeight(); if (this.canScroll()) { - if (this.$scrollContainer.scrollTop() === 0) { + if (currentPosition === 0) { this.toggleDisableButton(this.$scrollTopBtn, true); this.toggleDisableButton(this.$scrollBottomBtn, false); } else if (bottomScroll === this.$scrollContainer.prop('scrollHeight')) { @@ -123,12 +123,14 @@ window.Build = (function () { }; Build.prototype.scrollToTop = function () { - this.$scrollContainer.getNiceScroll(0).doScrollTop(0); + this.hasBeenScrolled = true; + this.$scrollContainer.scrollTop(0); this.toggleScroll(); }; Build.prototype.scrollToBottom = function () { - this.$scrollContainer.getNiceScroll(0).doScrollTo(this.$scrollContainer.prop('scrollHeight')); + this.hasBeenScrolled = true; + this.$scrollContainer.scrollTop(this.$scrollContainer.prop('scrollHeight')); this.toggleScroll(); }; @@ -147,27 +149,34 @@ window.Build = (function () { Build.prototype.verifyTopPosition = function () { const $buildPage = $('.build-page'); + const $flashError = $('.alert-wrapper'); const $header = $('.build-header', $buildPage); const $runnersStuck = $('.js-build-stuck', $buildPage); const $startsEnvironment = $('.js-environment-container', $buildPage); const $erased = $('.js-build-erased', $buildPage); + const prependTopDefault = 20; + // header + navigation + margin let topPostion = 168; - if ($header) { + if ($header.length) { topPostion += $header.outerHeight(); } - if ($runnersStuck) { + if ($runnersStuck.length) { topPostion += $runnersStuck.outerHeight(); } - if ($startsEnvironment) { - topPostion += $startsEnvironment.outerHeight(); + if ($startsEnvironment.length) { + topPostion += $startsEnvironment.outerHeight() + prependTopDefault; + } + + if ($erased.length) { + topPostion += $erased.outerHeight() + prependTopDefault; } - if ($erased) { - topPostion += $erased.outerHeight() + 10; + if ($flashError.length) { + topPostion += $flashError.outerHeight(); } this.$buildTrace.css({ @@ -216,7 +225,11 @@ window.Build = (function () { Build.timeout = setTimeout(() => { //eslint-disable-next-line this.getBuildTrace() - .then(() => this.scrollToBottom()); + .then(() => { + if (!this.hasBeenScrolled) { + this.scrollToBottom(); + } + }); }, 4000); } else { this.$buildRefreshAnimation.remove(); @@ -239,6 +252,7 @@ window.Build = (function () { Build.prototype.toggleSidebar = function (shouldHide) { const shouldShow = typeof shouldHide === 'boolean' ? !shouldHide : undefined; + const $toggleButton = $('.js-sidebar-build-toggle-header'); this.$buildTrace .toggleClass('sidebar-expanded', shouldShow) @@ -246,6 +260,16 @@ window.Build = (function () { this.$sidebar .toggleClass('right-sidebar-expanded', shouldShow) .toggleClass('right-sidebar-collapsed', shouldHide); + + $('.js-build-page') + .toggleClass('sidebar-expanded', shouldShow) + .toggleClass('sidebar-collapsed', shouldHide); + + if (this.$sidebar.hasClass('right-sidebar-expanded')) { + $toggleButton.addClass('hidden'); + } else { + $toggleButton.removeClass('hidden'); + } }; Build.prototype.sidebarOnResize = function () { @@ -253,13 +277,14 @@ window.Build = (function () { this.verifyTopPosition(); - if (this.$scrollContainer.getNiceScroll(0)) { + if (this.canScroll()) { this.toggleScroll(); } }; Build.prototype.sidebarOnClick = function () { if (this.shouldHideSidebarForViewport()) this.toggleSidebar(); + this.verifyTopPosition(); }; Build.prototype.updateArtifactRemoveDate = function () { diff --git a/app/assets/javascripts/commons/polyfills.js b/app/assets/javascripts/commons/polyfills.js index cb054a2a197..bc3e741f524 100644 --- a/app/assets/javascripts/commons/polyfills.js +++ b/app/assets/javascripts/commons/polyfills.js @@ -1,5 +1,6 @@ // ECMAScript polyfills import 'core-js/fn/array/find'; +import 'core-js/fn/array/find-index'; import 'core-js/fn/array/from'; import 'core-js/fn/array/includes'; import 'core-js/fn/object/assign'; diff --git a/app/assets/javascripts/dispatcher.js b/app/assets/javascripts/dispatcher.js index 51cc8c085b2..5f87a05067b 100644 --- a/app/assets/javascripts/dispatcher.js +++ b/app/assets/javascripts/dispatcher.js @@ -2,7 +2,6 @@ /* global UsernameValidator */ /* global ActiveTabMemoizer */ /* global ShortcutsNavigation */ -/* global Build */ /* global IssuableIndex */ /* global ShortcutsIssuable */ /* global ZenMode */ @@ -119,9 +118,6 @@ import initSettingsPanels from './settings_panels'; shortcut_handler = new ShortcutsNavigation(); new UsersSelect(); break; - case 'projects:jobs:show': - new Build(); - break; case 'projects:merge_requests:index': case 'projects:issues:index': if (gl.FilteredSearchManager && document.querySelector('.filtered-search')) { @@ -329,25 +325,14 @@ import initSettingsPanels from './settings_panels'; shortcut_handler = new ShortcutsNavigation(); new TreeView(); new BlobViewer(); - gl.TargetBranchDropDown.bootstrap(); break; case 'projects:find_file:show': shortcut_handler = true; break; - case 'projects:blob:new': - gl.TargetBranchDropDown.bootstrap(); - break; - case 'projects:blob:create': - gl.TargetBranchDropDown.bootstrap(); - break; case 'projects:blob:show': new BlobViewer(); - gl.TargetBranchDropDown.bootstrap(); initBlob(); break; - case 'projects:blob:edit': - gl.TargetBranchDropDown.bootstrap(); - break; case 'projects:blame:show': initBlob(); break; diff --git a/app/assets/javascripts/gl_dropdown.js b/app/assets/javascripts/gl_dropdown.js index d34561e5512..3babe273100 100644 --- a/app/assets/javascripts/gl_dropdown.js +++ b/app/assets/javascripts/gl_dropdown.js @@ -248,7 +248,7 @@ GitLabDropdown = (function() { return function(data) { _this.fullData = data; _this.parseData(_this.fullData); - _this.focusTextInput(); + _this.focusTextInput(true); if (_this.options.filterable && _this.filter && _this.filter.input && _this.filter.input.val() && _this.filter.input.val().trim() !== '') { return _this.filter.input.trigger('input'); } @@ -728,8 +728,20 @@ GitLabDropdown = (function() { return [selectedObject, isMarking]; }; - GitLabDropdown.prototype.focusTextInput = function() { - if (this.options.filterable) { this.filterInput.focus(); } + GitLabDropdown.prototype.focusTextInput = function(triggerFocus = false) { + if (this.options.filterable) { + $(':focus').blur(); + + this.dropdown.one('transitionend', () => { + this.filterInput.focus(); + }); + + if (triggerFocus) { + // This triggers after a ajax request + // in case of slow requests, the dropdown transition could already be finished + this.dropdown.trigger('transitionend'); + } + } }; GitLabDropdown.prototype.addInput = function(fieldName, value, selectedObject) { diff --git a/app/assets/javascripts/jobs/components/header.vue b/app/assets/javascripts/jobs/components/header.vue new file mode 100644 index 00000000000..5b9cf577189 --- /dev/null +++ b/app/assets/javascripts/jobs/components/header.vue @@ -0,0 +1,83 @@ +<script> + import ciHeader from '../../vue_shared/components/header_ci_component.vue'; + import loadingIcon from '../../vue_shared/components/loading_icon.vue'; + + export default { + name: 'jobHeaderSection', + props: { + job: { + type: Object, + required: true, + }, + isLoading: { + type: Boolean, + required: true, + }, + }, + components: { + ciHeader, + loadingIcon, + }, + data() { + return { + actions: this.getActions(), + }; + }, + computed: { + status() { + return this.job && this.job.status; + }, + shouldRenderContent() { + return !this.isLoading && Object.keys(this.job).length; + }, + }, + methods: { + getActions() { + const actions = []; + + if (this.job.new_issue_path) { + actions.push({ + label: 'New issue', + path: this.job.new_issue_path, + cssClass: 'js-new-issue btn btn-new btn-inverted visible-md-block visible-lg-block', + type: 'ujs-link', + }); + } + + if (this.job.retry_path) { + actions.push({ + label: 'Retry', + path: this.job.retry_path, + cssClass: 'js-retry-button btn btn-inverted-secondary visible-md-block visible-lg-block', + type: 'ujs-link', + }); + } + + return actions; + }, + }, + watch: { + job() { + this.actions = this.getActions(); + }, + }, + }; +</script> +<template> + <div class="js-build-header build-header top-area"> + <ci-header + v-if="shouldRenderContent" + :status="status" + item-name="Job" + :item-id="job.id" + :time="job.created_at" + :user="job.user" + :actions="actions" + :hasSidebarButton="true" + /> + <loading-icon + v-if="isLoading" + size="2" + /> + </div> +</template> diff --git a/app/assets/javascripts/jobs/components/sidebar_detail_row.vue b/app/assets/javascripts/jobs/components/sidebar_detail_row.vue new file mode 100644 index 00000000000..ab2bcd728a8 --- /dev/null +++ b/app/assets/javascripts/jobs/components/sidebar_detail_row.vue @@ -0,0 +1,31 @@ +<script> + export default { + name: 'SidebarDetailRow', + props: { + title: { + type: String, + required: false, + default: '', + }, + value: { + type: String, + required: true, + }, + }, + computed: { + hasTitle() { + return this.title.length > 0; + }, + }, + }; +</script> +<template> + <p class="build-detail-row"> + <span + v-if="hasTitle" + class="build-light-text"> + {{title}}: + </span> + {{value}} + </p> +</template> diff --git a/app/assets/javascripts/jobs/components/sidebar_details_block.vue b/app/assets/javascripts/jobs/components/sidebar_details_block.vue new file mode 100644 index 00000000000..4223a8fea49 --- /dev/null +++ b/app/assets/javascripts/jobs/components/sidebar_details_block.vue @@ -0,0 +1,150 @@ +<script> + import detailRow from './sidebar_detail_row.vue'; + import loadingIcon from '../../vue_shared/components/loading_icon.vue'; + import timeagoMixin from '../../vue_shared/mixins/timeago'; + import { timeIntervalInWords } from '../../lib/utils/datetime_utility'; + + export default { + name: 'SidebarDetailsBlock', + props: { + job: { + type: Object, + required: true, + }, + isLoading: { + type: Boolean, + required: true, + }, + }, + mixins: [ + timeagoMixin, + ], + components: { + detailRow, + loadingIcon, + }, + computed: { + shouldRenderContent() { + return !this.isLoading && Object.keys(this.job).length > 0; + }, + coverage() { + return `${this.job.coverage}%`; + }, + duration() { + return timeIntervalInWords(this.job.duration); + }, + queued() { + return timeIntervalInWords(this.job.queued); + }, + runnerId() { + return `#${this.job.runner.id}`; + }, + }, + }; +</script> +<template> + <div> + <template v-if="shouldRenderContent"> + <div + class="block retry-link" + v-if="job.retry_path || job.new_issue_path"> + <a + v-if="job.new_issue_path" + class="js-new-issue btn btn-new btn-inverted" + :href="job.new_issue_path"> + New issue + </a> + <a + v-if="job.retry_path" + class="js-retry-job btn btn-inverted-secondary" + :href="job.retry_path" + data-method="post" + rel="nofollow"> + Retry + </a> + </div> + <div class="block"> + <p + class="build-detail-row js-job-mr" + v-if="job.merge_request"> + <span + class="build-light-text"> + Merge Request: + </span> + <a :href="job.merge_request.path"> + !{{job.merge_request.iid}} + </a> + </p> + + <detail-row + class="js-job-duration" + v-if="job.duration" + title="Duration" + :value="duration" + /> + <detail-row + class="js-job-finished" + v-if="job.finished_at" + title="Finished" + :value="timeFormated(job.finished_at)" + /> + <detail-row + class="js-job-erased" + v-if="job.erased_at" + title="Erased" + :value="timeFormated(job.erased_at)" + /> + <detail-row + class="js-job-queued" + v-if="job.queued" + title="Queued" + :value="queued" + /> + <detail-row + class="js-job-runner" + v-if="job.runner" + title="Runner" + :value="runnerId" + /> + <detail-row + class="js-job-coverage" + v-if="job.coverage" + title="Coverage" + :value="coverage" + /> + <p + class="build-detail-row js-job-tags" + v-if="job.tags.length"> + <span + class="build-light-text"> + Tags: + </span> + <span + v-for="tag in job.tags" + key="tag" + class="label label-primary"> + {{tag}} + </span> + </p> + + <div + v-if="job.cancel_path" + class="btn-group prepend-top-5" + role="group"> + <a + class="js-cancel-job btn btn-sm btn-default" + :href="job.cancel_path" + data-method="post" + rel="nofollow"> + Cancel + </a> + </div> + </div> + </template> + <loading-icon + class="prepend-top-10" + v-if="isLoading" + size="2" + /> + </div> +</template> diff --git a/app/assets/javascripts/jobs/job_details_bundle.js b/app/assets/javascripts/jobs/job_details_bundle.js new file mode 100644 index 00000000000..939d17129de --- /dev/null +++ b/app/assets/javascripts/jobs/job_details_bundle.js @@ -0,0 +1,68 @@ +/* global Flash */ + +import Vue from 'vue'; +import JobMediator from './job_details_mediator'; +import jobHeader from './components/header.vue'; +import detailsBlock from './components/sidebar_details_block.vue'; + +document.addEventListener('DOMContentLoaded', () => { + const dataset = document.getElementById('js-job-details-vue').dataset; + const mediator = new JobMediator({ endpoint: dataset.endpoint }); + + mediator.fetchJob(); + + // Header + // eslint-disable-next-line no-new + new Vue({ + el: '#js-build-header-vue', + data() { + return { + mediator, + }; + }, + components: { + jobHeader, + }, + mounted() { + this.mediator.initBuildClass(); + }, + updated() { + // Wait for flash message to be appended + Vue.nextTick(() => { + if (this.mediator.build) { + this.mediator.build.verifyTopPosition(); + } + }); + }, + render(createElement) { + return createElement('job-header', { + props: { + isLoading: this.mediator.state.isLoading, + job: this.mediator.store.state.job, + }, + }); + }, + }); + + // Sidebar information block + // eslint-disable-next-line + new Vue({ + el: '#js-details-block-vue', + data() { + return { + mediator, + }; + }, + components: { + detailsBlock, + }, + render(createElement) { + return createElement('details-block', { + props: { + isLoading: this.mediator.state.isLoading, + job: this.mediator.store.state.job, + }, + }); + }, + }); +}); diff --git a/app/assets/javascripts/jobs/job_details_mediator.js b/app/assets/javascripts/jobs/job_details_mediator.js new file mode 100644 index 00000000000..063c52fac74 --- /dev/null +++ b/app/assets/javascripts/jobs/job_details_mediator.js @@ -0,0 +1,67 @@ +/* global Flash */ +/* global Build */ + +import Visibility from 'visibilityjs'; +import Poll from '../lib/utils/poll'; +import JobStore from './stores/job_store'; +import JobService from './services/job_service'; +import '../build'; + +export default class JobMediator { + constructor(options = {}) { + this.options = options; + + this.store = new JobStore(); + this.service = new JobService(options.endpoint); + + this.state = { + isLoading: false, + }; + } + + initBuildClass() { + this.build = new Build(); + } + + fetchJob() { + this.poll = new Poll({ + resource: this.service, + method: 'getJob', + successCallback: this.successCallback.bind(this), + errorCallback: this.errorCallback.bind(this), + }); + + if (!Visibility.hidden()) { + this.state.isLoading = true; + this.poll.makeRequest(); + } else { + this.getJob(); + } + + Visibility.change(() => { + if (!Visibility.hidden()) { + this.poll.restart(); + } else { + this.poll.stop(); + } + }); + } + + getJob() { + return this.service.getJob() + .then(response => this.successCallback(response)) + .catch(() => this.errorCallback()); + } + + successCallback(response) { + const data = response.json(); + this.state.isLoading = false; + this.store.storeJob(data); + } + + errorCallback() { + this.state.isLoading = false; + + return new Flash('An error occurred while fetching the job.'); + } +} diff --git a/app/assets/javascripts/jobs/services/job_service.js b/app/assets/javascripts/jobs/services/job_service.js new file mode 100644 index 00000000000..eaf1c6e500a --- /dev/null +++ b/app/assets/javascripts/jobs/services/job_service.js @@ -0,0 +1,14 @@ +import Vue from 'vue'; +import VueResource from 'vue-resource'; + +Vue.use(VueResource); + +export default class JobService { + constructor(endpoint) { + this.job = Vue.resource(endpoint); + } + + getJob() { + return this.job.get(); + } +} diff --git a/app/assets/javascripts/jobs/stores/job_store.js b/app/assets/javascripts/jobs/stores/job_store.js new file mode 100644 index 00000000000..766194b8387 --- /dev/null +++ b/app/assets/javascripts/jobs/stores/job_store.js @@ -0,0 +1,11 @@ +export default class JobStore { + constructor() { + this.state = { + job: {}, + }; + } + + storeJob(job = {}) { + this.state.job = job; + } +} diff --git a/app/assets/javascripts/lib/utils/datetime_utility.js b/app/assets/javascripts/lib/utils/datetime_utility.js index 40eadd9396c..54c0da3fc9c 100644 --- a/app/assets/javascripts/lib/utils/datetime_utility.js +++ b/app/assets/javascripts/lib/utils/datetime_utility.js @@ -146,3 +146,24 @@ window.dateFormat = dateFormat; }; })(window); }).call(window); + +/** + * Port of ruby helper time_interval_in_words. + * + * @param {Number} seconds + * @return {String} + */ +// eslint-disable-next-line import/prefer-default-export +export function timeIntervalInWords(intervalInSeconds) { + const secondsInteger = parseInt(intervalInSeconds, 10); + const minutes = Math.floor(secondsInteger / 60); + const seconds = secondsInteger - (minutes * 60); + let text = ''; + + if (minutes >= 1) { + text = `${minutes} ${gl.text.pluralize('minute', minutes)} ${seconds} ${gl.text.pluralize('second', seconds)}`; + } else { + text = `${seconds} ${gl.text.pluralize('second', seconds)}`; + } + return text; +} diff --git a/app/assets/javascripts/locale/de/app.js b/app/assets/javascripts/locale/de/app.js index 5f6d9f01bf7..e7d2b174405 100644 --- a/app/assets/javascripts/locale/de/app.js +++ b/app/assets/javascripts/locale/de/app.js @@ -1 +1 @@ -var locales = locales || {}; locales['de'] = {"domain":"app","locale_data":{"app":{"":{"Project-Id-Version":"gitlab 1.0.0","Report-Msgid-Bugs-To":"","PO-Revision-Date":"2017-05-09 13:44+0200","Language-Team":"German","Language":"de","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","Plural-Forms":"nplurals=2; plural=n != 1;","Last-Translator":"","X-Generator":"Poedit 2.0.1","lang":"de","domain":"app","plural_forms":"nplurals=2; plural=n != 1;"},"About auto deploy":[""],"Activity":[""],"Add Changelog":[""],"Add Contribution guide":[""],"Add License":[""],"Add an SSH key to your profile to pull or push via SSH.":[""],"Add new directory":[""],"Archived project! Repository is read-only":[""],"Are you sure you want to delete this pipeline schedule?":[""],"Branch":["",""],"Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}":[""],"Branches":[""],"ByAuthor|by":["Von"],"CI configuration":[""],"Cancel":[""],"Changelog":[""],"Charts":[""],"CiStatusLabel|canceled":[""],"CiStatusLabel|created":[""],"CiStatusLabel|failed":[""],"CiStatusLabel|manual action":[""],"CiStatusLabel|passed":[""],"CiStatusLabel|passed with warnings":[""],"CiStatusLabel|pending":[""],"CiStatusLabel|skipped":[""],"CiStatusLabel|waiting for manual action":[""],"CiStatusText|blocked":[""],"CiStatusText|canceled":[""],"CiStatusText|created":[""],"CiStatusText|failed":[""],"CiStatusText|manual":[""],"CiStatusText|passed":[""],"CiStatusText|pending":[""],"CiStatusText|skipped":[""],"CiStatus|running":[""],"Commit":["Commit","Commits"],"CommitMessage|Add %{file_name}":["Commit\u0000Commits"],"Commits":["Commit\u0000Commits"],"Commits|History":["Commit\u0000Commits"],"Compare":[""],"Contribution guide":[""],"Contributors":[""],"Copy URL to clipboard":[""],"Copy commit SHA to clipboard":[""],"Create New Directory":[""],"Create directory":[""],"Create empty bare repository":[""],"Create merge request":["Zugehörige Merge Requests"],"CreateNewFork|Fork":[""],"Cron Timezone":[""],"Custom notification events":[""],"Custom notification levels are the same as participating levels. With custom notification levels you will also receive notifications for select events. To find out more, check out %{notification_link}.":[""],"Cycle Analytics":[""],"Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project.":["Cycle Analytics liefern einen Überblick darüber, wie viel Zeit in Ihrem Projekt von einer Idee bis zum Produktivdeployment vergeht."],"CycleAnalyticsStage|Code":["Code"],"CycleAnalyticsStage|Issue":["Issue"],"CycleAnalyticsStage|Plan":["Planung"],"CycleAnalyticsStage|Production":["Produktiv"],"CycleAnalyticsStage|Review":["Review"],"CycleAnalyticsStage|Staging":["Staging"],"CycleAnalyticsStage|Test":["Test"],"Delete":[""],"Deploy":["Deployment","Deployments"],"Description":[""],"Directory name":[""],"Don't show again":[""],"Download tar":[""],"Download tar.bz2":[""],"Download tar.gz":[""],"Download zip":[""],"DownloadArtifacts|Download":[""],"DownloadSource|Download":[""],"Edit":[""],"Edit Pipeline Schedule %{id}":[""],"Failed to change the owner":[""],"Failed to remove the pipeline schedule":[""],"Files":[""],"Filter":[""],"Find by path":[""],"Find file":[""],"FirstPushedBy|First":["Erster"],"FirstPushedBy|pushed by":["gepusht von"],"ForkedFromProjectPath|Forked from":[""],"Forks":[""],"From issue creation until deploy to production":["Vom Anlegen des Issues bis zum Produktivdeployment"],"From merge request merge until deploy to production":["Vom Merge Request bis zum Produktivdeployment"],"Go to your fork":[""],"GoToYourFork|Fork":[""],"Home":[""],"Housekeeping successfully started":[""],"Import repository":[""],"Interval Pattern":[""],"Introducing Cycle Analytics":["Was sind Cycle Analytics?"],"LFSStatus|Disabled":[""],"LFSStatus|Enabled":[""],"Last %d day":["Letzter %d Tag","Letzten %d Tage"],"Last Pipeline":[""],"Last Update":[""],"Last commit":[""],"Leave group":[""],"Leave project":[""],"Limited to showing %d event at most":["Eingeschränkt auf maximal %d Ereignis","Eingeschränkt auf maximal %d Ereignisse"],"Median":["Median"],"MissingSSHKeyWarningLink|add an SSH key":[""],"New Issue":["Neues Issue","Neue Issues"],"New Pipeline Schedule":[""],"New branch":[""],"New directory":[""],"New file":[""],"New issue":["Neues Issue\u0000Neue Issues"],"New merge request":[""],"New snippet":[""],"New tag":[""],"No repository":[""],"No schedules":[""],"Not available":["Nicht verfügbar"],"Not enough data":["Nicht genügend Daten"],"Notification events":[""],"NotificationEvent|Close issue":[""],"NotificationEvent|Close merge request":[""],"NotificationEvent|Failed pipeline":[""],"NotificationEvent|Merge merge request":[""],"NotificationEvent|New issue":[""],"NotificationEvent|New merge request":[""],"NotificationEvent|New note":[""],"NotificationEvent|Reassign issue":[""],"NotificationEvent|Reassign merge request":[""],"NotificationEvent|Reopen issue":[""],"NotificationEvent|Successful pipeline":[""],"NotificationLevel|Custom":[""],"NotificationLevel|Disabled":[""],"NotificationLevel|Global":[""],"NotificationLevel|On mention":[""],"NotificationLevel|Participate":[""],"NotificationLevel|Watch":[""],"OpenedNDaysAgo|Opened":["Erstellt"],"Owner":[""],"Pipeline Health":["Pipeline Kennzahlen"],"Pipeline Schedule":[""],"Pipeline Schedules":[""],"PipelineSchedules|Activated":[""],"PipelineSchedules|Active":[""],"PipelineSchedules|All":[""],"PipelineSchedules|Inactive":[""],"PipelineSchedules|Next Run":[""],"PipelineSchedules|None":[""],"PipelineSchedules|Provide a short description for this pipeline":[""],"PipelineSchedules|Take ownership":[""],"PipelineSchedules|Target":[""],"Project '%{project_name}' queued for deletion.":[""],"Project '%{project_name}' was successfully created.":[""],"Project '%{project_name}' was successfully updated.":[""],"Project '%{project_name}' will be deleted.":[""],"Project access must be granted explicitly to each user.":[""],"Project export could not be deleted.":[""],"Project export has been deleted.":[""],"Project export link has expired. Please generate a new export from your project settings.":[""],"Project export started. A download link will be sent by email.":[""],"Project home":[""],"ProjectFeature|Disabled":[""],"ProjectFeature|Everyone with access":[""],"ProjectFeature|Only team members":[""],"ProjectFileTree|Name":[""],"ProjectLastActivity|Never":[""],"ProjectLifecycle|Stage":["Phase"],"ProjectNetworkGraph|Graph":[""],"Read more":["Mehr"],"Readme":["Mehr"],"RefSwitcher|Branches":[""],"RefSwitcher|Tags":[""],"Related Commits":["Zugehörige Commits"],"Related Deployed Jobs":["Zugehörige Deploymentjobs"],"Related Issues":["Zugehörige Issues"],"Related Jobs":["Zugehörige Jobs"],"Related Merge Requests":["Zugehörige Merge Requests"],"Related Merged Requests":["Zugehörige abgeschlossene Merge Requests"],"Remind later":[""],"Remove project":[""],"Request Access":[""],"Save pipeline schedule":[""],"Schedule a new pipeline":[""],"Search branches and tags":[""],"Select Archive Format":[""],"Select a timezone":[""],"Select target branch":[""],"Set a password on your account to pull or push via %{protocol}":[""],"Set up CI":[""],"Set up Koding":[""],"Set up auto deploy":[""],"SetPasswordToCloneLink|set a password":[""],"Showing %d event":["Zeige %d Ereignis","Zeige %d Ereignisse"],"Source code":[""],"StarProject|Star":[""],"Switch branch/tag":[""],"Tag":["",""],"Tags":[""],"Target Branch":[""],"The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request.":["Die Code-Phase stellt die Zeit vom ersten Commit bis zum Erstellen eines Merge Requests dar. Sobald Sie Ihren ersten Merge Request anlegen, werden dessen Daten automatisch ergänzt."],"The collection of events added to the data gathered for that stage.":["Ereignisse, die für diese Phase ausgewertet wurden."],"The fork relationship has been removed.":[""],"The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage.":["Die Issue-Phase stellt die Zeit vom Anlegen eines Issues bis zum Zuweisen eines Meilensteins oder Hinzufügen zum Issue Board dar. Erstellen Sie einen Issue, damit dessen Daten hier erscheinen."],"The phase of the development lifecycle.":["Die Phase im Entwicklungsprozess."],"The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit.":["Die Planungsphase stellt die Zeit von der vorherigen Phase bis zum Pushen des ersten Commits dar. Sobald Sie den ersten Commit pushen, werden dessen Daten hier erscheinen."],"The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle.":["Die Produktiv-Phase stellt die Gesamtzeit vom Anlegen eines Issues bis zum Deployment auf dem Produktivsystem dar. Sobald Sie den vollständigen Entwicklungszyklus von einer Idee bis zum Produktivdeployment durchlaufen haben, erscheinen die zugehörigen Daten hier."],"The project can be accessed by any logged in user.":[""],"The project can be accessed without any authentication.":[""],"The repository for this project does not exist.":[""],"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.":["Die Review-Phase stellt die Zeit vom Anlegen eines Merge Requests bis zum Mergen dar. Sobald Sie Ihren ersten Merge Request abschließen, werden dessen Daten hier automatisch angezeigt."],"The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time.":["Die Staging-Phase stellt die Zeit zwischen Mergen eines Merge Requests und dem Produktivdeployment dar. Sobald Sie das erste Produktivdeployment durchgeführt haben, werden dessen Daten hier automatisch angezeigt."],"The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running.":["Die Test-Phase stellt die Zeit dar, die GitLab CI benötigt um die Pipelines von Merge Requests abzuarbeiten. Sobald die erste Pipeline abgeschlossen ist, werden deren Daten hier automatisch angezeigt."],"The time taken by each data entry gathered by that stage.":["Zeit die für das jeweilige Ereignis in der Phase ermittelt wurde."],"The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6.":["Der mittlere aller erfassten Werte. Zum Beispiel ist für 3, 5, 9 der Median 5. Bei 3, 5, 7, 8 ist der Median (5+7)/2 = 6."],"This means you can not push code until you create an empty repository or import existing one.":[""],"Time before an issue gets scheduled":["Zeit bis ein Issue geplant wird"],"Time before an issue starts implementation":["Zeit bis die Implementierung für ein Issue beginnt"],"Time between merge request creation and merge/close":["Zeit zwischen Anlegen und Mergen/Schließen eines Merge Requests"],"Time until first merge request":["Zeit bis zum ersten Merge Request"],"Timeago|%s days ago":["Tag\u0000Tage"],"Timeago|%s days remaining":["Tag\u0000Tage"],"Timeago|%s hours remaining":[""],"Timeago|%s minutes ago":[""],"Timeago|%s minutes remaining":[""],"Timeago|%s months ago":[""],"Timeago|%s months remaining":[""],"Timeago|%s seconds remaining":[""],"Timeago|%s weeks ago":[""],"Timeago|%s weeks remaining":[""],"Timeago|%s years ago":[""],"Timeago|%s years remaining":[""],"Timeago|1 day remaining":["Tag\u0000Tage"],"Timeago|1 hour remaining":[""],"Timeago|1 minute remaining":[""],"Timeago|1 month remaining":[""],"Timeago|1 week remaining":[""],"Timeago|1 year remaining":[""],"Timeago|Past due":[""],"Timeago|a day ago":["Tag\u0000Tage"],"Timeago|a month ago":[""],"Timeago|a week ago":[""],"Timeago|a while":[""],"Timeago|a year ago":[""],"Timeago|about %s hours ago":[""],"Timeago|about a minute ago":[""],"Timeago|about an hour ago":[""],"Timeago|in %s days":["Tag\u0000Tage"],"Timeago|in %s hours":[""],"Timeago|in %s minutes":[""],"Timeago|in %s months":[""],"Timeago|in %s seconds":[""],"Timeago|in %s weeks":[""],"Timeago|in %s years":[""],"Timeago|in 1 day":["Tag\u0000Tage"],"Timeago|in 1 hour":[""],"Timeago|in 1 minute":[""],"Timeago|in 1 month":[""],"Timeago|in 1 week":[""],"Timeago|in 1 year":[""],"Timeago|less than a minute ago":[""],"Time|hr":["h","h"],"Time|min":["min","min"],"Time|s":["s"],"Total Time":["Gesamtzeit"],"Total test time for all commits/merges":["Gesamte Testlaufzeit für alle Commits/Merges"],"Unstar":[""],"Upload New File":[""],"Upload file":[""],"Use your global notification setting":[""],"VisibilityLevel|Internal":[""],"VisibilityLevel|Private":[""],"VisibilityLevel|Public":[""],"Want to see the data? Please ask an administrator for access.":["Um diese Daten einsehen zu können, wenden Sie sich bitte an Ihren Administrator."],"We don't have enough data to show this stage.":["Es liegen nicht genügend Daten vor, um diese Phase anzuzeigen."],"Withdraw Access Request":[""],"You are going to remove %{project_name_with_namespace}.\\nRemoved project CANNOT be restored!\\nAre you ABSOLUTELY sure?":[""],"You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?":[""],"You are going to transfer %{project_name_with_namespace} to another owner. Are you ABSOLUTELY sure?":[""],"You can only add files when you are on a branch":[""],"You must sign in to star a project":[""],"You need permission.":["Sie benötigen Zugriffsrechte."],"You will not get any notifications via email":[""],"You will only receive notifications for the events you choose":[""],"You will only receive notifications for threads you have participated in":[""],"You will receive notifications for any activity":[""],"You will receive notifications only for comments in which you were @mentioned":[""],"You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account":[""],"You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile":[""],"Your name":[""],"committed":[""],"day":["Tag","Tage"],"notification emails":[""]}}};
\ No newline at end of file +var locales = locales || {}; locales['de'] = {"domain":"app","locale_data":{"app":{"":{"Project-Id-Version":"gitlab 1.0.0","Report-Msgid-Bugs-To":"","PO-Revision-Date":"2017-05-09 13:44+0200","Language-Team":"German","Language":"de","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","Plural-Forms":"nplurals=2; plural=n != 1;","Last-Translator":"","X-Generator":"Poedit 2.0.1","lang":"de","domain":"app","plural_forms":"nplurals=2; plural=n != 1;"},"Are you sure you want to delete this pipeline schedule?":[""],"ByAuthor|by":["Von"],"Cancel":[""],"Commit":["Commit","Commits"],"Cron Timezone":[""],"Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project.":["Cycle Analytics liefern einen Überblick darüber, wie viel Zeit in Ihrem Projekt von einer Idee bis zum Produktivdeployment vergeht."],"CycleAnalyticsStage|Code":["Code"],"CycleAnalyticsStage|Issue":["Issue"],"CycleAnalyticsStage|Plan":["Planung"],"CycleAnalyticsStage|Production":["Produktiv"],"CycleAnalyticsStage|Review":["Review"],"CycleAnalyticsStage|Staging":["Staging"],"CycleAnalyticsStage|Test":["Test"],"Delete":[""],"Deploy":["Deployment","Deployments"],"Description":[""],"Edit":[""],"Edit Pipeline Schedule %{id}":[""],"Failed to change the owner":[""],"Failed to remove the pipeline schedule":[""],"Filter":[""],"FirstPushedBy|First":["Erster"],"FirstPushedBy|pushed by":["gepusht von"],"From issue creation until deploy to production":["Vom Anlegen des Issues bis zum Produktivdeployment"],"From merge request merge until deploy to production":["Vom Merge Request bis zum Produktivdeployment"],"Interval Pattern":[""],"Introducing Cycle Analytics":["Was sind Cycle Analytics?"],"Last %d day":["Letzter %d Tag","Letzten %d Tage"],"Last Pipeline":[""],"Limited to showing %d event at most":["Eingeschränkt auf maximal %d Ereignis","Eingeschränkt auf maximal %d Ereignisse"],"Median":["Median"],"New Issue":["Neues Issue","Neue Issues"],"New Pipeline Schedule":[""],"No schedules":[""],"Not available":["Nicht verfügbar"],"Not enough data":["Nicht genügend Daten"],"OpenedNDaysAgo|Opened":["Erstellt"],"Owner":[""],"Pipeline Health":["Pipeline Kennzahlen"],"Pipeline Schedule":[""],"Pipeline Schedules":[""],"PipelineSchedules|Activated":[""],"PipelineSchedules|Active":[""],"PipelineSchedules|All":[""],"PipelineSchedules|Inactive":[""],"PipelineSchedules|Next Run":[""],"PipelineSchedules|None":[""],"PipelineSchedules|Provide a short description for this pipeline":[""],"PipelineSchedules|Take ownership":[""],"PipelineSchedules|Target":[""],"ProjectLifecycle|Stage":["Phase"],"Read more":["Mehr"],"Related Commits":["Zugehörige Commits"],"Related Deployed Jobs":["Zugehörige Deploymentjobs"],"Related Issues":["Zugehörige Issues"],"Related Jobs":["Zugehörige Jobs"],"Related Merge Requests":["Zugehörige Merge Requests"],"Related Merged Requests":["Zugehörige abgeschlossene Merge Requests"],"Save pipeline schedule":[""],"Schedule a new pipeline":[""],"Select a timezone":[""],"Select target branch":[""],"Showing %d event":["Zeige %d Ereignis","Zeige %d Ereignisse"],"Target Branch":[""],"The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request.":["Die Code-Phase stellt die Zeit vom ersten Commit bis zum Erstellen eines Merge Requests dar. Sobald Sie Ihren ersten Merge Request anlegen, werden dessen Daten automatisch ergänzt."],"The collection of events added to the data gathered for that stage.":["Ereignisse, die für diese Phase ausgewertet wurden."],"The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage.":["Die Issue-Phase stellt die Zeit vom Anlegen eines Issues bis zum Zuweisen eines Meilensteins oder Hinzufügen zum Issue Board dar. Erstellen Sie einen Issue, damit dessen Daten hier erscheinen."],"The phase of the development lifecycle.":["Die Phase im Entwicklungsprozess."],"The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit.":["Die Planungsphase stellt die Zeit von der vorherigen Phase bis zum Pushen des ersten Commits dar. Sobald Sie den ersten Commit pushen, werden dessen Daten hier erscheinen."],"The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle.":["Die Produktiv-Phase stellt die Gesamtzeit vom Anlegen eines Issues bis zum Deployment auf dem Produktivsystem dar. Sobald Sie den vollständigen Entwicklungszyklus von einer Idee bis zum Produktivdeployment durchlaufen haben, erscheinen die zugehörigen Daten hier."],"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.":["Die Review-Phase stellt die Zeit vom Anlegen eines Merge Requests bis zum Mergen dar. Sobald Sie Ihren ersten Merge Request abschließen, werden dessen Daten hier automatisch angezeigt."],"The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time.":["Die Staging-Phase stellt die Zeit zwischen Mergen eines Merge Requests und dem Produktivdeployment dar. Sobald Sie das erste Produktivdeployment durchgeführt haben, werden dessen Daten hier automatisch angezeigt."],"The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running.":["Die Test-Phase stellt die Zeit dar, die GitLab CI benötigt um die Pipelines von Merge Requests abzuarbeiten. Sobald die erste Pipeline abgeschlossen ist, werden deren Daten hier automatisch angezeigt."],"The time taken by each data entry gathered by that stage.":["Zeit die für das jeweilige Ereignis in der Phase ermittelt wurde."],"The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6.":["Der mittlere aller erfassten Werte. Zum Beispiel ist für 3, 5, 9 der Median 5. Bei 3, 5, 7, 8 ist der Median (5+7)/2 = 6."],"Time before an issue gets scheduled":["Zeit bis ein Issue geplant wird"],"Time before an issue starts implementation":["Zeit bis die Implementierung für ein Issue beginnt"],"Time between merge request creation and merge/close":["Zeit zwischen Anlegen und Mergen/Schließen eines Merge Requests"],"Time until first merge request":["Zeit bis zum ersten Merge Request"],"Time|hr":["h","h"],"Time|min":["min","min"],"Time|s":["s"],"Total Time":["Gesamtzeit"],"Total test time for all commits/merges":["Gesamte Testlaufzeit für alle Commits/Merges"],"Want to see the data? Please ask an administrator for access.":["Um diese Daten einsehen zu können, wenden Sie sich bitte an Ihren Administrator."],"We don't have enough data to show this stage.":["Es liegen nicht genügend Daten vor, um diese Phase anzuzeigen."],"You need permission.":["Sie benötigen Zugriffsrechte."],"day":["Tag","Tage"]}}};
\ No newline at end of file diff --git a/app/assets/javascripts/locale/en/app.js b/app/assets/javascripts/locale/en/app.js index 774dc2f094f..0bb76c80b7a 100644 --- a/app/assets/javascripts/locale/en/app.js +++ b/app/assets/javascripts/locale/en/app.js @@ -1 +1 @@ -var locales = locales || {}; locales['en'] = {"domain":"app","locale_data":{"app":{"":{"Project-Id-Version":"gitlab 1.0.0","Report-Msgid-Bugs-To":"","PO-Revision-Date":"2017-04-12 22:36-0500","Last-Translator":"FULL NAME <EMAIL@ADDRESS>","Language-Team":"English","Language":"en","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","Plural-Forms":"nplurals=2; plural=n != 1;","lang":"en","domain":"app","plural_forms":"nplurals=2; plural=n != 1;"},"About auto deploy":[""],"Activity":[""],"Add Changelog":[""],"Add Contribution guide":[""],"Add License":[""],"Add an SSH key to your profile to pull or push via SSH.":[""],"Add new directory":[""],"Archived project! Repository is read-only":[""],"Are you sure you want to delete this pipeline schedule?":[""],"Branch":["",""],"Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}":[""],"Branches":[""],"ByAuthor|by":[""],"CI configuration":[""],"Cancel":[""],"Changelog":[""],"Charts":[""],"CiStatusLabel|canceled":[""],"CiStatusLabel|created":[""],"CiStatusLabel|failed":[""],"CiStatusLabel|manual action":[""],"CiStatusLabel|passed":[""],"CiStatusLabel|passed with warnings":[""],"CiStatusLabel|pending":[""],"CiStatusLabel|skipped":[""],"CiStatusLabel|waiting for manual action":[""],"CiStatusText|blocked":[""],"CiStatusText|canceled":[""],"CiStatusText|created":[""],"CiStatusText|failed":[""],"CiStatusText|manual":[""],"CiStatusText|passed":[""],"CiStatusText|pending":[""],"CiStatusText|skipped":[""],"CiStatus|running":[""],"Commit":["",""],"CommitMessage|Add %{file_name}":[""],"Commits":[""],"Commits|History":[""],"Compare":[""],"Contribution guide":[""],"Contributors":[""],"Copy URL to clipboard":[""],"Copy commit SHA to clipboard":[""],"Create New Directory":[""],"Create directory":[""],"Create empty bare repository":[""],"Create merge request":[""],"CreateNewFork|Fork":[""],"Cron Timezone":[""],"Custom notification events":[""],"Custom notification levels are the same as participating levels. With custom notification levels you will also receive notifications for select events. To find out more, check out %{notification_link}.":[""],"Cycle Analytics":[""],"Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project.":[""],"CycleAnalyticsStage|Code":[""],"CycleAnalyticsStage|Issue":[""],"CycleAnalyticsStage|Plan":[""],"CycleAnalyticsStage|Production":[""],"CycleAnalyticsStage|Review":[""],"CycleAnalyticsStage|Staging":[""],"CycleAnalyticsStage|Test":[""],"Delete":[""],"Deploy":["",""],"Description":[""],"Directory name":[""],"Don't show again":[""],"Download tar":[""],"Download tar.bz2":[""],"Download tar.gz":[""],"Download zip":[""],"DownloadArtifacts|Download":[""],"DownloadSource|Download":[""],"Edit":[""],"Edit Pipeline Schedule %{id}":[""],"Failed to change the owner":[""],"Failed to remove the pipeline schedule":[""],"Files":[""],"Filter":[""],"Find by path":[""],"Find file":[""],"FirstPushedBy|First":[""],"FirstPushedBy|pushed by":[""],"ForkedFromProjectPath|Forked from":[""],"Forks":[""],"From issue creation until deploy to production":[""],"From merge request merge until deploy to production":[""],"Go to your fork":[""],"GoToYourFork|Fork":[""],"Home":[""],"Housekeeping successfully started":[""],"Import repository":[""],"Interval Pattern":[""],"Introducing Cycle Analytics":[""],"LFSStatus|Disabled":[""],"LFSStatus|Enabled":[""],"Last %d day":["",""],"Last Pipeline":[""],"Last Update":[""],"Last commit":[""],"Leave group":[""],"Leave project":[""],"Limited to showing %d event at most":["",""],"Median":[""],"MissingSSHKeyWarningLink|add an SSH key":[""],"New Issue":["",""],"New Pipeline Schedule":[""],"New branch":[""],"New directory":[""],"New file":[""],"New issue":[""],"New merge request":[""],"New snippet":[""],"New tag":[""],"No repository":[""],"No schedules":[""],"Not available":[""],"Not enough data":[""],"Notification events":[""],"NotificationEvent|Close issue":[""],"NotificationEvent|Close merge request":[""],"NotificationEvent|Failed pipeline":[""],"NotificationEvent|Merge merge request":[""],"NotificationEvent|New issue":[""],"NotificationEvent|New merge request":[""],"NotificationEvent|New note":[""],"NotificationEvent|Reassign issue":[""],"NotificationEvent|Reassign merge request":[""],"NotificationEvent|Reopen issue":[""],"NotificationEvent|Successful pipeline":[""],"NotificationLevel|Custom":[""],"NotificationLevel|Disabled":[""],"NotificationLevel|Global":[""],"NotificationLevel|On mention":[""],"NotificationLevel|Participate":[""],"NotificationLevel|Watch":[""],"OpenedNDaysAgo|Opened":[""],"Owner":[""],"Pipeline Health":[""],"Pipeline Schedule":[""],"Pipeline Schedules":[""],"PipelineSchedules|Activated":[""],"PipelineSchedules|Active":[""],"PipelineSchedules|All":[""],"PipelineSchedules|Inactive":[""],"PipelineSchedules|Next Run":[""],"PipelineSchedules|None":[""],"PipelineSchedules|Provide a short description for this pipeline":[""],"PipelineSchedules|Take ownership":[""],"PipelineSchedules|Target":[""],"Project '%{project_name}' queued for deletion.":[""],"Project '%{project_name}' was successfully created.":[""],"Project '%{project_name}' was successfully updated.":[""],"Project '%{project_name}' will be deleted.":[""],"Project access must be granted explicitly to each user.":[""],"Project export could not be deleted.":[""],"Project export has been deleted.":[""],"Project export link has expired. Please generate a new export from your project settings.":[""],"Project export started. A download link will be sent by email.":[""],"Project home":[""],"ProjectFeature|Disabled":[""],"ProjectFeature|Everyone with access":[""],"ProjectFeature|Only team members":[""],"ProjectFileTree|Name":[""],"ProjectLastActivity|Never":[""],"ProjectLifecycle|Stage":[""],"ProjectNetworkGraph|Graph":[""],"Read more":[""],"Readme":[""],"RefSwitcher|Branches":[""],"RefSwitcher|Tags":[""],"Related Commits":[""],"Related Deployed Jobs":[""],"Related Issues":[""],"Related Jobs":[""],"Related Merge Requests":[""],"Related Merged Requests":[""],"Remind later":[""],"Remove project":[""],"Request Access":[""],"Save pipeline schedule":[""],"Schedule a new pipeline":[""],"Search branches and tags":[""],"Select Archive Format":[""],"Select a timezone":[""],"Select target branch":[""],"Set a password on your account to pull or push via %{protocol}":[""],"Set up CI":[""],"Set up Koding":[""],"Set up auto deploy":[""],"SetPasswordToCloneLink|set a password":[""],"Showing %d event":["",""],"Source code":[""],"StarProject|Star":[""],"Switch branch/tag":[""],"Tag":["",""],"Tags":[""],"Target Branch":[""],"The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request.":[""],"The collection of events added to the data gathered for that stage.":[""],"The fork relationship has been removed.":[""],"The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage.":[""],"The phase of the development lifecycle.":[""],"The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit.":[""],"The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle.":[""],"The project can be accessed by any logged in user.":[""],"The project can be accessed without any authentication.":[""],"The repository for this project does not exist.":[""],"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.":[""],"The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time.":[""],"The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running.":[""],"The time taken by each data entry gathered by that stage.":[""],"The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6.":[""],"This means you can not push code until you create an empty repository or import existing one.":[""],"Time before an issue gets scheduled":[""],"Time before an issue starts implementation":[""],"Time between merge request creation and merge/close":[""],"Time until first merge request":[""],"Timeago|%s days ago":[""],"Timeago|%s days remaining":[""],"Timeago|%s hours remaining":[""],"Timeago|%s minutes ago":[""],"Timeago|%s minutes remaining":[""],"Timeago|%s months ago":[""],"Timeago|%s months remaining":[""],"Timeago|%s seconds remaining":[""],"Timeago|%s weeks ago":[""],"Timeago|%s weeks remaining":[""],"Timeago|%s years ago":[""],"Timeago|%s years remaining":[""],"Timeago|1 day remaining":[""],"Timeago|1 hour remaining":[""],"Timeago|1 minute remaining":[""],"Timeago|1 month remaining":[""],"Timeago|1 week remaining":[""],"Timeago|1 year remaining":[""],"Timeago|Past due":[""],"Timeago|a day ago":[""],"Timeago|a month ago":[""],"Timeago|a week ago":[""],"Timeago|a while":[""],"Timeago|a year ago":[""],"Timeago|about %s hours ago":[""],"Timeago|about a minute ago":[""],"Timeago|about an hour ago":[""],"Timeago|in %s days":[""],"Timeago|in %s hours":[""],"Timeago|in %s minutes":[""],"Timeago|in %s months":[""],"Timeago|in %s seconds":[""],"Timeago|in %s weeks":[""],"Timeago|in %s years":[""],"Timeago|in 1 day":[""],"Timeago|in 1 hour":[""],"Timeago|in 1 minute":[""],"Timeago|in 1 month":[""],"Timeago|in 1 week":[""],"Timeago|in 1 year":[""],"Timeago|less than a minute ago":[""],"Time|hr":["",""],"Time|min":["",""],"Time|s":[""],"Total Time":[""],"Total test time for all commits/merges":[""],"Unstar":[""],"Upload New File":[""],"Upload file":[""],"Use your global notification setting":[""],"VisibilityLevel|Internal":[""],"VisibilityLevel|Private":[""],"VisibilityLevel|Public":[""],"Want to see the data? Please ask an administrator for access.":[""],"We don't have enough data to show this stage.":[""],"Withdraw Access Request":[""],"You are going to remove %{project_name_with_namespace}.\\nRemoved project CANNOT be restored!\\nAre you ABSOLUTELY sure?":[""],"You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?":[""],"You are going to transfer %{project_name_with_namespace} to another owner. Are you ABSOLUTELY sure?":[""],"You can only add files when you are on a branch":[""],"You must sign in to star a project":[""],"You need permission.":[""],"You will not get any notifications via email":[""],"You will only receive notifications for the events you choose":[""],"You will only receive notifications for threads you have participated in":[""],"You will receive notifications for any activity":[""],"You will receive notifications only for comments in which you were @mentioned":[""],"You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account":[""],"You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile":[""],"Your name":[""],"committed":[""],"day":["",""],"notification emails":[""]}}};
\ No newline at end of file +var locales = locales || {}; locales['en'] = {"domain":"app","locale_data":{"app":{"":{"Project-Id-Version":"gitlab 1.0.0","Report-Msgid-Bugs-To":"","PO-Revision-Date":"2017-04-12 22:36-0500","Last-Translator":"FULL NAME <EMAIL@ADDRESS>","Language-Team":"English","Language":"en","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","Plural-Forms":"nplurals=2; plural=n != 1;","lang":"en","domain":"app","plural_forms":"nplurals=2; plural=n != 1;"},"Are you sure you want to delete this pipeline schedule?":[""],"ByAuthor|by":[""],"Cancel":[""],"Commit":["",""],"Cron Timezone":[""],"Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project.":[""],"CycleAnalyticsStage|Code":[""],"CycleAnalyticsStage|Issue":[""],"CycleAnalyticsStage|Plan":[""],"CycleAnalyticsStage|Production":[""],"CycleAnalyticsStage|Review":[""],"CycleAnalyticsStage|Staging":[""],"CycleAnalyticsStage|Test":[""],"Delete":[""],"Deploy":["",""],"Description":[""],"Edit":[""],"Edit Pipeline Schedule %{id}":[""],"Failed to change the owner":[""],"Failed to remove the pipeline schedule":[""],"Filter":[""],"FirstPushedBy|First":[""],"FirstPushedBy|pushed by":[""],"From issue creation until deploy to production":[""],"From merge request merge until deploy to production":[""],"Interval Pattern":[""],"Introducing Cycle Analytics":[""],"Last %d day":["",""],"Last Pipeline":[""],"Limited to showing %d event at most":["",""],"Median":[""],"New Issue":["",""],"New Pipeline Schedule":[""],"No schedules":[""],"Not available":[""],"Not enough data":[""],"OpenedNDaysAgo|Opened":[""],"Owner":[""],"Pipeline Health":[""],"Pipeline Schedule":[""],"Pipeline Schedules":[""],"PipelineSchedules|Activated":[""],"PipelineSchedules|Active":[""],"PipelineSchedules|All":[""],"PipelineSchedules|Inactive":[""],"PipelineSchedules|Next Run":[""],"PipelineSchedules|None":[""],"PipelineSchedules|Provide a short description for this pipeline":[""],"PipelineSchedules|Take ownership":[""],"PipelineSchedules|Target":[""],"ProjectLifecycle|Stage":[""],"Read more":[""],"Related Commits":[""],"Related Deployed Jobs":[""],"Related Issues":[""],"Related Jobs":[""],"Related Merge Requests":[""],"Related Merged Requests":[""],"Save pipeline schedule":[""],"Schedule a new pipeline":[""],"Select a timezone":[""],"Select target branch":[""],"Showing %d event":["",""],"Target Branch":[""],"The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request.":[""],"The collection of events added to the data gathered for that stage.":[""],"The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage.":[""],"The phase of the development lifecycle.":[""],"The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit.":[""],"The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle.":[""],"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.":[""],"The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time.":[""],"The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running.":[""],"The time taken by each data entry gathered by that stage.":[""],"The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6.":[""],"Time before an issue gets scheduled":[""],"Time before an issue starts implementation":[""],"Time between merge request creation and merge/close":[""],"Time until first merge request":[""],"Time|hr":["",""],"Time|min":["",""],"Time|s":[""],"Total Time":[""],"Total test time for all commits/merges":[""],"Want to see the data? Please ask an administrator for access.":[""],"We don't have enough data to show this stage.":[""],"You need permission.":[""],"day":["",""]}}};
\ No newline at end of file diff --git a/app/assets/javascripts/locale/es/app.js b/app/assets/javascripts/locale/es/app.js index 0fbe4ada8fa..6977625f4d8 100644 --- a/app/assets/javascripts/locale/es/app.js +++ b/app/assets/javascripts/locale/es/app.js @@ -1 +1 @@ -var locales = locales || {}; locales['es'] = {"domain":"app","locale_data":{"app":{"":{"Project-Id-Version":"gitlab 1.0.0","Report-Msgid-Bugs-To":"","PO-Revision-Date":"2017-05-20 22:37-0500","Language-Team":"Spanish","Language":"es","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","Plural-Forms":"nplurals=2; plural=n != 1;","Last-Translator":"","X-Generator":"Poedit 2.0.1","lang":"es","domain":"app","plural_forms":"nplurals=2; plural=n != 1;"},"About auto deploy":[""],"Activity":[""],"Add Changelog":[""],"Add Contribution guide":[""],"Add License":[""],"Add an SSH key to your profile to pull or push via SSH.":[""],"Add new directory":[""],"Archived project! Repository is read-only":[""],"Are you sure you want to delete this pipeline schedule?":[""],"Branch":["",""],"Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}":[""],"Branches":[""],"ByAuthor|by":["por"],"CI configuration":[""],"Cancel":[""],"Changelog":[""],"Charts":[""],"CiStatusLabel|canceled":[""],"CiStatusLabel|created":[""],"CiStatusLabel|failed":[""],"CiStatusLabel|manual action":[""],"CiStatusLabel|passed":[""],"CiStatusLabel|passed with warnings":[""],"CiStatusLabel|pending":[""],"CiStatusLabel|skipped":[""],"CiStatusLabel|waiting for manual action":[""],"CiStatusText|blocked":[""],"CiStatusText|canceled":[""],"CiStatusText|created":[""],"CiStatusText|failed":[""],"CiStatusText|manual":[""],"CiStatusText|passed":[""],"CiStatusText|pending":[""],"CiStatusText|skipped":[""],"CiStatus|running":[""],"Commit":["Cambio","Cambios"],"CommitMessage|Add %{file_name}":["Cambio\u0000Cambios"],"Commits":["Cambio\u0000Cambios"],"Commits|History":["Cambio\u0000Cambios"],"Compare":[""],"Contribution guide":[""],"Contributors":[""],"Copy URL to clipboard":[""],"Copy commit SHA to clipboard":[""],"Create New Directory":[""],"Create directory":[""],"Create empty bare repository":[""],"Create merge request":["Solicitudes de fusión Relacionadas"],"CreateNewFork|Fork":[""],"Cron Timezone":[""],"Custom notification events":[""],"Custom notification levels are the same as participating levels. With custom notification levels you will also receive notifications for select events. To find out more, check out %{notification_link}.":[""],"Cycle Analytics":[""],"Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project.":["Cycle Analytics ofrece una visión general de cuánto tiempo tarda en pasar de idea a producción en su proyecto."],"CycleAnalyticsStage|Code":["Código"],"CycleAnalyticsStage|Issue":["Incidencia"],"CycleAnalyticsStage|Plan":["Planificación"],"CycleAnalyticsStage|Production":["Producción"],"CycleAnalyticsStage|Review":["Revisión"],"CycleAnalyticsStage|Staging":["Puesta en escena"],"CycleAnalyticsStage|Test":["Pruebas"],"Delete":[""],"Deploy":["Despliegue","Despliegues"],"Description":[""],"Directory name":[""],"Don't show again":[""],"Download tar":[""],"Download tar.bz2":[""],"Download tar.gz":[""],"Download zip":[""],"DownloadArtifacts|Download":[""],"DownloadSource|Download":[""],"Edit":[""],"Edit Pipeline Schedule %{id}":[""],"Failed to change the owner":[""],"Failed to remove the pipeline schedule":[""],"Files":[""],"Filter":[""],"Find by path":[""],"Find file":[""],"FirstPushedBy|First":["Primer"],"FirstPushedBy|pushed by":["enviado por"],"ForkedFromProjectPath|Forked from":[""],"Forks":[""],"From issue creation until deploy to production":["Desde la creación de la incidencia hasta el despliegue a producción"],"From merge request merge until deploy to production":["Desde la integración de la solicitud de fusión hasta el despliegue a producción"],"Go to your fork":[""],"GoToYourFork|Fork":[""],"Home":[""],"Housekeeping successfully started":[""],"Import repository":[""],"Interval Pattern":[""],"Introducing Cycle Analytics":["Introducción a Cycle Analytics"],"LFSStatus|Disabled":[""],"LFSStatus|Enabled":[""],"Last %d day":["Último %d día","Últimos %d días"],"Last Pipeline":[""],"Last Update":[""],"Last commit":[""],"Leave group":[""],"Leave project":[""],"Limited to showing %d event at most":["Limitado a mostrar máximo %d evento","Limitado a mostrar máximo %d eventos"],"Median":["Mediana"],"MissingSSHKeyWarningLink|add an SSH key":[""],"New Issue":["Nueva incidencia","Nuevas incidencias"],"New Pipeline Schedule":[""],"New branch":[""],"New directory":[""],"New file":[""],"New issue":["Nueva incidencia\u0000Nuevas incidencias"],"New merge request":[""],"New snippet":[""],"New tag":[""],"No repository":[""],"No schedules":[""],"Not available":["No disponible"],"Not enough data":["No hay suficientes datos"],"Notification events":[""],"NotificationEvent|Close issue":[""],"NotificationEvent|Close merge request":[""],"NotificationEvent|Failed pipeline":[""],"NotificationEvent|Merge merge request":[""],"NotificationEvent|New issue":[""],"NotificationEvent|New merge request":[""],"NotificationEvent|New note":[""],"NotificationEvent|Reassign issue":[""],"NotificationEvent|Reassign merge request":[""],"NotificationEvent|Reopen issue":[""],"NotificationEvent|Successful pipeline":[""],"NotificationLevel|Custom":[""],"NotificationLevel|Disabled":[""],"NotificationLevel|Global":[""],"NotificationLevel|On mention":[""],"NotificationLevel|Participate":[""],"NotificationLevel|Watch":[""],"OpenedNDaysAgo|Opened":["Abierto"],"Owner":[""],"Pipeline Health":["Estado del Pipeline"],"Pipeline Schedule":[""],"Pipeline Schedules":[""],"PipelineSchedules|Activated":[""],"PipelineSchedules|Active":[""],"PipelineSchedules|All":[""],"PipelineSchedules|Inactive":[""],"PipelineSchedules|Next Run":[""],"PipelineSchedules|None":[""],"PipelineSchedules|Provide a short description for this pipeline":[""],"PipelineSchedules|Take ownership":[""],"PipelineSchedules|Target":[""],"Project '%{project_name}' queued for deletion.":[""],"Project '%{project_name}' was successfully created.":[""],"Project '%{project_name}' was successfully updated.":[""],"Project '%{project_name}' will be deleted.":[""],"Project access must be granted explicitly to each user.":[""],"Project export could not be deleted.":[""],"Project export has been deleted.":[""],"Project export link has expired. Please generate a new export from your project settings.":[""],"Project export started. A download link will be sent by email.":[""],"Project home":[""],"ProjectFeature|Disabled":[""],"ProjectFeature|Everyone with access":[""],"ProjectFeature|Only team members":[""],"ProjectFileTree|Name":[""],"ProjectLastActivity|Never":[""],"ProjectLifecycle|Stage":["Etapa"],"ProjectNetworkGraph|Graph":[""],"Read more":["Leer más"],"Readme":["Leer más"],"RefSwitcher|Branches":[""],"RefSwitcher|Tags":[""],"Related Commits":["Cambios Relacionados"],"Related Deployed Jobs":["Trabajos Desplegados Relacionados"],"Related Issues":["Incidencias Relacionadas"],"Related Jobs":["Trabajos Relacionados"],"Related Merge Requests":["Solicitudes de fusión Relacionadas"],"Related Merged Requests":["Solicitudes de fusión Relacionadas"],"Remind later":[""],"Remove project":[""],"Request Access":[""],"Save pipeline schedule":[""],"Schedule a new pipeline":[""],"Search branches and tags":[""],"Select Archive Format":[""],"Select a timezone":[""],"Select target branch":[""],"Set a password on your account to pull or push via %{protocol}":[""],"Set up CI":[""],"Set up Koding":[""],"Set up auto deploy":[""],"SetPasswordToCloneLink|set a password":[""],"Showing %d event":["Mostrando %d evento","Mostrando %d eventos"],"Source code":[""],"StarProject|Star":[""],"Switch branch/tag":[""],"Tag":["",""],"Tags":[""],"Target Branch":[""],"The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request.":["La etapa de desarrollo muestra el tiempo desde el primer cambio hasta la creación de la solicitud de fusión. Los datos serán automáticamente incorporados aquí una vez creada tu primera solicitud de fusión."],"The collection of events added to the data gathered for that stage.":["La colección de eventos agregados a los datos recopilados para esa etapa."],"The fork relationship has been removed.":[""],"The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage.":["La etapa de incidencia muestra el tiempo que toma desde la creación de un tema hasta asignar el tema a un hito, o añadir el tema a una lista en el panel de temas. Empieza a crear temas para ver los datos de esta etapa."],"The phase of the development lifecycle.":["La etapa del ciclo de vida de desarrollo."],"The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit.":["La etapa de planificación muestra el tiempo desde el paso anterior hasta el envío de tu primera confirmación. Este tiempo se añadirá automáticamente una vez que usted envíe el primer cambio."],"The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle.":["La etapa de producción muestra el tiempo total que tarda entre la creación de una incidencia y el despliegue del código a producción. Los datos se añadirán automáticamente una vez haya finalizado por completo el ciclo de idea a producción."],"The project can be accessed by any logged in user.":[""],"The project can be accessed without any authentication.":[""],"The repository for this project does not exist.":[""],"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.":["La etapa de revisión muestra el tiempo desde la creación de la solicitud de fusión hasta que los cambios se fusionaron. Los datos se añadirán automáticamente después de fusionar su primera solicitud de fusión."],"The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time.":["La etapa de puesta en escena muestra el tiempo entre la fusión y el despliegue de código en el entorno de producción. Los datos se añadirán automáticamente una vez que se despliega a producción por primera vez."],"The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running.":["La etapa de pruebas muestra el tiempo que GitLab CI toma para ejecutar cada pipeline para la solicitud de fusión relacionada. Los datos se añadirán automáticamente luego de que el primer pipeline termine de ejecutarse."],"The time taken by each data entry gathered by that stage.":["El tiempo utilizado por cada entrada de datos obtenido por esa etapa."],"The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6.":["El valor en el punto medio de una serie de valores observados. Por ejemplo, entre 3, 5, 9, la mediana es 5. Entre 3, 5, 7, 8, la mediana es (5 + 7) / 2 = 6."],"This means you can not push code until you create an empty repository or import existing one.":[""],"Time before an issue gets scheduled":["Tiempo antes de que una incidencia sea programada"],"Time before an issue starts implementation":["Tiempo antes de que empieze la implementación de una incidencia"],"Time between merge request creation and merge/close":["Tiempo entre la creación de la solicitud de fusión y la integración o cierre de ésta"],"Time until first merge request":["Tiempo hasta la primera solicitud de fusión"],"Timeago|%s days ago":["día\u0000días"],"Timeago|%s days remaining":["día\u0000días"],"Timeago|%s hours remaining":[""],"Timeago|%s minutes ago":[""],"Timeago|%s minutes remaining":[""],"Timeago|%s months ago":[""],"Timeago|%s months remaining":[""],"Timeago|%s seconds remaining":[""],"Timeago|%s weeks ago":[""],"Timeago|%s weeks remaining":[""],"Timeago|%s years ago":[""],"Timeago|%s years remaining":[""],"Timeago|1 day remaining":["día\u0000días"],"Timeago|1 hour remaining":[""],"Timeago|1 minute remaining":[""],"Timeago|1 month remaining":[""],"Timeago|1 week remaining":[""],"Timeago|1 year remaining":[""],"Timeago|Past due":[""],"Timeago|a day ago":["día\u0000días"],"Timeago|a month ago":[""],"Timeago|a week ago":[""],"Timeago|a while":[""],"Timeago|a year ago":[""],"Timeago|about %s hours ago":[""],"Timeago|about a minute ago":[""],"Timeago|about an hour ago":[""],"Timeago|in %s days":["día\u0000días"],"Timeago|in %s hours":[""],"Timeago|in %s minutes":[""],"Timeago|in %s months":[""],"Timeago|in %s seconds":[""],"Timeago|in %s weeks":[""],"Timeago|in %s years":[""],"Timeago|in 1 day":["día\u0000días"],"Timeago|in 1 hour":[""],"Timeago|in 1 minute":[""],"Timeago|in 1 month":[""],"Timeago|in 1 week":[""],"Timeago|in 1 year":[""],"Timeago|less than a minute ago":[""],"Time|hr":["hr","hrs"],"Time|min":["min","mins"],"Time|s":["s"],"Total Time":["Tiempo Total"],"Total test time for all commits/merges":["Tiempo total de pruebas para todos los cambios o integraciones"],"Unstar":[""],"Upload New File":[""],"Upload file":[""],"Use your global notification setting":[""],"VisibilityLevel|Internal":[""],"VisibilityLevel|Private":[""],"VisibilityLevel|Public":[""],"Want to see the data? Please ask an administrator for access.":["¿Quieres ver los datos? Por favor pide acceso al administrador."],"We don't have enough data to show this stage.":["No hay suficientes datos para mostrar en esta etapa."],"Withdraw Access Request":[""],"You are going to remove %{project_name_with_namespace}.\\nRemoved project CANNOT be restored!\\nAre you ABSOLUTELY sure?":[""],"You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?":[""],"You are going to transfer %{project_name_with_namespace} to another owner. Are you ABSOLUTELY sure?":[""],"You can only add files when you are on a branch":[""],"You must sign in to star a project":[""],"You need permission.":["Necesitas permisos."],"You will not get any notifications via email":[""],"You will only receive notifications for the events you choose":[""],"You will only receive notifications for threads you have participated in":[""],"You will receive notifications for any activity":[""],"You will receive notifications only for comments in which you were @mentioned":[""],"You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account":[""],"You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile":[""],"Your name":[""],"committed":[""],"day":["día","días"],"notification emails":[""]}}};
\ No newline at end of file +var locales = locales || {}; locales['es'] = {"domain":"app","locale_data":{"app":{"":{"Project-Id-Version":"gitlab 1.0.0","Report-Msgid-Bugs-To":"","PO-Revision-Date":"2017-06-07 12:29-0500","Language-Team":"Spanish","Language":"es","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","Plural-Forms":"nplurals=2; plural=n != 1;","Last-Translator":"Bob Van Landuyt <bob@gitlab.com>","X-Generator":"Poedit 2.0.2","lang":"es","domain":"app","plural_forms":"nplurals=2; plural=n != 1;"},"About auto deploy":["Acerca del auto despliegue"],"Activity":["Actividad"],"Add Changelog":["Agregar Changelog"],"Add Contribution guide":["Agregar guía de contribución"],"Add License":["Agregar Licencia"],"Add an SSH key to your profile to pull or push via SSH.":["Agregar una clave SSH a tu perfil para actualizar o enviar a través de SSH."],"Add new directory":["Agregar nuevo directorio"],"Archived project! Repository is read-only":["¡Proyecto archivado! El repositorio es de sólo lectura"],"Branch":["Rama","Ramas"],"Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}":["La rama <strong>%{branch_name}</strong> fue creada. Para configurar el auto despliegue, escoge una plantilla Yaml para GitLab CI y envía tus cambios. %{link_to_autodeploy_doc}"],"Branches":["Ramas"],"ByAuthor|by":["por"],"CI configuration":["Configuración de CI"],"Changelog":["Changelog"],"Charts":["Gráficos"],"CiStatusLabel|canceled":["cancelado"],"CiStatusLabel|created":["creado"],"CiStatusLabel|failed":["fallado"],"CiStatusLabel|manual action":["acción manual"],"CiStatusLabel|passed":["pasó"],"CiStatusLabel|passed with warnings":["pasó con advertencias"],"CiStatusLabel|pending":["pendiente"],"CiStatusLabel|skipped":["omitido"],"CiStatusLabel|waiting for manual action":["esperando acción manual"],"CiStatusText|blocked":["bloqueado"],"CiStatusText|canceled":["cancelado"],"CiStatusText|created":["creado"],"CiStatusText|failed":["fallado"],"CiStatusText|manual":["manual"],"CiStatusText|passed":["pasó"],"CiStatusText|pending":["pendiente"],"CiStatusText|skipped":["omitido"],"CiStatus|running":["en ejecución"],"Commit":["Cambio","Cambios"],"CommitMessage|Add %{file_name}":["Agregar %{file_name}"],"Commits":["Cambios"],"Commits|History":["Historial"],"Compare":["Comparar"],"Contribution guide":["Guía de contribución"],"Contributors":["Contribuidores"],"Copy URL to clipboard":["Copiar URL al portapapeles"],"Copy commit SHA to clipboard":["Copiar SHA del cambio al portapapeles"],"Create New Directory":["Crear Nuevo Directorio"],"Create directory":["Crear directorio"],"Create empty bare repository":["Crear repositorio vacío"],"Create merge request":["Crear solicitud de fusión"],"CreateNewFork|Fork":["Bifurcar"],"Custom notification events":["Eventos de notificaciones personalizadas"],"Custom notification levels are the same as participating levels. With custom notification levels you will also receive notifications for select events. To find out more, check out %{notification_link}.":["Los niveles de notificación personalizados son los mismos que los niveles participantes. Con los niveles de notificación personalizados, también recibirá notificaciones para eventos seleccionados. Para obtener más información, consulte %{notification_link}."],"Cycle Analytics":["Cycle Analytics"],"Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project.":["Cycle Analytics ofrece una visión general de cuánto tiempo tarda en pasar de idea a producción en su proyecto."],"CycleAnalyticsStage|Code":["Código"],"CycleAnalyticsStage|Issue":["Incidencia"],"CycleAnalyticsStage|Plan":["Planificación"],"CycleAnalyticsStage|Production":["Producción"],"CycleAnalyticsStage|Review":["Revisión"],"CycleAnalyticsStage|Staging":["Puesta en escena"],"CycleAnalyticsStage|Test":["Pruebas"],"Deploy":["Despliegue","Despliegues"],"Directory name":["Nombre del directorio"],"Don't show again":["No mostrar de nuevo"],"Download tar":["Descargar tar"],"Download tar.bz2":["Descargar tar.bz2"],"Download tar.gz":["Descargar tar.gz"],"Download zip":["Descargar zip"],"DownloadArtifacts|Download":["Descargar"],"DownloadSource|Download":["Descargar"],"Files":["Archivos"],"Find by path":["Buscar por ruta"],"Find file":["Buscar archivo"],"FirstPushedBy|First":["Primer"],"FirstPushedBy|pushed by":["enviado por"],"ForkedFromProjectPath|Forked from":["Bifurcado de"],"Forks":["Bifurcaciones"],"From issue creation until deploy to production":["Desde la creación de la incidencia hasta el despliegue a producción"],"From merge request merge until deploy to production":["Desde la integración de la solicitud de fusión hasta el despliegue a producción"],"Go to your fork":["Ir a tu bifurcación"],"GoToYourFork|Fork":["Bifurcación"],"Home":["Inicio"],"Housekeeping successfully started":["Servicio de limpieza iniciado con éxito"],"Import repository":["Importar repositorio"],"Introducing Cycle Analytics":["Introducción a Cycle Analytics"],"LFSStatus|Disabled":["Deshabilitado"],"LFSStatus|Enabled":["Habilitado"],"Last %d day":["Último %d día","Últimos %d días"],"Last Update":["Última actualización"],"Last commit":["Último cambio"],"Leave group":["Abandonar grupo"],"Leave project":["Abandonar proyecto"],"Limited to showing %d event at most":["Limitado a mostrar máximo %d evento","Limitado a mostrar máximo %d eventos"],"Median":["Mediana"],"MissingSSHKeyWarningLink|add an SSH key":["agregar una clave SSH"],"New Issue":["Nueva incidencia","Nuevas incidencias"],"New branch":["Nueva rama"],"New directory":["Nuevo directorio"],"New file":["Nuevo archivo"],"New issue":["Nueva incidencia"],"New merge request":["Nueva solicitud de fusión"],"New snippet":["Nuevo fragmento de código"],"New tag":["Nueva etiqueta"],"No repository":["No hay repositorio"],"Not available":["No disponible"],"Not enough data":["No hay suficientes datos"],"Notification events":["Eventos de notificación"],"NotificationEvent|Close issue":["Cerrar incidencia"],"NotificationEvent|Close merge request":["Cerrar solicitud de fusión"],"NotificationEvent|Failed pipeline":["Pipeline fallido"],"NotificationEvent|Merge merge request":["Integrar solicitud de fusión"],"NotificationEvent|New issue":["Nueva incidencia"],"NotificationEvent|New merge request":["Nueva solicitud de fusión"],"NotificationEvent|New note":["Nueva nota"],"NotificationEvent|Reassign issue":["Reasignar incidencia"],"NotificationEvent|Reassign merge request":["Reasignar solicitud de fusión"],"NotificationEvent|Reopen issue":["Reabrir incidencia"],"NotificationEvent|Successful pipeline":["Pipeline exitoso"],"NotificationLevel|Custom":["Personalizado"],"NotificationLevel|Disabled":["Deshabilitado"],"NotificationLevel|Global":["Global"],"NotificationLevel|On mention":["Cuando me mencionan"],"NotificationLevel|Participate":["Participación"],"NotificationLevel|Watch":["Vigilancia"],"OpenedNDaysAgo|Opened":["Abierto"],"Pipeline Health":["Estado del Pipeline"],"Project '%{project_name}' queued for deletion.":["Proyecto ‘%{project_name}’ en cola para eliminación."],"Project '%{project_name}' was successfully created.":["Proyecto ‘%{project_name}’ fue creado satisfactoriamente."],"Project '%{project_name}' was successfully updated.":["Proyecto ‘%{project_name}’ fue actualizado satisfactoriamente."],"Project '%{project_name}' will be deleted.":["Proyecto ‘%{project_name}’ será eliminado."],"Project access must be granted explicitly to each user.":["El acceso al proyecto debe concederse explícitamente a cada usuario."],"Project export could not be deleted.":["No se pudo eliminar la exportación del proyecto."],"Project export has been deleted.":["La exportación del proyecto ha sido eliminada."],"Project export link has expired. Please generate a new export from your project settings.":["El enlace de exportación del proyecto ha caducado. Por favor, genera una nueva exportación desde la configuración del proyecto."],"Project export started. A download link will be sent by email.":["Se inició la exportación del proyecto. Se enviará un enlace de descarga por correo electrónico."],"Project home":["Inicio del proyecto"],"ProjectFeature|Disabled":["Deshabilitada"],"ProjectFeature|Everyone with access":["Todos con acceso"],"ProjectFeature|Only team members":["Solo miembros del equipo"],"ProjectFileTree|Name":["Nombre"],"ProjectLastActivity|Never":["Nunca"],"ProjectLifecycle|Stage":["Etapa"],"ProjectNetworkGraph|Graph":["Historial gráfico"],"Read more":["Leer más"],"Readme":["Readme"],"RefSwitcher|Branches":["Ramas"],"RefSwitcher|Tags":["Etiquetas"],"Related Commits":["Cambios Relacionados"],"Related Deployed Jobs":["Trabajos Desplegados Relacionados"],"Related Issues":["Incidencias Relacionadas"],"Related Jobs":["Trabajos Relacionados"],"Related Merge Requests":["Solicitudes de fusión Relacionadas"],"Related Merged Requests":["Solicitudes de fusión Relacionadas"],"Remind later":["Recordar después"],"Remove project":["Eliminar proyecto"],"Request Access":["Solicitar acceso"],"Search branches and tags":["Buscar ramas y etiquetas"],"Select Archive Format":["Seleccionar formato de archivo"],"Set a password on your account to pull or push via %{protocol}":["Establezca una contraseña en su cuenta para actualizar o enviar a través de% {protocol}"],"Set up CI":["Configurar CI"],"Set up Koding":["Configurar Koding"],"Set up auto deploy":["Configurar auto despliegue"],"SetPasswordToCloneLink|set a password":["establecer una contraseña"],"Showing %d event":["Mostrando %d evento","Mostrando %d eventos"],"Source code":["Código fuente"],"StarProject|Star":["Destacar"],"Switch branch/tag":["Cambiar rama/etiqueta"],"Tag":["Etiqueta","Etiquetas"],"Tags":["Etiquetas"],"The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request.":["La etapa de desarrollo muestra el tiempo desde el primer cambio hasta la creación de la solicitud de fusión. Los datos serán automáticamente incorporados aquí una vez creada tu primera solicitud de fusión."],"The collection of events added to the data gathered for that stage.":["La colección de eventos agregados a los datos recopilados para esa etapa."],"The fork relationship has been removed.":["La relación con la bifurcación se ha eliminado."],"The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage.":["La etapa de incidencia muestra el tiempo que toma desde la creación de un tema hasta asignar el tema a un hito, o añadir el tema a una lista en el panel de temas. Empieza a crear temas para ver los datos de esta etapa."],"The phase of the development lifecycle.":["La etapa del ciclo de vida de desarrollo."],"The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit.":["La etapa de planificación muestra el tiempo desde el paso anterior hasta el envío de tu primera confirmación. Este tiempo se añadirá automáticamente una vez que usted envíe el primer cambio."],"The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle.":["La etapa de producción muestra el tiempo total que tarda entre la creación de una incidencia y el despliegue del código a producción. Los datos se añadirán automáticamente una vez haya finalizado por completo el ciclo de idea a producción."],"The project can be accessed by any logged in user.":["El proyecto puede ser accedido por cualquier usuario conectado."],"The project can be accessed without any authentication.":["El proyecto puede accederse sin ninguna autenticación."],"The repository for this project does not exist.":["El repositorio para este proyecto no existe."],"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.":["La etapa de revisión muestra el tiempo desde la creación de la solicitud de fusión hasta que los cambios se fusionaron. Los datos se añadirán automáticamente después de fusionar su primera solicitud de fusión."],"The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time.":["La etapa de puesta en escena muestra el tiempo entre la fusión y el despliegue de código en el entorno de producción. Los datos se añadirán automáticamente una vez que se despliega a producción por primera vez."],"The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running.":["La etapa de pruebas muestra el tiempo que GitLab CI toma para ejecutar cada pipeline para la solicitud de fusión relacionada. Los datos se añadirán automáticamente luego de que el primer pipeline termine de ejecutarse."],"The time taken by each data entry gathered by that stage.":["El tiempo utilizado por cada entrada de datos obtenido por esa etapa."],"The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6.":["El valor en el punto medio de una serie de valores observados. Por ejemplo, entre 3, 5, 9, la mediana es 5. Entre 3, 5, 7, 8, la mediana es (5 + 7) / 2 = 6."],"This means you can not push code until you create an empty repository or import existing one.":["Esto significa que no puede enviar código hasta que cree un repositorio vacío o importe uno existente."],"Time before an issue gets scheduled":["Tiempo antes de que una incidencia sea programada"],"Time before an issue starts implementation":["Tiempo antes de que empieze la implementación de una incidencia"],"Time between merge request creation and merge/close":["Tiempo entre la creación de la solicitud de fusión y la integración o cierre de ésta"],"Time until first merge request":["Tiempo hasta la primera solicitud de fusión"],"Timeago|%s days ago":["hace %s días"],"Timeago|%s days remaining":["%s días restantes"],"Timeago|%s hours remaining":["%s horas restantes"],"Timeago|%s minutes ago":["hace %s minutos"],"Timeago|%s minutes remaining":["%s minutos restantes"],"Timeago|%s months ago":["hace %s meses"],"Timeago|%s months remaining":["%s meses restantes"],"Timeago|%s seconds remaining":["%s segundos restantes"],"Timeago|%s weeks ago":["hace %s semanas"],"Timeago|%s weeks remaining":["%s semanas restantes"],"Timeago|%s years ago":["hace %s años"],"Timeago|%s years remaining":["%s años restantes"],"Timeago|1 day remaining":["1 día restante"],"Timeago|1 hour remaining":["1 hora restante"],"Timeago|1 minute remaining":["1 minuto restante"],"Timeago|1 month remaining":["1 mes restante"],"Timeago|1 week remaining":["1 semana restante"],"Timeago|1 year remaining":["1 año restante"],"Timeago|Past due":["Atrasado"],"Timeago|a day ago":["hace un día"],"Timeago|a month ago":["hace 1 mes"],"Timeago|a week ago":["hace 1 semana"],"Timeago|a while":["hace un momento"],"Timeago|a year ago":["hace 1 año"],"Timeago|about %s hours ago":["hace alrededor de %s horas"],"Timeago|about a minute ago":["hace alrededor de 1 minuto"],"Timeago|about an hour ago":["hace alrededor de 1 hora"],"Timeago|in %s days":["en %s días"],"Timeago|in %s hours":["en %s horas"],"Timeago|in %s minutes":["en %s minutos"],"Timeago|in %s months":["en %s meses"],"Timeago|in %s seconds":["en %s segundos"],"Timeago|in %s weeks":["en %s semanas"],"Timeago|in %s years":["en %s años"],"Timeago|in 1 day":["en 1 día"],"Timeago|in 1 hour":["en 1 hora"],"Timeago|in 1 minute":["en 1 minuto"],"Timeago|in 1 month":["en 1 mes"],"Timeago|in 1 week":["en 1 semana"],"Timeago|in 1 year":["en 1 año"],"Timeago|less than a minute ago":["hace menos de 1 minuto"],"Time|hr":["hr","hrs"],"Time|min":["min","mins"],"Time|s":["s"],"Total Time":["Tiempo Total"],"Total test time for all commits/merges":["Tiempo total de pruebas para todos los cambios o integraciones"],"Unstar":["No Destacar"],"Upload New File":["Subir nuevo archivo"],"Upload file":["Subir archivo"],"Use your global notification setting":["Utiliza tu configuración de notificación global"],"VisibilityLevel|Internal":["Interno"],"VisibilityLevel|Private":["Privado"],"VisibilityLevel|Public":["Público"],"Want to see the data? Please ask an administrator for access.":["¿Quieres ver los datos? Por favor pide acceso al administrador."],"We don't have enough data to show this stage.":["No hay suficientes datos para mostrar en esta etapa."],"Withdraw Access Request":["Retirar Solicitud de Acceso"],"You are going to remove %{project_name_with_namespace}.\\nRemoved project CANNOT be restored!\\nAre you ABSOLUTELY sure?":["Va a eliminar %{project_name_with_namespace}.\\n¡El proyecto eliminado NO puede ser restaurado!\\n¿Estás TOTALMENTE seguro?"],"You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?":["Vas a eliminar el enlace de la bifurcación con el proyecto original %{forked_from_project}. ¿Estás TOTALMENTE seguro?"],"You are going to transfer %{project_name_with_namespace} to another owner. Are you ABSOLUTELY sure?":["Vas a transferir %{project_name_with_namespace} a otro propietario. ¿Estás TOTALMENTE seguro?"],"You can only add files when you are on a branch":["Sólo puede agregar archivos cuando estas en una rama"],"You must sign in to star a project":["Debes iniciar sesión para destacar un proyecto"],"You need permission.":["Necesitas permisos."],"You will not get any notifications via email":["No recibirás ninguna notificación por correo electrónico"],"You will only receive notifications for the events you choose":["Solo recibirás notificaciones de los eventos que elijas"],"You will only receive notifications for threads you have participated in":["Solo recibirás notificaciones de los temas en los que has participado"],"You will receive notifications for any activity":["Recibirás notificaciones para cualquier actividad"],"You will receive notifications only for comments in which you were @mentioned":["Recibirás notificaciones sólo para los comentarios en los que se te mencionó"],"You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account":["No podrás actualizar o enviar código al proyecto a través de %{protocol} hasta que %{set_password_link} en tu cuenta"],"You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile":["No podrás actualizar o enviar código al proyecto a través de SSH hasta que %{add_ssh_key_link} en su perfil"],"Your name":["Tu nombre"],"committed":["cambió"],"day":["día","días"],"notification emails":["correos electrónicos de notificación"]}}};
\ No newline at end of file diff --git a/app/assets/javascripts/locale/zh_CN/app.js b/app/assets/javascripts/locale/zh_CN/app.js index 2439fa931ef..d1335cfbc0f 100644 --- a/app/assets/javascripts/locale/zh_CN/app.js +++ b/app/assets/javascripts/locale/zh_CN/app.js @@ -1 +1 @@ -var locales = locales || {}; locales['zh_CN'] = {"domain":"app","locale_data":{"app":{"":{"Project-Id-Version":"gitlab 1.0.0","Report-Msgid-Bugs-To":"","PO-Revision-Date":"2017-05-04 19:24-0500","Last-Translator":"HuangTao <htve@outlook.com>, 2017","Language-Team":"Chinese (China) (https://www.transifex.com/gitlab-zh/teams/75177/zh_CN/)","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","Language":"zh_CN","Plural-Forms":"nplurals=1; plural=0;","lang":"zh_CN","domain":"app","plural_forms":"nplurals=1; plural=0;"},"About auto deploy":[""],"Activity":[""],"Add Changelog":[""],"Add Contribution guide":[""],"Add License":[""],"Add an SSH key to your profile to pull or push via SSH.":[""],"Add new directory":[""],"Archived project! Repository is read-only":[""],"Are you sure you want to delete this pipeline schedule?":[""],"Branch":["",""],"Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}":[""],"Branches":[""],"ByAuthor|by":["作者:"],"CI configuration":[""],"Cancel":[""],"Changelog":[""],"Charts":[""],"CiStatusLabel|canceled":[""],"CiStatusLabel|created":[""],"CiStatusLabel|failed":[""],"CiStatusLabel|manual action":[""],"CiStatusLabel|passed":[""],"CiStatusLabel|passed with warnings":[""],"CiStatusLabel|pending":[""],"CiStatusLabel|skipped":[""],"CiStatusLabel|waiting for manual action":[""],"CiStatusText|blocked":[""],"CiStatusText|canceled":[""],"CiStatusText|created":[""],"CiStatusText|failed":[""],"CiStatusText|manual":[""],"CiStatusText|passed":[""],"CiStatusText|pending":[""],"CiStatusText|skipped":[""],"CiStatus|running":[""],"Commit":["提交"],"CommitMessage|Add %{file_name}":["提交"],"Commits":["提交"],"Commits|History":["提交"],"Compare":[""],"Contribution guide":[""],"Contributors":[""],"Copy URL to clipboard":[""],"Copy commit SHA to clipboard":[""],"Create New Directory":[""],"Create directory":[""],"Create empty bare repository":[""],"Create merge request":["相关的合并请求"],"CreateNewFork|Fork":[""],"Cron Timezone":[""],"Custom notification events":[""],"Custom notification levels are the same as participating levels. With custom notification levels you will also receive notifications for select events. To find out more, check out %{notification_link}.":[""],"Cycle Analytics":[""],"Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project.":["周期分析概述了项目从想法到产品实现的各阶段所需的时间。"],"CycleAnalyticsStage|Code":["编码"],"CycleAnalyticsStage|Issue":["议题"],"CycleAnalyticsStage|Plan":["计划"],"CycleAnalyticsStage|Production":["生产"],"CycleAnalyticsStage|Review":["评审"],"CycleAnalyticsStage|Staging":["预发布"],"CycleAnalyticsStage|Test":["测试"],"Delete":[""],"Deploy":["部署"],"Description":[""],"Directory name":[""],"Don't show again":[""],"Download tar":[""],"Download tar.bz2":[""],"Download tar.gz":[""],"Download zip":[""],"DownloadArtifacts|Download":[""],"DownloadSource|Download":[""],"Edit":[""],"Edit Pipeline Schedule %{id}":[""],"Failed to change the owner":[""],"Failed to remove the pipeline schedule":[""],"Files":[""],"Filter":[""],"Find by path":[""],"Find file":[""],"FirstPushedBy|First":["首次推送"],"FirstPushedBy|pushed by":["推送者:"],"ForkedFromProjectPath|Forked from":[""],"Forks":[""],"From issue creation until deploy to production":["从创建议题到部署至生产环境"],"From merge request merge until deploy to production":["从合并请求被合并后到部署至生产环境"],"Go to your fork":[""],"GoToYourFork|Fork":[""],"Home":[""],"Housekeeping successfully started":[""],"Import repository":[""],"Interval Pattern":[""],"Introducing Cycle Analytics":["周期分析简介"],"LFSStatus|Disabled":[""],"LFSStatus|Enabled":[""],"Last %d day":["最后 %d 天"],"Last Pipeline":[""],"Last Update":[""],"Last commit":[""],"Leave group":[""],"Leave project":[""],"Limited to showing %d event at most":["最多显示 %d 个事件"],"Median":["中位数"],"MissingSSHKeyWarningLink|add an SSH key":[""],"New Issue":["新议题"],"New Pipeline Schedule":[""],"New branch":[""],"New directory":[""],"New file":[""],"New issue":["新议题"],"New merge request":[""],"New snippet":[""],"New tag":[""],"No repository":[""],"No schedules":[""],"Not available":["数据不足"],"Not enough data":["数据不足"],"Notification events":[""],"NotificationEvent|Close issue":[""],"NotificationEvent|Close merge request":[""],"NotificationEvent|Failed pipeline":[""],"NotificationEvent|Merge merge request":[""],"NotificationEvent|New issue":[""],"NotificationEvent|New merge request":[""],"NotificationEvent|New note":[""],"NotificationEvent|Reassign issue":[""],"NotificationEvent|Reassign merge request":[""],"NotificationEvent|Reopen issue":[""],"NotificationEvent|Successful pipeline":[""],"NotificationLevel|Custom":[""],"NotificationLevel|Disabled":[""],"NotificationLevel|Global":[""],"NotificationLevel|On mention":[""],"NotificationLevel|Participate":[""],"NotificationLevel|Watch":[""],"OpenedNDaysAgo|Opened":["开始于"],"Owner":[""],"Pipeline Health":["流水线健康指标"],"Pipeline Schedule":[""],"Pipeline Schedules":[""],"PipelineSchedules|Activated":[""],"PipelineSchedules|Active":[""],"PipelineSchedules|All":[""],"PipelineSchedules|Inactive":[""],"PipelineSchedules|Next Run":[""],"PipelineSchedules|None":[""],"PipelineSchedules|Provide a short description for this pipeline":[""],"PipelineSchedules|Take ownership":[""],"PipelineSchedules|Target":[""],"Project '%{project_name}' queued for deletion.":[""],"Project '%{project_name}' was successfully created.":[""],"Project '%{project_name}' was successfully updated.":[""],"Project '%{project_name}' will be deleted.":[""],"Project access must be granted explicitly to each user.":[""],"Project export could not be deleted.":[""],"Project export has been deleted.":[""],"Project export link has expired. Please generate a new export from your project settings.":[""],"Project export started. A download link will be sent by email.":[""],"Project home":[""],"ProjectFeature|Disabled":[""],"ProjectFeature|Everyone with access":[""],"ProjectFeature|Only team members":[""],"ProjectFileTree|Name":[""],"ProjectLastActivity|Never":[""],"ProjectLifecycle|Stage":["项目生命周期"],"ProjectNetworkGraph|Graph":[""],"Read more":["了解更多"],"Readme":["了解更多"],"RefSwitcher|Branches":[""],"RefSwitcher|Tags":[""],"Related Commits":["相关的提交"],"Related Deployed Jobs":["相关的部署作业"],"Related Issues":["相关的议题"],"Related Jobs":["相关的作业"],"Related Merge Requests":["相关的合并请求"],"Related Merged Requests":["相关已合并的合并请求"],"Remind later":[""],"Remove project":[""],"Request Access":[""],"Save pipeline schedule":[""],"Schedule a new pipeline":[""],"Search branches and tags":[""],"Select Archive Format":[""],"Select a timezone":[""],"Select target branch":[""],"Set a password on your account to pull or push via %{protocol}":[""],"Set up CI":[""],"Set up Koding":[""],"Set up auto deploy":[""],"SetPasswordToCloneLink|set a password":[""],"Showing %d event":["显示 %d 个事件"],"Source code":[""],"StarProject|Star":[""],"Switch branch/tag":[""],"Tag":["",""],"Tags":[""],"Target Branch":[""],"The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request.":["编码阶段概述了从第一次提交到创建合并请求的时间。创建第一个合并请求后,数据将自动添加到此处。"],"The collection of events added to the data gathered for that stage.":["与该阶段相关的事件。"],"The fork relationship has been removed.":[""],"The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage.":["议题阶段概述了从创建议题到将议题设置里程碑或将议题添加到议题看板的时间。开始创建议题以查看此阶段的数据。"],"The phase of the development lifecycle.":["项目生命周期中的各个阶段。"],"The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit.":["计划阶段概述了从议题添加到日程后到推送首次提交的时间。当首次推送提交后,数据将自动添加到此处。"],"The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle.":["生产阶段概述了从创建一个议题到将代码部署到生产环境的总时间。当完成想法到部署生产的循环,数据将自动添加到此处。"],"The project can be accessed by any logged in user.":[""],"The project can be accessed without any authentication.":[""],"The repository for this project does not exist.":[""],"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.":["评审阶段概述了从创建合并请求到被合并的时间。当创建第一个合并请求后,数据将自动添加到此处。"],"The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time.":["预发布阶段概述了从合并请求被合并到部署至生产环境的总时间。首次部署到生产环境后,数据将自动添加到此处。"],"The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running.":["测试阶段概述了GitLab CI为相关合并请求运行每个流水线所需的时间。当第一个流水线运行完成后,数据将自动添加到此处。"],"The time taken by each data entry gathered by that stage.":["该阶段每条数据所花的时间"],"The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6.":["中位数是一个数列中最中间的值。例如在 3、5、9 之间,中位数是 5。在 3、5、7、8 之间,中位数是 (5 + 7)/ 2 = 6。"],"This means you can not push code until you create an empty repository or import existing one.":[""],"Time before an issue gets scheduled":["议题被列入日程表的时间"],"Time before an issue starts implementation":["开始进行编码前的时间"],"Time between merge request creation and merge/close":["从创建合并请求到被合并或关闭的时间"],"Time until first merge request":["创建第一个合并请求之前的时间"],"Timeago|%s days ago":["天"],"Timeago|%s days remaining":["天"],"Timeago|%s hours remaining":[""],"Timeago|%s minutes ago":[""],"Timeago|%s minutes remaining":[""],"Timeago|%s months ago":[""],"Timeago|%s months remaining":[""],"Timeago|%s seconds remaining":[""],"Timeago|%s weeks ago":[""],"Timeago|%s weeks remaining":[""],"Timeago|%s years ago":[""],"Timeago|%s years remaining":[""],"Timeago|1 day remaining":["天"],"Timeago|1 hour remaining":[""],"Timeago|1 minute remaining":[""],"Timeago|1 month remaining":[""],"Timeago|1 week remaining":[""],"Timeago|1 year remaining":[""],"Timeago|Past due":[""],"Timeago|a day ago":["天"],"Timeago|a month ago":[""],"Timeago|a week ago":[""],"Timeago|a while":[""],"Timeago|a year ago":[""],"Timeago|about %s hours ago":[""],"Timeago|about a minute ago":[""],"Timeago|about an hour ago":[""],"Timeago|in %s days":["天"],"Timeago|in %s hours":[""],"Timeago|in %s minutes":[""],"Timeago|in %s months":[""],"Timeago|in %s seconds":[""],"Timeago|in %s weeks":[""],"Timeago|in %s years":[""],"Timeago|in 1 day":["天"],"Timeago|in 1 hour":[""],"Timeago|in 1 minute":[""],"Timeago|in 1 month":[""],"Timeago|in 1 week":[""],"Timeago|in 1 year":[""],"Timeago|less than a minute ago":[""],"Time|hr":["小时"],"Time|min":["分钟"],"Time|s":["秒"],"Total Time":["总时间"],"Total test time for all commits/merges":["所有提交和合并的总测试时间"],"Unstar":[""],"Upload New File":[""],"Upload file":[""],"Use your global notification setting":[""],"VisibilityLevel|Internal":[""],"VisibilityLevel|Private":[""],"VisibilityLevel|Public":[""],"Want to see the data? Please ask an administrator for access.":["权限不足。如需查看相关数据,请向管理员申请权限。"],"We don't have enough data to show this stage.":["该阶段的数据不足,无法显示。"],"Withdraw Access Request":[""],"You are going to remove %{project_name_with_namespace}.\\nRemoved project CANNOT be restored!\\nAre you ABSOLUTELY sure?":[""],"You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?":[""],"You are going to transfer %{project_name_with_namespace} to another owner. Are you ABSOLUTELY sure?":[""],"You can only add files when you are on a branch":[""],"You must sign in to star a project":[""],"You need permission.":["您需要相关的权限。"],"You will not get any notifications via email":[""],"You will only receive notifications for the events you choose":[""],"You will only receive notifications for threads you have participated in":[""],"You will receive notifications for any activity":[""],"You will receive notifications only for comments in which you were @mentioned":[""],"You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account":[""],"You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile":[""],"Your name":[""],"committed":[""],"day":["天"],"notification emails":[""]}}};
\ No newline at end of file +var locales = locales || {}; locales['zh_CN'] = {"domain":"app","locale_data":{"app":{"":{"Project-Id-Version":"gitlab 1.0.0","Report-Msgid-Bugs-To":"","PO-Revision-Date":"2017-05-04 19:24-0500","Last-Translator":"HuangTao <htve@outlook.com>, 2017","Language-Team":"Chinese (China) (https://www.transifex.com/gitlab-zh/teams/75177/zh_CN/)","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","Language":"zh_CN","Plural-Forms":"nplurals=1; plural=0;","lang":"zh_CN","domain":"app","plural_forms":"nplurals=1; plural=0;"},"Are you sure you want to delete this pipeline schedule?":[""],"ByAuthor|by":["作者:"],"Cancel":[""],"Commit":["提交"],"Cron Timezone":[""],"Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project.":["周期分析概述了项目从想法到产品实现的各阶段所需的时间。"],"CycleAnalyticsStage|Code":["编码"],"CycleAnalyticsStage|Issue":["议题"],"CycleAnalyticsStage|Plan":["计划"],"CycleAnalyticsStage|Production":["生产"],"CycleAnalyticsStage|Review":["评审"],"CycleAnalyticsStage|Staging":["预发布"],"CycleAnalyticsStage|Test":["测试"],"Delete":[""],"Deploy":["部署"],"Description":[""],"Edit":[""],"Edit Pipeline Schedule %{id}":[""],"Failed to change the owner":[""],"Failed to remove the pipeline schedule":[""],"Filter":[""],"FirstPushedBy|First":["首次推送"],"FirstPushedBy|pushed by":["推送者:"],"From issue creation until deploy to production":["从创建议题到部署至生产环境"],"From merge request merge until deploy to production":["从合并请求被合并后到部署至生产环境"],"Interval Pattern":[""],"Introducing Cycle Analytics":["周期分析简介"],"Last %d day":["最后 %d 天"],"Last Pipeline":[""],"Limited to showing %d event at most":["最多显示 %d 个事件"],"Median":["中位数"],"New Issue":["新议题"],"New Pipeline Schedule":[""],"No schedules":[""],"Not available":["数据不足"],"Not enough data":["数据不足"],"OpenedNDaysAgo|Opened":["开始于"],"Owner":[""],"Pipeline Health":["流水线健康指标"],"Pipeline Schedule":[""],"Pipeline Schedules":[""],"PipelineSchedules|Activated":[""],"PipelineSchedules|Active":[""],"PipelineSchedules|All":[""],"PipelineSchedules|Inactive":[""],"PipelineSchedules|Next Run":[""],"PipelineSchedules|None":[""],"PipelineSchedules|Provide a short description for this pipeline":[""],"PipelineSchedules|Take ownership":[""],"PipelineSchedules|Target":[""],"ProjectLifecycle|Stage":["项目生命周期"],"Read more":["了解更多"],"Related Commits":["相关的提交"],"Related Deployed Jobs":["相关的部署作业"],"Related Issues":["相关的议题"],"Related Jobs":["相关的作业"],"Related Merge Requests":["相关的合并请求"],"Related Merged Requests":["相关已合并的合并请求"],"Save pipeline schedule":[""],"Schedule a new pipeline":[""],"Select a timezone":[""],"Select target branch":[""],"Showing %d event":["显示 %d 个事件"],"Target Branch":[""],"The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request.":["编码阶段概述了从第一次提交到创建合并请求的时间。创建第一个合并请求后,数据将自动添加到此处。"],"The collection of events added to the data gathered for that stage.":["与该阶段相关的事件。"],"The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage.":["议题阶段概述了从创建议题到将议题设置里程碑或将议题添加到议题看板的时间。开始创建议题以查看此阶段的数据。"],"The phase of the development lifecycle.":["项目生命周期中的各个阶段。"],"The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit.":["计划阶段概述了从议题添加到日程后到推送首次提交的时间。当首次推送提交后,数据将自动添加到此处。"],"The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle.":["生产阶段概述了从创建一个议题到将代码部署到生产环境的总时间。当完成想法到部署生产的循环,数据将自动添加到此处。"],"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.":["评审阶段概述了从创建合并请求到被合并的时间。当创建第一个合并请求后,数据将自动添加到此处。"],"The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time.":["预发布阶段概述了从合并请求被合并到部署至生产环境的总时间。首次部署到生产环境后,数据将自动添加到此处。"],"The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running.":["测试阶段概述了GitLab CI为相关合并请求运行每个流水线所需的时间。当第一个流水线运行完成后,数据将自动添加到此处。"],"The time taken by each data entry gathered by that stage.":["该阶段每条数据所花的时间"],"The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6.":["中位数是一个数列中最中间的值。例如在 3、5、9 之间,中位数是 5。在 3、5、7、8 之间,中位数是 (5 + 7)/ 2 = 6。"],"Time before an issue gets scheduled":["议题被列入日程表的时间"],"Time before an issue starts implementation":["开始进行编码前的时间"],"Time between merge request creation and merge/close":["从创建合并请求到被合并或关闭的时间"],"Time until first merge request":["创建第一个合并请求之前的时间"],"Time|hr":["小时"],"Time|min":["分钟"],"Time|s":["秒"],"Total Time":["总时间"],"Total test time for all commits/merges":["所有提交和合并的总测试时间"],"Want to see the data? Please ask an administrator for access.":["权限不足。如需查看相关数据,请向管理员申请权限。"],"We don't have enough data to show this stage.":["该阶段的数据不足,无法显示。"],"You need permission.":["您需要相关的权限。"],"day":["天"]}}};
\ No newline at end of file diff --git a/app/assets/javascripts/locale/zh_HK/app.js b/app/assets/javascripts/locale/zh_HK/app.js index 216b6286d93..30cb1e6b89e 100644 --- a/app/assets/javascripts/locale/zh_HK/app.js +++ b/app/assets/javascripts/locale/zh_HK/app.js @@ -1 +1 @@ -var locales = locales || {}; locales['zh_HK'] = {"domain":"app","locale_data":{"app":{"":{"Project-Id-Version":"gitlab 1.0.0","Report-Msgid-Bugs-To":"","PO-Revision-Date":"2017-05-04 19:24-0500","Last-Translator":"HuangTao <htve@outlook.com>, 2017","Language-Team":"Chinese (Hong Kong) (https://www.transifex.com/gitlab-zh/teams/75177/zh_HK/)","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","Language":"zh_HK","Plural-Forms":"nplurals=1; plural=0;","lang":"zh_HK","domain":"app","plural_forms":"nplurals=1; plural=0;"},"About auto deploy":[""],"Activity":[""],"Add Changelog":[""],"Add Contribution guide":[""],"Add License":[""],"Add an SSH key to your profile to pull or push via SSH.":[""],"Add new directory":[""],"Archived project! Repository is read-only":[""],"Are you sure you want to delete this pipeline schedule?":[""],"Branch":["",""],"Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}":[""],"Branches":[""],"ByAuthor|by":["作者:"],"CI configuration":[""],"Cancel":[""],"Changelog":[""],"Charts":[""],"CiStatusLabel|canceled":[""],"CiStatusLabel|created":[""],"CiStatusLabel|failed":[""],"CiStatusLabel|manual action":[""],"CiStatusLabel|passed":[""],"CiStatusLabel|passed with warnings":[""],"CiStatusLabel|pending":[""],"CiStatusLabel|skipped":[""],"CiStatusLabel|waiting for manual action":[""],"CiStatusText|blocked":[""],"CiStatusText|canceled":[""],"CiStatusText|created":[""],"CiStatusText|failed":[""],"CiStatusText|manual":[""],"CiStatusText|passed":[""],"CiStatusText|pending":[""],"CiStatusText|skipped":[""],"CiStatus|running":[""],"Commit":["提交"],"CommitMessage|Add %{file_name}":["提交"],"Commits":["提交"],"Commits|History":["提交"],"Compare":[""],"Contribution guide":[""],"Contributors":[""],"Copy URL to clipboard":[""],"Copy commit SHA to clipboard":[""],"Create New Directory":[""],"Create directory":[""],"Create empty bare repository":[""],"Create merge request":["相關的合併請求"],"CreateNewFork|Fork":[""],"Cron Timezone":[""],"Custom notification events":[""],"Custom notification levels are the same as participating levels. With custom notification levels you will also receive notifications for select events. To find out more, check out %{notification_link}.":[""],"Cycle Analytics":[""],"Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project.":["週期分析概述了項目從想法到產品實現的各階段所需的時間。"],"CycleAnalyticsStage|Code":["編碼"],"CycleAnalyticsStage|Issue":["議題"],"CycleAnalyticsStage|Plan":["計劃"],"CycleAnalyticsStage|Production":["生產"],"CycleAnalyticsStage|Review":["評審"],"CycleAnalyticsStage|Staging":["預發布"],"CycleAnalyticsStage|Test":["測試"],"Delete":[""],"Deploy":["部署"],"Description":[""],"Directory name":[""],"Don't show again":[""],"Download tar":[""],"Download tar.bz2":[""],"Download tar.gz":[""],"Download zip":[""],"DownloadArtifacts|Download":[""],"DownloadSource|Download":[""],"Edit":[""],"Edit Pipeline Schedule %{id}":[""],"Failed to change the owner":[""],"Failed to remove the pipeline schedule":[""],"Files":[""],"Filter":[""],"Find by path":[""],"Find file":[""],"FirstPushedBy|First":["首次推送"],"FirstPushedBy|pushed by":["推送者:"],"ForkedFromProjectPath|Forked from":[""],"Forks":[""],"From issue creation until deploy to production":["從創建議題到部署到生產環境"],"From merge request merge until deploy to production":["從合併請求的合併到部署至生產環境"],"Go to your fork":[""],"GoToYourFork|Fork":[""],"Home":[""],"Housekeeping successfully started":[""],"Import repository":[""],"Interval Pattern":[""],"Introducing Cycle Analytics":["週期分析簡介"],"LFSStatus|Disabled":[""],"LFSStatus|Enabled":[""],"Last %d day":["最後 %d 天"],"Last Pipeline":[""],"Last Update":[""],"Last commit":[""],"Leave group":[""],"Leave project":[""],"Limited to showing %d event at most":["最多顯示 %d 個事件"],"Median":["中位數"],"MissingSSHKeyWarningLink|add an SSH key":[""],"New Issue":["新議題"],"New Pipeline Schedule":[""],"New branch":[""],"New directory":[""],"New file":[""],"New issue":["新議題"],"New merge request":[""],"New snippet":[""],"New tag":[""],"No repository":[""],"No schedules":[""],"Not available":["不可用"],"Not enough data":["數據不足"],"Notification events":[""],"NotificationEvent|Close issue":[""],"NotificationEvent|Close merge request":[""],"NotificationEvent|Failed pipeline":[""],"NotificationEvent|Merge merge request":[""],"NotificationEvent|New issue":[""],"NotificationEvent|New merge request":[""],"NotificationEvent|New note":[""],"NotificationEvent|Reassign issue":[""],"NotificationEvent|Reassign merge request":[""],"NotificationEvent|Reopen issue":[""],"NotificationEvent|Successful pipeline":[""],"NotificationLevel|Custom":[""],"NotificationLevel|Disabled":[""],"NotificationLevel|Global":[""],"NotificationLevel|On mention":[""],"NotificationLevel|Participate":[""],"NotificationLevel|Watch":[""],"OpenedNDaysAgo|Opened":["開始於"],"Owner":[""],"Pipeline Health":["流水線健康指標"],"Pipeline Schedule":[""],"Pipeline Schedules":[""],"PipelineSchedules|Activated":[""],"PipelineSchedules|Active":[""],"PipelineSchedules|All":[""],"PipelineSchedules|Inactive":[""],"PipelineSchedules|Next Run":[""],"PipelineSchedules|None":[""],"PipelineSchedules|Provide a short description for this pipeline":[""],"PipelineSchedules|Take ownership":[""],"PipelineSchedules|Target":[""],"Project '%{project_name}' queued for deletion.":[""],"Project '%{project_name}' was successfully created.":[""],"Project '%{project_name}' was successfully updated.":[""],"Project '%{project_name}' will be deleted.":[""],"Project access must be granted explicitly to each user.":[""],"Project export could not be deleted.":[""],"Project export has been deleted.":[""],"Project export link has expired. Please generate a new export from your project settings.":[""],"Project export started. A download link will be sent by email.":[""],"Project home":[""],"ProjectFeature|Disabled":[""],"ProjectFeature|Everyone with access":[""],"ProjectFeature|Only team members":[""],"ProjectFileTree|Name":[""],"ProjectLastActivity|Never":[""],"ProjectLifecycle|Stage":["項目生命週期"],"ProjectNetworkGraph|Graph":[""],"Read more":["了解更多"],"Readme":["了解更多"],"RefSwitcher|Branches":[""],"RefSwitcher|Tags":[""],"Related Commits":["相關的提交"],"Related Deployed Jobs":["相關的部署作業"],"Related Issues":["相關的議題"],"Related Jobs":["相關的作業"],"Related Merge Requests":["相關的合併請求"],"Related Merged Requests":["相關已合併的合並請求"],"Remind later":[""],"Remove project":[""],"Request Access":[""],"Save pipeline schedule":[""],"Schedule a new pipeline":[""],"Search branches and tags":[""],"Select Archive Format":[""],"Select a timezone":[""],"Select target branch":[""],"Set a password on your account to pull or push via %{protocol}":[""],"Set up CI":[""],"Set up Koding":[""],"Set up auto deploy":[""],"SetPasswordToCloneLink|set a password":[""],"Showing %d event":["顯示 %d 個事件"],"Source code":[""],"StarProject|Star":[""],"Switch branch/tag":[""],"Tag":["",""],"Tags":[""],"Target Branch":[""],"The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request.":["編碼階段概述了從第一次提交到創建合併請求的時間。創建第壹個合並請求後,數據將自動添加到此處。"],"The collection of events added to the data gathered for that stage.":["與該階段相關的事件。"],"The fork relationship has been removed.":[""],"The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage.":["議題階段概述了從創建議題到將議題設置裏程碑或將議題添加到議題看板的時間。創建一個議題後,數據將自動添加到此處。"],"The phase of the development lifecycle.":["項目生命週期中的各個階段。"],"The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit.":["計劃階段概述了從議題添加到日程後到推送首次提交的時間。當首次推送提交後,數據將自動添加到此處。"],"The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle.":["生產階段概述了從創建議題到將代碼部署到生產環境的時間。當完成完整的想法到部署生產,數據將自動添加到此處。"],"The project can be accessed by any logged in user.":[""],"The project can be accessed without any authentication.":[""],"The repository for this project does not exist.":[""],"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.":["評審階段概述了從創建合並請求到合併的時間。當創建第壹個合並請求後,數據將自動添加到此處。"],"The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time.":["預發布階段概述了合並請求的合併到部署代碼到生產環境的總時間。當首次部署到生產環境後,數據將自動添加到此處。"],"The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running.":["測試階段概述了GitLab CI為相關合併請求運行每個流水線所需的時間。當第壹個流水線運行完成後,數據將自動添加到此處。"],"The time taken by each data entry gathered by that stage.":["該階段每條數據所花的時間"],"The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6.":["中位數是一個數列中最中間的值。例如在 3、5、9 之間,中位數是 5。在 3、5、7、8 之間,中位數是 (5 + 7)/ 2 = 6。"],"This means you can not push code until you create an empty repository or import existing one.":[""],"Time before an issue gets scheduled":["議題被列入日程表的時間"],"Time before an issue starts implementation":["開始進行編碼前的時間"],"Time between merge request creation and merge/close":["從創建合併請求到被合並或關閉的時間"],"Time until first merge request":["創建第壹個合併請求之前的時間"],"Timeago|%s days ago":["天"],"Timeago|%s days remaining":["天"],"Timeago|%s hours remaining":[""],"Timeago|%s minutes ago":[""],"Timeago|%s minutes remaining":[""],"Timeago|%s months ago":[""],"Timeago|%s months remaining":[""],"Timeago|%s seconds remaining":[""],"Timeago|%s weeks ago":[""],"Timeago|%s weeks remaining":[""],"Timeago|%s years ago":[""],"Timeago|%s years remaining":[""],"Timeago|1 day remaining":["天"],"Timeago|1 hour remaining":[""],"Timeago|1 minute remaining":[""],"Timeago|1 month remaining":[""],"Timeago|1 week remaining":[""],"Timeago|1 year remaining":[""],"Timeago|Past due":[""],"Timeago|a day ago":["天"],"Timeago|a month ago":[""],"Timeago|a week ago":[""],"Timeago|a while":[""],"Timeago|a year ago":[""],"Timeago|about %s hours ago":[""],"Timeago|about a minute ago":[""],"Timeago|about an hour ago":[""],"Timeago|in %s days":["天"],"Timeago|in %s hours":[""],"Timeago|in %s minutes":[""],"Timeago|in %s months":[""],"Timeago|in %s seconds":[""],"Timeago|in %s weeks":[""],"Timeago|in %s years":[""],"Timeago|in 1 day":["天"],"Timeago|in 1 hour":[""],"Timeago|in 1 minute":[""],"Timeago|in 1 month":[""],"Timeago|in 1 week":[""],"Timeago|in 1 year":[""],"Timeago|less than a minute ago":[""],"Time|hr":["小時"],"Time|min":["分鐘"],"Time|s":["秒"],"Total Time":["總時間"],"Total test time for all commits/merges":["所有提交和合併的總測試時間"],"Unstar":[""],"Upload New File":[""],"Upload file":[""],"Use your global notification setting":[""],"VisibilityLevel|Internal":[""],"VisibilityLevel|Private":[""],"VisibilityLevel|Public":[""],"Want to see the data? Please ask an administrator for access.":["權限不足。如需查看相關數據,請向管理員申請權限。"],"We don't have enough data to show this stage.":["該階段的數據不足,無法顯示。"],"Withdraw Access Request":[""],"You are going to remove %{project_name_with_namespace}.\\nRemoved project CANNOT be restored!\\nAre you ABSOLUTELY sure?":[""],"You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?":[""],"You are going to transfer %{project_name_with_namespace} to another owner. Are you ABSOLUTELY sure?":[""],"You can only add files when you are on a branch":[""],"You must sign in to star a project":[""],"You need permission.":["您需要相關的權限。"],"You will not get any notifications via email":[""],"You will only receive notifications for the events you choose":[""],"You will only receive notifications for threads you have participated in":[""],"You will receive notifications for any activity":[""],"You will receive notifications only for comments in which you were @mentioned":[""],"You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account":[""],"You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile":[""],"Your name":[""],"committed":[""],"day":["天"],"notification emails":[""]}}};
\ No newline at end of file +var locales = locales || {}; locales['zh_HK'] = {"domain":"app","locale_data":{"app":{"":{"Project-Id-Version":"gitlab 1.0.0","Report-Msgid-Bugs-To":"","PO-Revision-Date":"2017-05-04 19:24-0500","Last-Translator":"HuangTao <htve@outlook.com>, 2017","Language-Team":"Chinese (Hong Kong) (https://www.transifex.com/gitlab-zh/teams/75177/zh_HK/)","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","Language":"zh_HK","Plural-Forms":"nplurals=1; plural=0;","lang":"zh_HK","domain":"app","plural_forms":"nplurals=1; plural=0;"},"Are you sure you want to delete this pipeline schedule?":[""],"ByAuthor|by":["作者:"],"Cancel":[""],"Commit":["提交"],"Cron Timezone":[""],"Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project.":["週期分析概述了項目從想法到產品實現的各階段所需的時間。"],"CycleAnalyticsStage|Code":["編碼"],"CycleAnalyticsStage|Issue":["議題"],"CycleAnalyticsStage|Plan":["計劃"],"CycleAnalyticsStage|Production":["生產"],"CycleAnalyticsStage|Review":["評審"],"CycleAnalyticsStage|Staging":["預發布"],"CycleAnalyticsStage|Test":["測試"],"Delete":[""],"Deploy":["部署"],"Description":[""],"Edit":[""],"Edit Pipeline Schedule %{id}":[""],"Failed to change the owner":[""],"Failed to remove the pipeline schedule":[""],"Filter":[""],"FirstPushedBy|First":["首次推送"],"FirstPushedBy|pushed by":["推送者:"],"From issue creation until deploy to production":["從創建議題到部署到生產環境"],"From merge request merge until deploy to production":["從合併請求的合併到部署至生產環境"],"Interval Pattern":[""],"Introducing Cycle Analytics":["週期分析簡介"],"Last %d day":["最後 %d 天"],"Last Pipeline":[""],"Limited to showing %d event at most":["最多顯示 %d 個事件"],"Median":["中位數"],"New Issue":["新議題"],"New Pipeline Schedule":[""],"No schedules":[""],"Not available":["不可用"],"Not enough data":["數據不足"],"OpenedNDaysAgo|Opened":["開始於"],"Owner":[""],"Pipeline Health":["流水線健康指標"],"Pipeline Schedule":[""],"Pipeline Schedules":[""],"PipelineSchedules|Activated":[""],"PipelineSchedules|Active":[""],"PipelineSchedules|All":[""],"PipelineSchedules|Inactive":[""],"PipelineSchedules|Next Run":[""],"PipelineSchedules|None":[""],"PipelineSchedules|Provide a short description for this pipeline":[""],"PipelineSchedules|Take ownership":[""],"PipelineSchedules|Target":[""],"ProjectLifecycle|Stage":["項目生命週期"],"Read more":["了解更多"],"Related Commits":["相關的提交"],"Related Deployed Jobs":["相關的部署作業"],"Related Issues":["相關的議題"],"Related Jobs":["相關的作業"],"Related Merge Requests":["相關的合併請求"],"Related Merged Requests":["相關已合併的合並請求"],"Save pipeline schedule":[""],"Schedule a new pipeline":[""],"Select a timezone":[""],"Select target branch":[""],"Showing %d event":["顯示 %d 個事件"],"Target Branch":[""],"The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request.":["編碼階段概述了從第一次提交到創建合併請求的時間。創建第壹個合並請求後,數據將自動添加到此處。"],"The collection of events added to the data gathered for that stage.":["與該階段相關的事件。"],"The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage.":["議題階段概述了從創建議題到將議題設置裏程碑或將議題添加到議題看板的時間。創建一個議題後,數據將自動添加到此處。"],"The phase of the development lifecycle.":["項目生命週期中的各個階段。"],"The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit.":["計劃階段概述了從議題添加到日程後到推送首次提交的時間。當首次推送提交後,數據將自動添加到此處。"],"The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle.":["生產階段概述了從創建議題到將代碼部署到生產環境的時間。當完成完整的想法到部署生產,數據將自動添加到此處。"],"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.":["評審階段概述了從創建合並請求到合併的時間。當創建第壹個合並請求後,數據將自動添加到此處。"],"The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time.":["預發布階段概述了合並請求的合併到部署代碼到生產環境的總時間。當首次部署到生產環境後,數據將自動添加到此處。"],"The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running.":["測試階段概述了GitLab CI為相關合併請求運行每個流水線所需的時間。當第壹個流水線運行完成後,數據將自動添加到此處。"],"The time taken by each data entry gathered by that stage.":["該階段每條數據所花的時間"],"The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6.":["中位數是一個數列中最中間的值。例如在 3、5、9 之間,中位數是 5。在 3、5、7、8 之間,中位數是 (5 + 7)/ 2 = 6。"],"Time before an issue gets scheduled":["議題被列入日程表的時間"],"Time before an issue starts implementation":["開始進行編碼前的時間"],"Time between merge request creation and merge/close":["從創建合併請求到被合並或關閉的時間"],"Time until first merge request":["創建第壹個合併請求之前的時間"],"Time|hr":["小時"],"Time|min":["分鐘"],"Time|s":["秒"],"Total Time":["總時間"],"Total test time for all commits/merges":["所有提交和合併的總測試時間"],"Want to see the data? Please ask an administrator for access.":["權限不足。如需查看相關數據,請向管理員申請權限。"],"We don't have enough data to show this stage.":["該階段的數據不足,無法顯示。"],"You need permission.":["您需要相關的權限。"],"day":["天"]}}};
\ No newline at end of file diff --git a/app/assets/javascripts/locale/zh_TW/app.js b/app/assets/javascripts/locale/zh_TW/app.js index 6b5420015e8..f0fe1e31f18 100644 --- a/app/assets/javascripts/locale/zh_TW/app.js +++ b/app/assets/javascripts/locale/zh_TW/app.js @@ -1 +1 @@ -var locales = locales || {}; locales['zh_TW'] = {"domain":"app","locale_data":{"app":{"":{"Project-Id-Version":"gitlab 1.0.0","Report-Msgid-Bugs-To":"","PO-Revision-Date":"2017-05-04 19:24-0500","Last-Translator":"HuangTao <htve@outlook.com>, 2017","Language-Team":"Chinese (Taiwan) (https://www.transifex.com/gitlab-zh/teams/75177/zh_TW/)","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","Language":"zh_TW","Plural-Forms":"nplurals=1; plural=0;","lang":"zh_TW","domain":"app","plural_forms":"nplurals=1; plural=0;"},"About auto deploy":[""],"Activity":[""],"Add Changelog":[""],"Add Contribution guide":[""],"Add License":[""],"Add an SSH key to your profile to pull or push via SSH.":[""],"Add new directory":[""],"Archived project! Repository is read-only":[""],"Are you sure you want to delete this pipeline schedule?":[""],"Branch":["",""],"Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}":[""],"Branches":[""],"ByAuthor|by":["作者:"],"CI configuration":[""],"Cancel":[""],"Changelog":[""],"Charts":[""],"CiStatusLabel|canceled":[""],"CiStatusLabel|created":[""],"CiStatusLabel|failed":[""],"CiStatusLabel|manual action":[""],"CiStatusLabel|passed":[""],"CiStatusLabel|passed with warnings":[""],"CiStatusLabel|pending":[""],"CiStatusLabel|skipped":[""],"CiStatusLabel|waiting for manual action":[""],"CiStatusText|blocked":[""],"CiStatusText|canceled":[""],"CiStatusText|created":[""],"CiStatusText|failed":[""],"CiStatusText|manual":[""],"CiStatusText|passed":[""],"CiStatusText|pending":[""],"CiStatusText|skipped":[""],"CiStatus|running":[""],"Commit":["送交"],"CommitMessage|Add %{file_name}":["送交"],"Commits":["送交"],"Commits|History":["送交"],"Compare":[""],"Contribution guide":[""],"Contributors":[""],"Copy URL to clipboard":[""],"Copy commit SHA to clipboard":[""],"Create New Directory":[""],"Create directory":[""],"Create empty bare repository":[""],"Create merge request":["相關的合併請求"],"CreateNewFork|Fork":[""],"Cron Timezone":[""],"Custom notification events":[""],"Custom notification levels are the same as participating levels. With custom notification levels you will also receive notifications for select events. To find out more, check out %{notification_link}.":[""],"Cycle Analytics":[""],"Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project.":["週期分析概述了你的專案從想法到產品實現,各階段所需的時間。"],"CycleAnalyticsStage|Code":["程式開發"],"CycleAnalyticsStage|Issue":["議題"],"CycleAnalyticsStage|Plan":["計劃"],"CycleAnalyticsStage|Production":["上線"],"CycleAnalyticsStage|Review":["複閱"],"CycleAnalyticsStage|Staging":["預備"],"CycleAnalyticsStage|Test":["測試"],"Delete":[""],"Deploy":["部署"],"Description":[""],"Directory name":[""],"Don't show again":[""],"Download tar":[""],"Download tar.bz2":[""],"Download tar.gz":[""],"Download zip":[""],"DownloadArtifacts|Download":[""],"DownloadSource|Download":[""],"Edit":[""],"Edit Pipeline Schedule %{id}":[""],"Failed to change the owner":[""],"Failed to remove the pipeline schedule":[""],"Files":[""],"Filter":[""],"Find by path":[""],"Find file":[""],"FirstPushedBy|First":["首次推送"],"FirstPushedBy|pushed by":["推送者:"],"ForkedFromProjectPath|Forked from":[""],"Forks":[""],"From issue creation until deploy to production":["從議題建立至線上部署"],"From merge request merge until deploy to production":["從請求被合併後至線上部署"],"Go to your fork":[""],"GoToYourFork|Fork":[""],"Home":[""],"Housekeeping successfully started":[""],"Import repository":[""],"Interval Pattern":[""],"Introducing Cycle Analytics":["週期分析簡介"],"LFSStatus|Disabled":[""],"LFSStatus|Enabled":[""],"Last %d day":["最後 %d 天"],"Last Pipeline":[""],"Last Update":[""],"Last commit":[""],"Leave group":[""],"Leave project":[""],"Limited to showing %d event at most":["最多顯示 %d 個事件"],"Median":["中位數"],"MissingSSHKeyWarningLink|add an SSH key":[""],"New Issue":["新議題"],"New Pipeline Schedule":[""],"New branch":[""],"New directory":[""],"New file":[""],"New issue":["新議題"],"New merge request":[""],"New snippet":[""],"New tag":[""],"No repository":[""],"No schedules":[""],"Not available":["無法使用"],"Not enough data":["資料不足"],"Notification events":[""],"NotificationEvent|Close issue":[""],"NotificationEvent|Close merge request":[""],"NotificationEvent|Failed pipeline":[""],"NotificationEvent|Merge merge request":[""],"NotificationEvent|New issue":[""],"NotificationEvent|New merge request":[""],"NotificationEvent|New note":[""],"NotificationEvent|Reassign issue":[""],"NotificationEvent|Reassign merge request":[""],"NotificationEvent|Reopen issue":[""],"NotificationEvent|Successful pipeline":[""],"NotificationLevel|Custom":[""],"NotificationLevel|Disabled":[""],"NotificationLevel|Global":[""],"NotificationLevel|On mention":[""],"NotificationLevel|Participate":[""],"NotificationLevel|Watch":[""],"OpenedNDaysAgo|Opened":["開始於"],"Owner":[""],"Pipeline Health":["流水線健康指標"],"Pipeline Schedule":[""],"Pipeline Schedules":[""],"PipelineSchedules|Activated":[""],"PipelineSchedules|Active":[""],"PipelineSchedules|All":[""],"PipelineSchedules|Inactive":[""],"PipelineSchedules|Next Run":[""],"PipelineSchedules|None":[""],"PipelineSchedules|Provide a short description for this pipeline":[""],"PipelineSchedules|Take ownership":[""],"PipelineSchedules|Target":[""],"Project '%{project_name}' queued for deletion.":[""],"Project '%{project_name}' was successfully created.":[""],"Project '%{project_name}' was successfully updated.":[""],"Project '%{project_name}' will be deleted.":[""],"Project access must be granted explicitly to each user.":[""],"Project export could not be deleted.":[""],"Project export has been deleted.":[""],"Project export link has expired. Please generate a new export from your project settings.":[""],"Project export started. A download link will be sent by email.":[""],"Project home":[""],"ProjectFeature|Disabled":[""],"ProjectFeature|Everyone with access":[""],"ProjectFeature|Only team members":[""],"ProjectFileTree|Name":[""],"ProjectLastActivity|Never":[""],"ProjectLifecycle|Stage":["專案生命週期"],"ProjectNetworkGraph|Graph":[""],"Read more":["了解更多"],"Readme":["了解更多"],"RefSwitcher|Branches":[""],"RefSwitcher|Tags":[""],"Related Commits":["相關的送交"],"Related Deployed Jobs":["相關的部署作業"],"Related Issues":["相關的議題"],"Related Jobs":["相關的作業"],"Related Merge Requests":["相關的合併請求"],"Related Merged Requests":["相關已合併的請求"],"Remind later":[""],"Remove project":[""],"Request Access":[""],"Save pipeline schedule":[""],"Schedule a new pipeline":[""],"Search branches and tags":[""],"Select Archive Format":[""],"Select a timezone":[""],"Select target branch":[""],"Set a password on your account to pull or push via %{protocol}":[""],"Set up CI":[""],"Set up Koding":[""],"Set up auto deploy":[""],"SetPasswordToCloneLink|set a password":[""],"Showing %d event":["顯示 %d 個事件"],"Source code":[""],"StarProject|Star":[""],"Switch branch/tag":[""],"Tag":["",""],"Tags":[""],"Target Branch":[""],"The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request.":["程式開發階段顯示從第一次送交到建立合併請求的時間。建立第一個合併請求後,資料將自動填入。"],"The collection of events added to the data gathered for that stage.":["與該階段相關的事件。"],"The fork relationship has been removed.":[""],"The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage.":["議題階段顯示從議題建立到設置里程碑、或將該議題加至議題看板的時間。建立第一個議題後,資料將自動填入。"],"The phase of the development lifecycle.":["專案開發生命週期的各個階段。"],"The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit.":["計劃階段顯示從議題添加到日程後至推送第一個送交的時間。當第一次推送送交後,資料將自動填入。"],"The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle.":["上線階段顯示從建立一個議題到部署程式至線上的總時間。當完成從想法到產品實現的循環後,資料將自動填入。"],"The project can be accessed by any logged in user.":[""],"The project can be accessed without any authentication.":[""],"The repository for this project does not exist.":[""],"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.":["複閱階段顯示從合併請求建立後至被合併的時間。當建立第一個合併請求後,資料將自動填入。"],"The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time.":["預備階段顯示從合併請求被合併後至部署上線的時間。當第一次部署上線後,資料將自動填入。"],"The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running.":["測試階段顯示相關合併請求的流水線所花的時間。當第一個流水線運作完畢後,資料將自動填入。"],"The time taken by each data entry gathered by that stage.":["每筆該階段相關資料所花的時間。"],"The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6.":["中位數是一個數列中最中間的值。例如在 3、5、9 之間,中位數是 5。在 3、5、7、8 之間,中位數是 (5 + 7)/ 2 = 6。"],"This means you can not push code until you create an empty repository or import existing one.":[""],"Time before an issue gets scheduled":["議題被列入日程表的時間"],"Time before an issue starts implementation":["議題等待開始實作的時間"],"Time between merge request creation and merge/close":["合併請求被合併或是關閉的時間"],"Time until first merge request":["第一個合併請求被建立前的時間"],"Timeago|%s days ago":["天"],"Timeago|%s days remaining":["天"],"Timeago|%s hours remaining":[""],"Timeago|%s minutes ago":[""],"Timeago|%s minutes remaining":[""],"Timeago|%s months ago":[""],"Timeago|%s months remaining":[""],"Timeago|%s seconds remaining":[""],"Timeago|%s weeks ago":[""],"Timeago|%s weeks remaining":[""],"Timeago|%s years ago":[""],"Timeago|%s years remaining":[""],"Timeago|1 day remaining":["天"],"Timeago|1 hour remaining":[""],"Timeago|1 minute remaining":[""],"Timeago|1 month remaining":[""],"Timeago|1 week remaining":[""],"Timeago|1 year remaining":[""],"Timeago|Past due":[""],"Timeago|a day ago":["天"],"Timeago|a month ago":[""],"Timeago|a week ago":[""],"Timeago|a while":[""],"Timeago|a year ago":[""],"Timeago|about %s hours ago":[""],"Timeago|about a minute ago":[""],"Timeago|about an hour ago":[""],"Timeago|in %s days":["天"],"Timeago|in %s hours":[""],"Timeago|in %s minutes":[""],"Timeago|in %s months":[""],"Timeago|in %s seconds":[""],"Timeago|in %s weeks":[""],"Timeago|in %s years":[""],"Timeago|in 1 day":["天"],"Timeago|in 1 hour":[""],"Timeago|in 1 minute":[""],"Timeago|in 1 month":[""],"Timeago|in 1 week":[""],"Timeago|in 1 year":[""],"Timeago|less than a minute ago":[""],"Time|hr":["小時"],"Time|min":["分鐘"],"Time|s":["秒"],"Total Time":["總時間"],"Total test time for all commits/merges":["所有送交和合併的總測試時間"],"Unstar":[""],"Upload New File":[""],"Upload file":[""],"Use your global notification setting":[""],"VisibilityLevel|Internal":[""],"VisibilityLevel|Private":[""],"VisibilityLevel|Public":[""],"Want to see the data? Please ask an administrator for access.":["權限不足。如需查看相關資料,請向管理員申請權限。"],"We don't have enough data to show this stage.":["因該階段的資料不足而無法顯示相關資訊"],"Withdraw Access Request":[""],"You are going to remove %{project_name_with_namespace}.\\nRemoved project CANNOT be restored!\\nAre you ABSOLUTELY sure?":[""],"You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?":[""],"You are going to transfer %{project_name_with_namespace} to another owner. Are you ABSOLUTELY sure?":[""],"You can only add files when you are on a branch":[""],"You must sign in to star a project":[""],"You need permission.":["您需要相關的權限。"],"You will not get any notifications via email":[""],"You will only receive notifications for the events you choose":[""],"You will only receive notifications for threads you have participated in":[""],"You will receive notifications for any activity":[""],"You will receive notifications only for comments in which you were @mentioned":[""],"You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account":[""],"You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile":[""],"Your name":[""],"committed":[""],"day":["天"],"notification emails":[""]}}};
\ No newline at end of file +var locales = locales || {}; locales['zh_TW'] = {"domain":"app","locale_data":{"app":{"":{"Project-Id-Version":"gitlab 1.0.0","Report-Msgid-Bugs-To":"","PO-Revision-Date":"2017-05-04 19:24-0500","Last-Translator":"HuangTao <htve@outlook.com>, 2017","Language-Team":"Chinese (Taiwan) (https://www.transifex.com/gitlab-zh/teams/75177/zh_TW/)","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","Language":"zh_TW","Plural-Forms":"nplurals=1; plural=0;","lang":"zh_TW","domain":"app","plural_forms":"nplurals=1; plural=0;"},"Are you sure you want to delete this pipeline schedule?":[""],"ByAuthor|by":["作者:"],"Cancel":[""],"Commit":["送交"],"Cron Timezone":[""],"Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project.":["週期分析概述了你的專案從想法到產品實現,各階段所需的時間。"],"CycleAnalyticsStage|Code":["程式開發"],"CycleAnalyticsStage|Issue":["議題"],"CycleAnalyticsStage|Plan":["計劃"],"CycleAnalyticsStage|Production":["上線"],"CycleAnalyticsStage|Review":["複閱"],"CycleAnalyticsStage|Staging":["預備"],"CycleAnalyticsStage|Test":["測試"],"Delete":[""],"Deploy":["部署"],"Description":[""],"Edit":[""],"Edit Pipeline Schedule %{id}":[""],"Failed to change the owner":[""],"Failed to remove the pipeline schedule":[""],"Filter":[""],"FirstPushedBy|First":["首次推送"],"FirstPushedBy|pushed by":["推送者:"],"From issue creation until deploy to production":["從議題建立至線上部署"],"From merge request merge until deploy to production":["從請求被合併後至線上部署"],"Interval Pattern":[""],"Introducing Cycle Analytics":["週期分析簡介"],"Last %d day":["最後 %d 天"],"Last Pipeline":[""],"Limited to showing %d event at most":["最多顯示 %d 個事件"],"Median":["中位數"],"New Issue":["新議題"],"New Pipeline Schedule":[""],"No schedules":[""],"Not available":["無法使用"],"Not enough data":["資料不足"],"OpenedNDaysAgo|Opened":["開始於"],"Owner":[""],"Pipeline Health":["流水線健康指標"],"Pipeline Schedule":[""],"Pipeline Schedules":[""],"PipelineSchedules|Activated":[""],"PipelineSchedules|Active":[""],"PipelineSchedules|All":[""],"PipelineSchedules|Inactive":[""],"PipelineSchedules|Next Run":[""],"PipelineSchedules|None":[""],"PipelineSchedules|Provide a short description for this pipeline":[""],"PipelineSchedules|Take ownership":[""],"PipelineSchedules|Target":[""],"ProjectLifecycle|Stage":["專案生命週期"],"Read more":["了解更多"],"Related Commits":["相關的送交"],"Related Deployed Jobs":["相關的部署作業"],"Related Issues":["相關的議題"],"Related Jobs":["相關的作業"],"Related Merge Requests":["相關的合併請求"],"Related Merged Requests":["相關已合併的請求"],"Save pipeline schedule":[""],"Schedule a new pipeline":[""],"Select a timezone":[""],"Select target branch":[""],"Showing %d event":["顯示 %d 個事件"],"Target Branch":[""],"The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request.":["程式開發階段顯示從第一次送交到建立合併請求的時間。建立第一個合併請求後,資料將自動填入。"],"The collection of events added to the data gathered for that stage.":["與該階段相關的事件。"],"The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage.":["議題階段顯示從議題建立到設置里程碑、或將該議題加至議題看板的時間。建立第一個議題後,資料將自動填入。"],"The phase of the development lifecycle.":["專案開發生命週期的各個階段。"],"The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit.":["計劃階段顯示從議題添加到日程後至推送第一個送交的時間。當第一次推送送交後,資料將自動填入。"],"The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle.":["上線階段顯示從建立一個議題到部署程式至線上的總時間。當完成從想法到產品實現的循環後,資料將自動填入。"],"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.":["複閱階段顯示從合併請求建立後至被合併的時間。當建立第一個合併請求後,資料將自動填入。"],"The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time.":["預備階段顯示從合併請求被合併後至部署上線的時間。當第一次部署上線後,資料將自動填入。"],"The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running.":["測試階段顯示相關合併請求的流水線所花的時間。當第一個流水線運作完畢後,資料將自動填入。"],"The time taken by each data entry gathered by that stage.":["每筆該階段相關資料所花的時間。"],"The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6.":["中位數是一個數列中最中間的值。例如在 3、5、9 之間,中位數是 5。在 3、5、7、8 之間,中位數是 (5 + 7)/ 2 = 6。"],"Time before an issue gets scheduled":["議題被列入日程表的時間"],"Time before an issue starts implementation":["議題等待開始實作的時間"],"Time between merge request creation and merge/close":["合併請求被合併或是關閉的時間"],"Time until first merge request":["第一個合併請求被建立前的時間"],"Time|hr":["小時"],"Time|min":["分鐘"],"Time|s":["秒"],"Total Time":["總時間"],"Total test time for all commits/merges":["所有送交和合併的總測試時間"],"Want to see the data? Please ask an administrator for access.":["權限不足。如需查看相關資料,請向管理員申請權限。"],"We don't have enough data to show this stage.":["因該階段的資料不足而無法顯示相關資訊"],"You need permission.":["您需要相關的權限。"],"day":["天"]}}};
\ No newline at end of file diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js index fe367d0c42a..ed7629948ca 100644 --- a/app/assets/javascripts/main.js +++ b/app/assets/javascripts/main.js @@ -39,10 +39,6 @@ import './shortcuts_network'; // behaviors import './behaviors/'; -// blob -import './blob/create_branch_dropdown'; -import './blob/target_branch_dropdown'; - // templates import './templates/issuable_template_selector'; import './templates/issuable_template_selectors'; diff --git a/app/assets/javascripts/new_commit_form.js b/app/assets/javascripts/new_commit_form.js index 658879607e2..04073ef7270 100644 --- a/app/assets/javascripts/new_commit_form.js +++ b/app/assets/javascripts/new_commit_form.js @@ -1,23 +1,20 @@ /* eslint-disable func-names, space-before-function-paren, no-var, prefer-rest-params, wrap-iife, no-return-assign, max-len */ (function() { this.NewCommitForm = (function() { - function NewCommitForm(form, targetBranchName = 'target_branch') { + function NewCommitForm(form) { this.form = form; - this.targetBranchName = targetBranchName; this.renderDestination = this.renderDestination.bind(this); - this.targetBranchDropdown = form.find('button.js-target-branch'); + this.branchName = form.find('.js-branch-name'); this.originalBranch = form.find('.js-original-branch'); this.createMergeRequest = form.find('.js-create-merge-request'); this.createMergeRequestContainer = form.find('.js-create-merge-request-container'); - this.targetBranchDropdown.on('change.branch', this.renderDestination); + this.branchName.keyup(this.renderDestination); this.renderDestination(); } NewCommitForm.prototype.renderDestination = function() { var different; - var targetBranch = this.form.find(`input[name="${this.targetBranchName}"]`); - - different = targetBranch.val() !== this.originalBranch.val(); + different = this.branchName.val() !== this.originalBranch.val(); if (different) { this.createMergeRequestContainer.show(); if (!this.wasDifferent) { diff --git a/app/assets/javascripts/pipelines/components/header_component.vue b/app/assets/javascripts/pipelines/components/header_component.vue index 4f6c5c177cf..2a1ecac3707 100644 --- a/app/assets/javascripts/pipelines/components/header_component.vue +++ b/app/assets/javascripts/pipelines/components/header_component.vue @@ -91,7 +91,7 @@ export default { @actionClicked="postAction" /> <loading-icon - v-else + v-if="isLoading" size="2"/> </div> </template> diff --git a/app/assets/javascripts/pipelines/components/nav_controls.js b/app/assets/javascripts/pipelines/components/nav_controls.js deleted file mode 100644 index 6aa10531034..00000000000 --- a/app/assets/javascripts/pipelines/components/nav_controls.js +++ /dev/null @@ -1,52 +0,0 @@ -export default { - props: { - newPipelinePath: { - type: String, - required: true, - }, - - hasCiEnabled: { - type: Boolean, - required: true, - }, - - helpPagePath: { - type: String, - required: true, - }, - - ciLintPath: { - type: String, - required: true, - }, - - canCreatePipeline: { - type: Boolean, - required: true, - }, - }, - - template: ` - <div class="nav-controls"> - <a - v-if="canCreatePipeline" - :href="newPipelinePath" - class="btn btn-create"> - Run Pipeline - </a> - - <a - v-if="!hasCiEnabled" - :href="helpPagePath" - class="btn btn-info"> - Get started with Pipelines - </a> - - <a - :href="ciLintPath" - class="btn btn-default"> - CI Lint - </a> - </div> - `, -}; diff --git a/app/assets/javascripts/pipelines/components/nav_controls.vue b/app/assets/javascripts/pipelines/components/nav_controls.vue new file mode 100644 index 00000000000..632fc167f2b --- /dev/null +++ b/app/assets/javascripts/pipelines/components/nav_controls.vue @@ -0,0 +1,54 @@ +<script> +export default { + name: 'PipelineNavControls', + props: { + newPipelinePath: { + type: String, + required: true, + }, + + hasCiEnabled: { + type: Boolean, + required: true, + }, + + helpPagePath: { + type: String, + required: true, + }, + + ciLintPath: { + type: String, + required: true, + }, + + canCreatePipeline: { + type: Boolean, + required: true, + }, + }, +}; +</script> +<template> + <div class="nav-controls"> + <a + v-if="canCreatePipeline" + :href="newPipelinePath" + class="btn btn-create"> + Run Pipeline + </a> + + <a + v-if="!hasCiEnabled" + :href="helpPagePath" + class="btn btn-info"> + Get started with Pipelines + </a> + + <a + :href="ciLintPath" + class="btn btn-default"> + CI Lint + </a> + </div> +</template> diff --git a/app/assets/javascripts/pipelines/components/navigation_tabs.js b/app/assets/javascripts/pipelines/components/navigation_tabs.js deleted file mode 100644 index 1626ae17a30..00000000000 --- a/app/assets/javascripts/pipelines/components/navigation_tabs.js +++ /dev/null @@ -1,72 +0,0 @@ -export default { - props: { - scope: { - type: String, - required: true, - }, - - count: { - type: Object, - required: true, - }, - - paths: { - type: Object, - required: true, - }, - }, - - mounted() { - $(document).trigger('init.scrolling-tabs'); - }, - - template: ` - <ul class="nav-links scrolling-tabs"> - <li - class="js-pipelines-tab-all" - :class="{ 'active': scope === 'all'}"> - <a :href="paths.allPath"> - All - <span class="badge js-totalbuilds-count"> - {{count.all}} - </span> - </a> - </li> - <li class="js-pipelines-tab-pending" - :class="{ 'active': scope === 'pending'}"> - <a :href="paths.pendingPath"> - Pending - <span class="badge"> - {{count.pending}} - </span> - </a> - </li> - <li class="js-pipelines-tab-running" - :class="{ 'active': scope === 'running'}"> - <a :href="paths.runningPath"> - Running - <span class="badge"> - {{count.running}} - </span> - </a> - </li> - <li class="js-pipelines-tab-finished" - :class="{ 'active': scope === 'finished'}"> - <a :href="paths.finishedPath"> - Finished - <span class="badge"> - {{count.finished}} - </span> - </a> - </li> - <li class="js-pipelines-tab-branches" - :class="{ 'active': scope === 'branches'}"> - <a :href="paths.branchesPath">Branches</a> - </li> - <li class="js-pipelines-tab-tags" - :class="{ 'active': scope === 'tags'}"> - <a :href="paths.tagsPath">Tags</a> - </li> - </ul> - `, -}; diff --git a/app/assets/javascripts/pipelines/components/navigation_tabs.vue b/app/assets/javascripts/pipelines/components/navigation_tabs.vue new file mode 100644 index 00000000000..d2f6d47f043 --- /dev/null +++ b/app/assets/javascripts/pipelines/components/navigation_tabs.vue @@ -0,0 +1,76 @@ +<script> +export default { + name: 'PipelineNavigationTabs', + props: { + scope: { + type: String, + required: true, + }, + count: { + type: Object, + required: true, + }, + paths: { + type: Object, + required: true, + }, + }, + mounted() { + $(document).trigger('init.scrolling-tabs'); + }, +}; +</script> +<template> + <ul class="nav-links scrolling-tabs"> + <li + class="js-pipelines-tab-all" + :class="{ active: scope === 'all'}"> + <a :href="paths.allPath"> + All + <span class="badge js-totalbuilds-count"> + {{count.all}} + </span> + </a> + </li> + <li + class="js-pipelines-tab-pending" + :class="{ active: scope === 'pending'}"> + <a :href="paths.pendingPath"> + Pending + <span class="badge"> + {{count.pending}} + </span> + </a> + </li> + <li + class="js-pipelines-tab-running" + :class="{ active: scope === 'running'}"> + <a :href="paths.runningPath"> + Running + <span class="badge"> + {{count.running}} + </span> + </a> + </li> + <li + class="js-pipelines-tab-finished" + :class="{ active: scope === 'finished'}"> + <a :href="paths.finishedPath"> + Finished + <span class="badge"> + {{count.finished}} + </span> + </a> + </li> + <li + class="js-pipelines-tab-branches" + :class="{ active: scope === 'branches'}"> + <a :href="paths.branchesPath">Branches</a> + </li> + <li + class="js-pipelines-tab-tags" + :class="{ active: scope === 'tags'}"> + <a :href="paths.tagsPath">Tags</a> + </li> + </ul> +</template> diff --git a/app/assets/javascripts/pipelines/pipelines.js b/app/assets/javascripts/pipelines/pipelines.js index 23b967b4b32..b530461837c 100644 --- a/app/assets/javascripts/pipelines/pipelines.js +++ b/app/assets/javascripts/pipelines/pipelines.js @@ -5,8 +5,8 @@ import pipelinesTableComponent from '../vue_shared/components/pipelines_table'; import tablePagination from '../vue_shared/components/table_pagination.vue'; import emptyState from './components/empty_state.vue'; import errorState from './components/error_state.vue'; -import navigationTabs from './components/navigation_tabs'; -import navigationControls from './components/nav_controls'; +import navigationTabs from './components/navigation_tabs.vue'; +import navigationControls from './components/nav_controls.vue'; import loadingIcon from '../vue_shared/components/loading_icon.vue'; import Poll from '../lib/utils/poll'; diff --git a/app/assets/javascripts/vue_shared/components/header_ci_component.vue b/app/assets/javascripts/vue_shared/components/header_ci_component.vue index fe6d6a792e7..1d4d90f75b6 100644 --- a/app/assets/javascripts/vue_shared/components/header_ci_component.vue +++ b/app/assets/javascripts/vue_shared/components/header_ci_component.vue @@ -40,6 +40,11 @@ export default { required: false, default: () => [], }, + hasSidebarButton: { + type: Boolean, + required: false, + default: false, + }, }, mixins: [ @@ -66,8 +71,9 @@ export default { }, }; </script> + <template> - <header class="page-content-header"> + <header class="page-content-header ci-header-container"> <section class="header-main-content"> <ci-icon-badge :status="status" /> @@ -102,7 +108,7 @@ export default { </section> <section - class="header-action-button nav-controls" + class="header-action-buttons" v-if="actions.length"> <template v-for="action in actions"> @@ -113,6 +119,15 @@ export default { {{action.label}} </a> + <a + v-if="action.type === 'ujs-link'" + :href="action.path" + data-method="post" + rel="nofollow" + :class="action.cssClass"> + {{action.label}} + </a> + <button v-else="action.type === 'button'" @click="onClickAction(action)" @@ -120,7 +135,6 @@ export default { :class="action.cssClass" type="button"> {{action.label}} - <i v-show="action.isLoading" class="fa fa-spin fa-spinner" @@ -128,6 +142,18 @@ export default { </i> </button> </template> + <button + v-if="hasSidebarButton" + type="button" + class="btn btn-default visible-xs-block visible-sm-block sidebar-toggle-btn js-sidebar-build-toggle js-sidebar-build-toggle-header" + aria-label="Toggle Sidebar" + id="toggleSidebar"> + <i + class="fa fa-angle-double-left" + aria-hidden="true" + aria-labelledby="toggleSidebar"> + </i> + </button> </section> </header> </template> diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss index 17f1dc2f479..cba890ce831 100644 --- a/app/assets/stylesheets/framework/dropdowns.scss +++ b/app/assets/stylesheets/framework/dropdowns.scss @@ -48,6 +48,10 @@ @include chevron-active; border-color: $gray-darkest; } + + [data-toggle="dropdown"] { + outline: 0; + } } .dropdown-toggle { @@ -109,6 +113,7 @@ &:focus:active { @include chevron-active; border-color: $dropdown-toggle-active-border-color; + outline: 0; } } diff --git a/app/assets/stylesheets/pages/builds.scss b/app/assets/stylesheets/pages/builds.scss index e35558ad8e8..203fd6d07e4 100644 --- a/app/assets/stylesheets/pages/builds.scss +++ b/app/assets/stylesheets/pages/builds.scss @@ -71,7 +71,9 @@ height: 35px; display: flex; justify-content: flex-end; - border-bottom: 1px outset $white-light; + background: $gray-light; + border: 1px solid $gray-normal; + color: $gl-text-color; .truncated-info { margin: 0 auto; @@ -82,7 +84,7 @@ } .raw-link { - color: inherit; + color: $gl-text-color; margin-left: 5px; text-decoration: underline; } @@ -93,17 +95,25 @@ display: flex; align-self: center; font-size: 15px; + margin-bottom: 4px; svg { height: 15px; display: block; - fill: $white-light; + fill: $gl-text-color; } - a, + .controllers-buttons, .btn-scroll { - margin: 0 8px; - color: $white-light; + color: $gl-text-color; + height: 15px; + vertical-align: middle; + padding: 0; + width: 12px; + } + + .controllers-buttons { + margin: 1px 10px; } .btn-scroll.animate { @@ -137,21 +147,22 @@ top: 35px; left: 10px; bottom: 0; - overflow-y: hidden; - padding-bottom: 20px; - padding-right: 20px; + overflow-y: scroll; + overflow-x: hidden; + padding: 10px 20px 20px 5px; } .environment-information { - background-color: $gray-light; border: 1px solid $border-color; - padding: 12px $gl-padding; + padding: 8px $gl-padding 12px; border-radius: $border-radius-default; svg { position: relative; - top: 1px; + top: 5px; margin-right: 5px; + width: 22px; + height: 22px; } } @@ -165,54 +176,31 @@ } } -.status-message { - display: inline-block; - color: $white-light; - - .status-icon { - display: inline-block; - width: 16px; - height: 33px; +.build-header { + .ci-header-container, + .header-action-buttons { + display: flex; } - .status-text { - float: left; - opacity: 0; - margin-right: 10px; - font-weight: normal; - line-height: 1.8; - transition: opacity 1s ease-out; - - &.animate { - animation: fade-out-status 2s ease; - } + .ci-header-container { + min-height: 54px; } - &:hover .status-text { - opacity: 1; + .page-content-header { + padding: 10px 0 9px; } -} - -.build-header { - position: relative; - padding: 0; - display: flex; - min-height: 58px; - align-items: center; - - @media (max-width: $screen-sm-max) { - padding-right: 40px; - margin-top: 6px; - .btn-inverted { - display: none; + .header-action-buttons { + @media (max-width: $screen-xs-max) { + .sidebar-toggle-btn { + margin-top: 0; + margin-left: 10px; + max-height: 34px; + } } } .header-content { - flex: 1; - line-height: 1.8; - a { color: $gl-text-color; @@ -235,7 +223,7 @@ } .right-sidebar.build-sidebar { - padding: $gl-padding 0; + padding: 0; &.right-sidebar-collapsed { display: none; @@ -248,6 +236,10 @@ .block { width: 100%; + &:last-child { + border-bottom: 1px solid $border-gray-normal; + } + &.coverage { padding: 0 16px 11px; } @@ -257,34 +249,39 @@ } } - .js-build-variable { + .trigger-build-variable { color: $code-color; } - .js-build-value { + .trigger-build-value { padding: 2px 4px; color: $black; background-color: $white-light; } - .build-sidebar-header { - padding: 0 $gl-padding $gl-padding; - - .gutter-toggle { - margin-top: 0; - } + .label { + margin-left: 2px; } .retry-link { - color: $gl-link-color; display: none; - &:hover { - text-decoration: underline; + .btn-inverted-secondary { + color: $blue-500; + + &:hover { + color: $white-light; + } } @media (max-width: $screen-sm-max) { display: block; + + .btn { + i { + margin-left: 5px; + } + } } } @@ -308,6 +305,12 @@ left: $gl-padding; width: auto; } + + svg { + position: relative; + top: 2px; + margin-right: 3px; + } } .builds-container { @@ -369,6 +372,10 @@ } } } + + .link-commit { + color: $blue-600; + } } .build-sidebar { diff --git a/app/assets/stylesheets/pages/login.scss b/app/assets/stylesheets/pages/login.scss index 8249e02b64a..3cbe8dededb 100644 --- a/app/assets/stylesheets/pages/login.scss +++ b/app/assets/stylesheets/pages/login.scss @@ -128,6 +128,7 @@ a { width: 100%; font-size: 18px; + margin-right: 0; &:hover { border: 1px solid transparent; @@ -140,6 +141,7 @@ a { border: none; border-bottom: 2px solid $link-underline-blue; + margin-right: 0; color: $black; &:hover { diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss index e622e5c3f4b..a0442463390 100644 --- a/app/assets/stylesheets/pages/notes.scss +++ b/app/assets/stylesheets/pages/notes.scss @@ -462,7 +462,6 @@ ul.notes { .more-actions-toggle { padding: 0; - outline: none; &:hover .icon, &:focus .icon { diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index 58b458cd837..cd9382e8de5 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -545,12 +545,13 @@ border: 1px solid $border-color; border-radius: 30px; background-color: $white-light; + } - &:hover { - background-color: $stage-hover-bg; - border: 1px solid $stage-hover-border; - color: $gl-text-color; - } + a.build-content:hover, + button.build-content:hover { + background-color: $stage-hover-bg; + border: 1px solid $stage-hover-border; + color: $gl-text-color; } @@ -985,10 +986,17 @@ } } -.pipeline-header-container { +.ci-header-container { min-height: 55px; .text-center { padding-top: 12px; } + + .header-action-buttons { + .btn, + a { + margin-left: 10px; + } + } } diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index a2f781a6a6e..062665bc634 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -769,8 +769,7 @@ pre.light-well { } .project-refs-form .dropdown-menu, -.dropdown-menu-projects, -.dropdown-menu-branches { +.dropdown-menu-projects { width: 300px; @media (min-width: $screen-sm-min) { diff --git a/app/assets/stylesheets/pages/status.scss b/app/assets/stylesheets/pages/status.scss index 4a284247143..4ed8617b6a3 100644 --- a/app/assets/stylesheets/pages/status.scss +++ b/app/assets/stylesheets/pages/status.scss @@ -19,8 +19,7 @@ overflow: visible; } - &.ci-failed, - &.ci-failed_with_warnings { + &.ci-failed { color: $red-500; border-color: $red-500; @@ -39,8 +38,7 @@ } } - &.ci-success, - &.ci-success_with_warnings { + &.ci-success { color: $green-600; border-color: $green-500; @@ -73,7 +71,9 @@ } } - &.ci-pending { + &.ci-pending, + &.ci-success_with_warnings, + &.ci-failed_with_warnings { color: $orange-600; border-color: $orange-500; diff --git a/app/controllers/concerns/creates_commit.rb b/app/controllers/concerns/creates_commit.rb index 183eb00ef67..36ad307a93b 100644 --- a/app/controllers/concerns/creates_commit.rb +++ b/app/controllers/concerns/creates_commit.rb @@ -1,11 +1,6 @@ module CreatesCommit extend ActiveSupport::Concern - def set_start_branch_to_branch_name - branch_exists = @repository.find_branch(@branch_name) - @start_branch = @branch_name if branch_exists - end - def create_commit(service, success_path:, failure_path:, failure_view: nil, success_notice: nil) if can?(current_user, :push_code, @project) @project_to_commit_into = @project diff --git a/app/controllers/concerns/milestone_actions.rb b/app/controllers/concerns/milestone_actions.rb index 3e2a0fe4f8b..b2536a1c949 100644 --- a/app/controllers/concerns/milestone_actions.rb +++ b/app/controllers/concerns/milestone_actions.rb @@ -46,8 +46,10 @@ module MilestoneActions def milestone_redirect_path if @project namespace_project_milestone_path(@project.namespace, @project, @milestone) - else + elsif @group group_milestone_path(@group, @milestone.safe_title, title: @milestone.title) + else + dashboard_milestone_path(@milestone.safe_title, title: @milestone.title) end end end diff --git a/app/controllers/concerns/spammable_actions.rb b/app/controllers/concerns/spammable_actions.rb index d0a692070d9..b68d76aeff0 100644 --- a/app/controllers/concerns/spammable_actions.rb +++ b/app/controllers/concerns/spammable_actions.rb @@ -17,10 +17,18 @@ module SpammableActions private + def ensure_spam_config_loaded! + return @spam_config_loaded if defined?(@spam_config_loaded) + + @spam_config_loaded = Gitlab::Recaptcha.load_configurations! + end + def recaptcha_check_with_fallback(&fallback) if spammable.valid? redirect_to spammable elsif render_recaptcha? + ensure_spam_config_loaded! + if params[:recaptcha_verification] flash[:alert] = 'There was an error with the reCAPTCHA. Please solve the reCAPTCHA again.' end @@ -35,7 +43,7 @@ module SpammableActions default_params = { request: request } recaptcha_check = params[:recaptcha_verification] && - Gitlab::Recaptcha.load_configurations! && + ensure_spam_config_loaded! && verify_recaptcha return default_params unless recaptcha_check diff --git a/app/controllers/dashboard/milestones_controller.rb b/app/controllers/dashboard/milestones_controller.rb index df528d10f6e..751dbbd8e96 100644 --- a/app/controllers/dashboard/milestones_controller.rb +++ b/app/controllers/dashboard/milestones_controller.rb @@ -1,6 +1,8 @@ class Dashboard::MilestonesController < Dashboard::ApplicationController + include MilestoneActions + before_action :projects - before_action :milestone, only: [:show] + before_action :milestone, only: [:show, :merge_requests, :participants, :labels] def index respond_to do |format| diff --git a/app/controllers/dashboard/todos_controller.rb b/app/controllers/dashboard/todos_controller.rb index 623392c1240..28c90548cc1 100644 --- a/app/controllers/dashboard/todos_controller.rb +++ b/app/controllers/dashboard/todos_controller.rb @@ -47,11 +47,6 @@ class Dashboard::TodosController < Dashboard::ApplicationController render json: todos_counts end - # Used in TodosHelper also - def self.todos_count_format(count) - count >= 100 ? '99+' : count - end - private def find_todos diff --git a/app/controllers/jwt_controller.rb b/app/controllers/jwt_controller.rb index c585d26df77..11db164b3fa 100644 --- a/app/controllers/jwt_controller.rb +++ b/app/controllers/jwt_controller.rb @@ -39,7 +39,7 @@ class JwtController < ApplicationController errors: [ { code: 'UNAUTHORIZED', message: "HTTP Basic: Access denied\n" \ - "You have 2FA enabled, please use a personal access token for Git over HTTP.\n" \ + "You must use a personal access token with 'api' scope for Git over HTTP.\n" \ "You can generate one at #{profile_personal_access_tokens_url}" } ] }, status: 401 diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb index d8d14ea1fed..66e6a9a451c 100644 --- a/app/controllers/projects/blob_controller.rb +++ b/app/controllers/projects/blob_controller.rb @@ -26,8 +26,6 @@ class Projects::BlobController < Projects::ApplicationController end def create - set_start_branch_to_branch_name - create_commit(Files::CreateService, success_notice: "The file has been successfully created.", success_path: -> { namespace_project_blob_path(@project.namespace, @project, File.join(@branch_name, @file_path)) }, failure_view: :new, diff --git a/app/controllers/projects/branches_controller.rb b/app/controllers/projects/branches_controller.rb index d8ed470e461..70b06cfd9b4 100644 --- a/app/controllers/projects/branches_controller.rb +++ b/app/controllers/projects/branches_controller.rb @@ -10,10 +10,10 @@ class Projects::BranchesController < Projects::ApplicationController def index @sort = params[:sort].presence || sort_value_name @branches = BranchesFinder.new(@repository, params).execute + @branches = Kaminari.paginate_array(@branches).page(params[:page]) respond_to do |format| format.html do - paginate_branches @refs_pipelines = @project.pipelines.latest_successful_for_refs(@branches.map(&:name)) @max_commits = @branches.reduce(0) do |memo, branch| @@ -22,7 +22,6 @@ class Projects::BranchesController < Projects::ApplicationController end end format.json do - paginate_branches unless params[:show_all] render json: @branches.map(&:name) end end @@ -106,10 +105,6 @@ class Projects::BranchesController < Projects::ApplicationController end end - def paginate_branches - @branches = Kaminari.paginate_array(@branches).page(params[:page]) - end - def url_to_autodeploy_setup(project, branch_name) namespace_project_new_blob_path( project.namespace, diff --git a/app/controllers/projects/git_http_client_controller.rb b/app/controllers/projects/git_http_client_controller.rb index 7f3205a8001..928f17e6a8e 100644 --- a/app/controllers/projects/git_http_client_controller.rb +++ b/app/controllers/projects/git_http_client_controller.rb @@ -104,7 +104,7 @@ class Projects::GitHttpClientController < Projects::ApplicationController def render_missing_personal_token render plain: "HTTP Basic: Access denied\n" \ - "You have 2FA enabled, please use a personal access token for Git over HTTP.\n" \ + "You must use a personal access token with 'api' scope for Git over HTTP.\n" \ "You can generate one at #{profile_personal_access_tokens_url}", status: 401 end diff --git a/app/controllers/projects/tree_controller.rb b/app/controllers/projects/tree_controller.rb index f8eb8e00a5d..266a15c1cf9 100644 --- a/app/controllers/projects/tree_controller.rb +++ b/app/controllers/projects/tree_controller.rb @@ -36,7 +36,6 @@ class Projects::TreeController < Projects::ApplicationController def create_dir return render_404 unless @commit_params.values.all? - set_start_branch_to_branch_name create_commit(Files::CreateDirService, success_notice: "The directory has been successfully created.", success_path: namespace_project_tree_path(@project.namespace, @project, File.join(@branch_name, @dir_name)), failure_path: namespace_project_tree_path(@project.namespace, @project, @ref)) diff --git a/app/helpers/form_helper.rb b/app/helpers/form_helper.rb index 53962b84618..014fc46b130 100644 --- a/app/helpers/form_helper.rb +++ b/app/helpers/form_helper.rb @@ -29,7 +29,7 @@ module FormHelper current_user: true, project_id: issuable.project.try(:id), field_name: "#{issuable.class.model_name.param_key}[assignee_ids][]", - default_label: 'Assignee', + default_label: 'Unassigned', 'max-select': 1, 'dropdown-header': 'Assignee', multi_select: true, diff --git a/app/helpers/milestones_helper.rb b/app/helpers/milestones_helper.rb index c515774140c..a230db22fa2 100644 --- a/app/helpers/milestones_helper.rb +++ b/app/helpers/milestones_helper.rb @@ -121,6 +121,8 @@ module MilestonesHelper merge_requests_namespace_project_milestone_path(@project.namespace, @project, milestone, format: :json) elsif @group merge_requests_group_milestone_path(@group, milestone.safe_title, title: milestone.title, format: :json) + else + merge_requests_dashboard_milestone_path(milestone, title: milestone.title, format: :json) end end @@ -129,6 +131,8 @@ module MilestonesHelper participants_namespace_project_milestone_path(@project.namespace, @project, milestone, format: :json) elsif @group participants_group_milestone_path(@group, milestone.safe_title, title: milestone.title, format: :json) + else + participants_dashboard_milestone_path(milestone, title: milestone.title, format: :json) end end @@ -137,6 +141,8 @@ module MilestonesHelper labels_namespace_project_milestone_path(@project.namespace, @project, milestone, format: :json) elsif @group labels_group_milestone_path(@group, milestone.safe_title, title: milestone.title, format: :json) + else + labels_dashboard_milestone_path(milestone, title: milestone.title, format: :json) end end end diff --git a/app/helpers/todos_helper.rb b/app/helpers/todos_helper.rb index 19286fadb19..3d1b3a4711a 100644 --- a/app/helpers/todos_helper.rb +++ b/app/helpers/todos_helper.rb @@ -4,7 +4,7 @@ module TodosHelper end def todos_count_format(count) - count > 99 ? '99+' : count + count > 99 ? '99+' : count.to_s end def todos_done_count diff --git a/app/helpers/u2f_helper.rb b/app/helpers/u2f_helper.rb index 143b4ca6b51..81bfe5d4eeb 100644 --- a/app/helpers/u2f_helper.rb +++ b/app/helpers/u2f_helper.rb @@ -1,5 +1,5 @@ module U2fHelper def inject_u2f_api? - browser.chrome? && browser.version.to_i >= 41 && !browser.device.mobile? + ((browser.chrome? && browser.version.to_i >= 41) || (browser.opera? && browser.version.to_i >= 40)) && !browser.device.mobile? end end diff --git a/app/models/blob.rb b/app/models/blob.rb index 3869e79ba75..954d4e4d779 100644 --- a/app/models/blob.rb +++ b/app/models/blob.rb @@ -191,9 +191,12 @@ class Blob < SimpleDelegator rendered_as_text? && rich_viewer end + def expanded? + !!@expanded + end + def expand! - simple_viewer&.expanded = true - rich_viewer&.expanded = true + @expanded = true end private diff --git a/app/models/blob_viewer/base.rb b/app/models/blob_viewer/base.rb index d2aa33d994e..35965d01692 100644 --- a/app/models/blob_viewer/base.rb +++ b/app/models/blob_viewer/base.rb @@ -6,15 +6,15 @@ module BlobViewer self.loading_partial_name = 'loading' - delegate :partial_path, :loading_partial_path, :rich?, :simple?, :text?, :binary?, to: :class + delegate :partial_path, :loading_partial_path, :rich?, :simple?, :load_async?, :text?, :binary?, to: :class attr_reader :blob - attr_accessor :expanded delegate :project, to: :blob def initialize(blob) @blob = blob + @initially_binary = blob.binary? end def self.partial_path @@ -57,14 +57,10 @@ module BlobViewer false end - def load_async? - self.class.load_async? && render_error.nil? - end - def collapsed? return @collapsed if defined?(@collapsed) - @collapsed = !expanded && collapse_limit && blob.raw_size > collapse_limit + @collapsed = !blob.expanded? && collapse_limit && blob.raw_size > collapse_limit end def too_large? @@ -73,6 +69,10 @@ module BlobViewer @too_large = size_limit && blob.raw_size > size_limit end + def binary_detected_after_load? + !@initially_binary && blob.binary? + end + # This method is used on the server side to check whether we can attempt to # render the blob at all. Human-readable error messages are found in the # `BlobHelper#blob_render_error_reason` helper. diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb index 55c16f7e1fd..36c87eb0d0c 100644 --- a/app/models/commit_status.rb +++ b/app/models/commit_status.rb @@ -132,6 +132,11 @@ class CommitStatus < ActiveRecord::Base false end + # To be overriden when inherrited from + def cancelable? + false + end + def stuck? false end diff --git a/app/presenters/merge_request_presenter.rb b/app/presenters/merge_request_presenter.rb index 0db9e31031c..8bf35953d29 100644 --- a/app/presenters/merge_request_presenter.rb +++ b/app/presenters/merge_request_presenter.rb @@ -110,12 +110,24 @@ class MergeRequestPresenter < Gitlab::View::Presenter::Delegated end def closing_issues_links - markdown issues_sentence(project, closing_issues), pipeline: :gfm, author: author, project: project + markdown( + issues_sentence(project, closing_issues), + pipeline: :gfm, + author: author, + project: project, + issuable_state_filter_enabled: true + ) end def mentioned_issues_links mentioned_issues = issues_mentioned_but_not_closing(current_user) - markdown issues_sentence(project, mentioned_issues), pipeline: :gfm, author: author, project: project + markdown( + issues_sentence(project, mentioned_issues), + pipeline: :gfm, + author: author, + project: project, + issuable_state_filter_enabled: true + ) end def assign_to_closing_issues_link diff --git a/app/serializers/build_details_entity.rb b/app/serializers/build_details_entity.rb index 0063920e603..514c4c2e35f 100644 --- a/app/serializers/build_details_entity.rb +++ b/app/serializers/build_details_entity.rb @@ -34,10 +34,8 @@ class BuildDetailsEntity < BuildEntity private def build_failed_issue_options - { - title: "Build Failed ##{build.id}", - description: namespace_project_job_url(project.namespace, project, build) - } + { title: "Build Failed ##{build.id}", + description: namespace_project_job_path(project.namespace, project, build) } end def current_user diff --git a/app/serializers/build_entity.rb b/app/serializers/build_entity.rb index c01efa9dd5c..67001f4547d 100644 --- a/app/serializers/build_entity.rb +++ b/app/serializers/build_entity.rb @@ -8,10 +8,14 @@ class BuildEntity < Grape::Entity path_to(:namespace_project_job, build) end - expose :retry_path, if: -> (*) { build&.retryable? } do |build| + expose :retry_path, if: -> (*) { retryable? } do |build| path_to(:retry_namespace_project_job, build) end + expose :cancel_path, if: -> (*) { cancelable? } do |build| + path_to(:cancel_namespace_project_job, build) + end + expose :play_path, if: -> (*) { playable? } do |build| path_to(:play_namespace_project_job, build) end @@ -25,6 +29,14 @@ class BuildEntity < Grape::Entity alias_method :build, :object + def cancelable? + build.cancelable? && can?(request.current_user, :update_build, build) + end + + def retryable? + build.retryable? && can?(request.current_user, :update_build, build) + end + def playable? build.playable? && can?(request.current_user, :update_build, build) end diff --git a/app/views/help/index.html.haml b/app/views/help/index.html.haml index b20e3a22133..31d0e589c26 100644 --- a/app/views/help/index.html.haml +++ b/app/views/help/index.html.haml @@ -4,7 +4,7 @@ Community Edition - if user_signed_in? %span= Gitlab::VERSION - %small= Gitlab::REVISION + %small= link_to Gitlab::REVISION, Gitlab::COM_URL + namespace_project_commits_path('gitlab-org', 'gitlab-ce', Gitlab::REVISION) = version_status_badge %p.slead GitLab is open source software to collaborate on code. diff --git a/app/views/projects/blob/_remove.html.haml b/app/views/projects/blob/_remove.html.haml index db6662a95ac..c8ca0406213 100644 --- a/app/views/projects/blob/_remove.html.haml +++ b/app/views/projects/blob/_remove.html.haml @@ -6,7 +6,7 @@ %h3.page-title Delete #{@blob.name} .modal-body - = form_tag namespace_project_blob_path(@project.namespace, @project, @id), method: :delete, class: 'form-horizontal js-replace-blob-form js-quick-submit js-requires-input' do + = form_tag namespace_project_blob_path(@project.namespace, @project, @id), method: :delete, class: 'form-horizontal js-delete-blob-form js-quick-submit js-requires-input' do = render 'shared/new_commit_form', placeholder: "Delete #{@blob.name}" .form-group @@ -15,4 +15,4 @@ = link_to "Cancel", '#', class: "btn btn-cancel", "data-dismiss" => "modal" :javascript - new NewCommitForm($('.js-replace-blob-form')) + new NewCommitForm($('.js-delete-blob-form')) diff --git a/app/views/projects/blob/_viewer.html.haml b/app/views/projects/blob/_viewer.html.haml index 4252f27d007..013f1c267c8 100644 --- a/app/views/projects/blob/_viewer.html.haml +++ b/app/views/projects/blob/_viewer.html.haml @@ -1,13 +1,19 @@ - hidden = local_assigns.fetch(:hidden, false) - render_error = viewer.render_error -- load_async = local_assigns.fetch(:load_async, viewer.load_async?) +- load_async = local_assigns.fetch(:load_async, viewer.load_async? && render_error.nil?) - viewer_url = local_assigns.fetch(:viewer_url) { url_for(params.merge(viewer: viewer.type, format: :json)) } if load_async .blob-viewer{ data: { type: viewer.type, url: viewer_url }, class: ('hidden' if hidden) } - - if load_async - = render viewer.loading_partial_path, viewer: viewer - - elsif render_error + - if render_error = render 'projects/blob/render_error', viewer: viewer + - elsif load_async + = render viewer.loading_partial_path, viewer: viewer - else - viewer.prepare! + + -# In the rare case where the first kilobyte of the file looks like text, + -# but the file turns out to actually be binary after loading all data, + -# we fall back on the binary Download viewer. + - viewer = BlobViewer::Download.new(viewer.blob) if viewer.binary_detected_after_load? + = render viewer.partial_path, viewer: viewer diff --git a/app/views/projects/commit/_change.html.haml b/app/views/projects/commit/_change.html.haml index b5f67cae341..281d823da52 100644 --- a/app/views/projects/commit/_change.html.haml +++ b/app/views/projects/commit/_change.html.haml @@ -18,14 +18,13 @@ = label_tag 'start_branch', branch_label, class: 'control-label' .col-sm-10 = hidden_field_tag :start_branch, @project.default_branch, id: 'start_branch' - = dropdown_tag(@project.default_branch, options: { title: "Switch branch", filter: true, placeholder: "Search branches", toggle_class: 'js-project-refs-dropdown js-target-branch dynamic', dropdown_class: 'dropdown-menu-selectable', data: { field_name: "start_branch", selected: @project.default_branch, start_branch: @project.default_branch, refs_url: namespace_project_branches_path(@project.namespace, @project), submit_form_on_click: false } }) + = dropdown_tag(@project.default_branch, options: { title: "Switch branch", filter: true, placeholder: "Search branches", toggle_class: 'js-project-refs-dropdown dynamic', dropdown_class: 'dropdown-menu-selectable', data: { field_name: "start_branch", selected: @project.default_branch, start_branch: @project.default_branch, refs_url: namespace_project_branches_path(@project.namespace, @project), submit_form_on_click: false } }) - if can?(current_user, :push_code, @project) - .js-create-merge-request-container - .checkbox - = label_tag do - = check_box_tag 'create_merge_request', 1, true, class: 'js-create-merge-request', id: nil - Start a <strong>new merge request</strong> with these changes + .checkbox + = label_tag do + = check_box_tag 'create_merge_request', 1, true, class: 'js-create-merge-request', id: nil + Start a <strong>new merge request</strong> with these changes - else = hidden_field_tag 'create_merge_request', 1, id: nil .form-actions @@ -35,6 +34,3 @@ - unless can?(current_user, :push_code, @project) .inline.prepend-left-10 = commit_in_fork_help - -:javascript - new NewCommitForm($('.js-#{type}-form'), 'start_branch') diff --git a/app/views/projects/jobs/_sidebar.html.haml b/app/views/projects/jobs/_sidebar.html.haml index 09d4ddc243b..8b9e6e57ec4 100644 --- a/app/views/projects/jobs/_sidebar.html.haml +++ b/app/views/projects/jobs/_sidebar.html.haml @@ -1,19 +1,15 @@ - builds = @build.pipeline.builds.to_a %aside.right-sidebar.right-sidebar-expanded.build-sidebar.js-build-sidebar.js-right-sidebar{ data: { "offset-top" => "101", "spy" => "affix" } } - .block.build-sidebar-header.visible-xs-block.visible-sm-block.append-bottom-default - Job - %strong ##{@build.id} - %a.gutter-toggle.pull-right.js-sidebar-build-toggle{ href: "#" } - = icon('angle-double-right') - - if @build.coverage - .block.coverage - .title - Test coverage - %p.build-detail-row - #{@build.coverage}% - .blocks-container + .block + %strong + = @build.name + %a.gutter-toggle.pull-right.visible-xs-block.visible-sm-block.js-sidebar-build-toggle{ href: "#", 'aria-label': 'Toggle Sidebar', role: 'button' } + = icon('angle-double-right') + + #js-details-block-vue + - if can?(current_user, :read_build, @project) && (@build.artifacts? || @build.artifacts_expired?) .block{ class: ("block-first" if !@build.coverage) } .title @@ -40,37 +36,6 @@ = link_to browse_namespace_project_job_artifacts_path(@project.namespace, @project, @build), class: 'btn btn-sm btn-default' do Browse - .block{ class: ("block-first" if !@build.coverage && !(can?(current_user, :read_build, @project) && (@build.artifacts? || @build.artifacts_expired?))) } - .title - Job details - - if can?(current_user, :update_build, @build) && @build.retryable? - = link_to "Retry job", retry_namespace_project_job_path(@project.namespace, @project, @build), class: 'pull-right retry-link', method: :post - - if @build.merge_request - %p.build-detail-row - %span.build-light-text Merge Request: - = link_to "#{@build.merge_request.to_reference}", merge_request_path(@build.merge_request), class: 'bold' - - if @build.duration - %p.build-detail-row - %span.build-light-text Duration: - = time_interval_in_words(@build.duration) - - if @build.finished_at - %p.build-detail-row - %span.build-light-text Finished: - #{time_ago_with_tooltip(@build.finished_at)} - - if @build.erased_at - %p.build-detail-row - %span.build-light-text Erased: - #{time_ago_with_tooltip(@build.erased_at)} - %p.build-detail-row - %span.build-light-text Runner: - - if @build.runner && current_user && current_user.admin - = link_to "##{@build.runner.id}", admin_runner_path(@build.runner.id) - - elsif @build.runner - \##{@build.runner.id} - .btn-group.btn-group-justified{ role: :group } - - if @build.active? - = link_to "Cancel", cancel_namespace_project_job_path(@project.namespace, @project, @build), class: 'btn btn-sm btn-default', method: :post - - if @build.trigger_request .build-widget %h4.title @@ -87,26 +52,29 @@ - @build.trigger_request.variables.each do |key, value| .hide.js-build - .js-build-variable= key - .js-build-value= value + .js-build-variable.trigger-build-variable= key + .js-build-value.trigger-build-value= value .block - .title - Commit title + %p + Commit + = link_to @build.pipeline.short_sha, namespace_project_commit_path(@project.namespace, @project, @build.pipeline.sha), class: 'commit-sha link-commit' + = clipboard_button(text: @build.pipeline.short_sha, title: "Copy commit SHA to clipboard") + - if @build.merge_request + in + = link_to "#{@build.merge_request.to_reference}", merge_request_path(@build.merge_request), class: 'link-commit' + %p.build-light-text.append-bottom-0 #{@build.pipeline.git_commit_title} - - if @build.tags.any? - .block - .title - Tags - - @build.tag_list.each do |tag| - %span.label.label-primary - = tag - - if @build.pipeline.stages_count > 1 .dropdown.build-dropdown - .title Stage + .title + %span{ class: "ci-status-icon-#{@build.pipeline.status}" } + = ci_icon_for_status(@build.pipeline.status) + = link_to "##{@build.pipeline.id}", namespace_project_pipeline_path(@project.namespace, @project, @build.pipeline), class: 'link-commit' + from + = link_to "#{@build.pipeline.ref}", namespace_project_branch_path(@project.namespace, @project, @build.pipeline.ref), class: 'link-commit' %button.dropdown-menu-toggle{ type: 'button', 'data-toggle' => 'dropdown' } %span.stage-selection More = icon('chevron-down') diff --git a/app/views/projects/jobs/show.html.haml b/app/views/projects/jobs/show.html.haml index 0d10dfcef70..c73bae0a2c9 100644 --- a/app/views/projects/jobs/show.html.haml +++ b/app/views/projects/jobs/show.html.haml @@ -3,9 +3,8 @@ = render "projects/pipelines/head" %div{ class: container_class } - .build-page - = render "header" - + .build-page.js-build-page + #js-build-header-vue - if @build.stuck? - unless @build.any_runners_online? .bs-callout.bs-callout-warning.js-build-stuck @@ -47,52 +46,52 @@ - if environment.try(:last_deployment) and will overwrite the #{deployment_link(environment.last_deployment, text: 'latest deployment')} - .prepend-top-default.js-build-erased - - if @build.erased? + - if @build.erased? + .prepend-top-default.js-build-erased .erased.alert.alert-warning - if @build.erased_by_user? Job has been erased by #{link_to(@build.erased_by_name, user_path(@build.erased_by))} #{time_ago_with_tooltip(@build.erased_at)} - else Job has been erased #{time_ago_with_tooltip(@build.erased_at)} - .prepend-top-default - .build-trace-container#build-trace - .top-bar.sticky - .js-truncated-info.truncated-info.hidden< - Showing last - %span.js-truncated-info-size.truncated-info-size>< - KiB of log - - %a.js-raw-link.raw-link{ href: raw_namespace_project_job_path(@project.namespace, @project, @build) }>< Complete Raw - .controllers - - if @build.has_trace? - = link_to raw_namespace_project_job_path(@project.namespace, @project, @build), - title: 'Open raw trace', - data: { placement: 'top', container: 'body' }, - class: 'js-raw-link-controller has-tooltip' do - = icon('download') - - - if can?(current_user, :update_build, @project) && @build.erasable? - = link_to erase_namespace_project_job_path(@project.namespace, @project, @build), - method: :post, - data: { confirm: 'Are you sure you want to erase this build?', placement: 'top', container: 'body' }, - title: 'Erase Build', - class: 'has-tooltip js-erase-link' do - = icon('trash') + .build-trace-container#build-trace + .top-bar.sticky + .js-truncated-info.truncated-info.hidden< + Showing last + %span.js-truncated-info-size.truncated-info-size>< + KiB of log - + %a.js-raw-link.raw-link{ href: raw_namespace_project_job_path(@project.namespace, @project, @build) }>< Complete Raw + .controllers + - if @build.has_trace? + = link_to raw_namespace_project_job_path(@project.namespace, @project, @build), + title: 'Show complete raw', + data: { placement: 'top', container: 'body' }, + class: 'js-raw-link-controller has-tooltip controllers-buttons' do + = icon('file-text-o') - %button.js-scroll-up.btn-scroll.btn-transparent.btn-blank.has-tooltip{ type: 'button', - disabled: true, - title: 'Scroll Up', - data: { placement: 'top', container: 'body'} } + - if can?(current_user, :update_build, @project) && @build.erasable? + = link_to erase_namespace_project_job_path(@project.namespace, @project, @build), + method: :post, + data: { confirm: 'Are you sure you want to erase this build?', placement: 'top', container: 'body' }, + title: 'Erase job log', + class: 'has-tooltip js-erase-link controllers-buttons' do + = icon('trash') + .has-tooltip.controllers-buttons{ title: 'Scroll to top', data: { placement: 'top', container: 'body'} } + %button.js-scroll-up.btn-scroll.btn-transparent.btn-blank{ type: 'button', disabled: true } = custom_icon('scroll_up') - %button.js-scroll-down.btn-scroll.btn-transparent.btn-blank.has-tooltip{ type: 'button', - disabled: true, - title: 'Scroll Down', - data: { placement: 'top', container: 'body'} } + .has-tooltip.controllers-buttons{ title: 'Scroll to bottom', data: { placement: 'top', container: 'body'} } + %button.js-scroll-down.btn-scroll.btn-transparent.btn-blank{ type: 'button', disabled: true } = custom_icon('scroll_down') - .bash.sticky.js-scroll-container - %code.js-build-output - .build-loader-animation.js-build-refresh + .bash.sticky.js-scroll-container + %code.js-build-output + .build-loader-animation.js-build-refresh = render "sidebar" .js-build-options{ data: javascript_build_options } + +#js-job-details-vue{ data: { endpoint: namespace_project_job_path(@project.namespace, @project, @build, format: :json) } } + +- content_for :page_specific_javascripts do + = webpack_bundle_tag('common_vue') + = webpack_bundle_tag('job_details') diff --git a/app/views/projects/pipelines/_head.html.haml b/app/views/projects/pipelines/_head.html.haml index a33da149c62..d2f0cb0806f 100644 --- a/app/views/projects/pipelines/_head.html.haml +++ b/app/views/projects/pipelines/_head.html.haml @@ -10,7 +10,7 @@ Pipelines - if project_nav_tab? :builds - = nav_link(controller: [:builds, :artifacts]) do + = nav_link(controller: [:jobs, :artifacts]) do = link_to project_jobs_path(@project), title: 'Jobs', class: 'shortcuts-builds' do %span Jobs diff --git a/app/views/shared/_branch_switcher.html.haml b/app/views/shared/_branch_switcher.html.haml deleted file mode 100644 index 69e3f3042a9..00000000000 --- a/app/views/shared/_branch_switcher.html.haml +++ /dev/null @@ -1,8 +0,0 @@ -- dropdown_toggle_text = @branch_name || tree_edit_branch -= hidden_field_tag 'branch_name', dropdown_toggle_text - -.dropdown - = dropdown_toggle dropdown_toggle_text, { toggle: 'dropdown', selected: dropdown_toggle_text, field_name: 'branch_name', form_id: '.js-edit-blob-form', refs_url: namespace_project_branches_path(@project.namespace, @project) }, { toggle_class: 'js-project-branches-dropdown js-target-branch' } - .dropdown-menu.dropdown-menu-selectable.dropdown-menu-paging.dropdown-menu-branches - = render partial: 'shared/projects/blob/branch_page_default' - = render partial: 'shared/projects/blob/branch_page_create' diff --git a/app/views/shared/_new_commit_form.html.haml b/app/views/shared/_new_commit_form.html.haml index 0b37fe3013b..25a56f84ec5 100644 --- a/app/views/shared/_new_commit_form.html.haml +++ b/app/views/shared/_new_commit_form.html.haml @@ -7,7 +7,7 @@ .form-group.branch = label_tag 'branch_name', 'Target branch', class: 'control-label' .col-sm-10 - = render 'shared/branch_switcher' + = text_field_tag 'branch_name', @branch_name || tree_edit_branch, required: true, class: "form-control js-branch-name ref-name" .js-create-merge-request-container .checkbox diff --git a/app/views/shared/projects/blob/_branch_page_create.html.haml b/app/views/shared/projects/blob/_branch_page_create.html.haml deleted file mode 100644 index c279a0d8846..00000000000 --- a/app/views/shared/projects/blob/_branch_page_create.html.haml +++ /dev/null @@ -1,8 +0,0 @@ -.dropdown-page-two.dropdown-new-branch - = dropdown_title('Create new branch', back: true) - = dropdown_content do - %input#new_branch_name.default-dropdown-input.append-bottom-10{ type: "text", placeholder: "Name new branch" } - %button.btn.btn-primary.pull-left.js-new-branch-btn{ type: "button" } - Create - %button.btn.btn-default.pull-right.js-cancel-branch-btn{ type: "button" } - Cancel diff --git a/app/views/shared/projects/blob/_branch_page_default.html.haml b/app/views/shared/projects/blob/_branch_page_default.html.haml deleted file mode 100644 index 9bf78d10878..00000000000 --- a/app/views/shared/projects/blob/_branch_page_default.html.haml +++ /dev/null @@ -1,10 +0,0 @@ -.dropdown-page-one - = dropdown_title "Select branch" - = dropdown_filter "Search branches" - = dropdown_content - = dropdown_loading - = dropdown_footer do - %ul.dropdown-footer-list - %li - %a.create-new-branch.dropdown-toggle-page{ href: "#" } - Create new branch diff --git a/changelogs/unreleased/31397-job-detail-real-time.yml b/changelogs/unreleased/31397-job-detail-real-time.yml new file mode 100644 index 00000000000..90487a1e75a --- /dev/null +++ b/changelogs/unreleased/31397-job-detail-real-time.yml @@ -0,0 +1,4 @@ +--- +title: Adds realtime feature to job show view header and sidebar info. Updates UX. +merge_request: +author: diff --git a/changelogs/unreleased/32517-disable-hover-state.yml b/changelogs/unreleased/32517-disable-hover-state.yml new file mode 100644 index 00000000000..31b02778963 --- /dev/null +++ b/changelogs/unreleased/32517-disable-hover-state.yml @@ -0,0 +1,5 @@ +--- +title: Removes hover style for nodes that are either links or buttons in the pipeline + graph +merge_request: +author: diff --git a/changelogs/unreleased/33003-avatar-in-project-api.yml b/changelogs/unreleased/33003-avatar-in-project-api.yml new file mode 100644 index 00000000000..41d796ebb32 --- /dev/null +++ b/changelogs/unreleased/33003-avatar-in-project-api.yml @@ -0,0 +1,4 @@ +--- +title: Accept image for avatar in project API +merge_request: 11988 +author: Ivan Chernov diff --git a/changelogs/unreleased/33132-change-icon-color.yml b/changelogs/unreleased/33132-change-icon-color.yml new file mode 100644 index 00000000000..c0e148f985b --- /dev/null +++ b/changelogs/unreleased/33132-change-icon-color.yml @@ -0,0 +1,4 @@ +--- +title: Render CI statuses with warnings in orange +merge_request: +author: diff --git a/changelogs/unreleased/33208-singup-active-state-underline.yml b/changelogs/unreleased/33208-singup-active-state-underline.yml new file mode 100644 index 00000000000..cddb43214ea --- /dev/null +++ b/changelogs/unreleased/33208-singup-active-state-underline.yml @@ -0,0 +1,4 @@ +--- +title: Fixes "sign in / Register" active state underline misalignment +merge_request: 11890 +author: Frank Sierra diff --git a/changelogs/unreleased/33381-display-issue-state-in-mr-widget-issue-links.yml b/changelogs/unreleased/33381-display-issue-state-in-mr-widget-issue-links.yml new file mode 100644 index 00000000000..4a7b02fec94 --- /dev/null +++ b/changelogs/unreleased/33381-display-issue-state-in-mr-widget-issue-links.yml @@ -0,0 +1,4 @@ +--- +title: Display issue state in issue links section of merge request widget +merge_request: 12021 +author: diff --git a/changelogs/unreleased/dashboard-milestone-tabs-loading-async.yml b/changelogs/unreleased/dashboard-milestone-tabs-loading-async.yml new file mode 100644 index 00000000000..357a623e0e8 --- /dev/null +++ b/changelogs/unreleased/dashboard-milestone-tabs-loading-async.yml @@ -0,0 +1,4 @@ +--- +title: Fixed dashboard milestone tabs not loading +merge_request: +author: diff --git a/changelogs/unreleased/dm-blob-binaryness-change.yml b/changelogs/unreleased/dm-blob-binaryness-change.yml new file mode 100644 index 00000000000..f3e3af26f12 --- /dev/null +++ b/changelogs/unreleased/dm-blob-binaryness-change.yml @@ -0,0 +1,5 @@ +--- +title: Detect if file that appears to be text in the first 1024 bytes is actually + binary afer loading all data +merge_request: +author: diff --git a/changelogs/unreleased/dm-mail-room-check-without-omnibus.yml b/changelogs/unreleased/dm-mail-room-check-without-omnibus.yml new file mode 100644 index 00000000000..7fd252e9b8b --- /dev/null +++ b/changelogs/unreleased/dm-mail-room-check-without-omnibus.yml @@ -0,0 +1,4 @@ +--- +title: Don't check if MailRoom is running on Omnibus +merge_request: +author: diff --git a/changelogs/unreleased/dm-revert-mr-8427.yml b/changelogs/unreleased/dm-revert-mr-8427.yml new file mode 100644 index 00000000000..a91cff2e9cd --- /dev/null +++ b/changelogs/unreleased/dm-revert-mr-8427.yml @@ -0,0 +1,4 @@ +--- +title: Revert 'New file from interface on existing branch' +merge_request: +author: diff --git a/changelogs/unreleased/fix-u2f-for-opera.yml b/changelogs/unreleased/fix-u2f-for-opera.yml new file mode 100644 index 00000000000..0eafb8eff9a --- /dev/null +++ b/changelogs/unreleased/fix-u2f-for-opera.yml @@ -0,0 +1,4 @@ +--- +title: Fix FIDO U2F for Opera browser +merge_request: 12082 +author: Jakub Kramarz and Jonas Kalderstam diff --git a/changelogs/unreleased/issuable-sidebar-edit-button-field-focus.yml b/changelogs/unreleased/issuable-sidebar-edit-button-field-focus.yml new file mode 100644 index 00000000000..05d52fcad0f --- /dev/null +++ b/changelogs/unreleased/issuable-sidebar-edit-button-field-focus.yml @@ -0,0 +1,4 @@ +--- +title: Fixed dropdown filter input not focusing after transition +merge_request: +author: diff --git a/changelogs/unreleased/pat-msg-on-auth-failure.yml b/changelogs/unreleased/pat-msg-on-auth-failure.yml new file mode 100644 index 00000000000..c1b1528bb7a --- /dev/null +++ b/changelogs/unreleased/pat-msg-on-auth-failure.yml @@ -0,0 +1,4 @@ +--- +title: Instruct user to use personal access token for Git over HTTP +merge_request: 11986 +author: Robin Bobbitt diff --git a/changelogs/unreleased/sh-bump-oauth2-gem.yml b/changelogs/unreleased/sh-bump-oauth2-gem.yml new file mode 100644 index 00000000000..b894a64968b --- /dev/null +++ b/changelogs/unreleased/sh-bump-oauth2-gem.yml @@ -0,0 +1,4 @@ +--- +title: Bump Faraday and dependent OAuth2 gem version to support no_proxy variable +merge_request: +author: diff --git a/changelogs/unreleased/sh-recaptcha-fix-try2.yml b/changelogs/unreleased/sh-recaptcha-fix-try2.yml new file mode 100644 index 00000000000..94729252c6f --- /dev/null +++ b/changelogs/unreleased/sh-recaptcha-fix-try2.yml @@ -0,0 +1,4 @@ +--- +title: Make sure reCAPTCHA configuration is loaded when spam checks are initiated +merge_request: +author: diff --git a/changelogs/unreleased/tc-link-to-commit-on-help-page.yml b/changelogs/unreleased/tc-link-to-commit-on-help-page.yml new file mode 100644 index 00000000000..3d11ba43d1f --- /dev/null +++ b/changelogs/unreleased/tc-link-to-commit-on-help-page.yml @@ -0,0 +1,4 @@ +--- +title: Make the revision on the `/help` page clickable +merge_request: 12016 +author: diff --git a/config/boot.rb b/config/boot.rb index f2830ae3166..17a71148370 100644 --- a/config/boot.rb +++ b/config/boot.rb @@ -4,3 +4,15 @@ require 'rubygems' ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE']) + +# Default Bootsnap configuration from https://github.com/Shopify/bootsnap#usage +require 'bootsnap' +Bootsnap.setup( + cache_dir: 'tmp/cache', + development_mode: ENV['RAILS_ENV'] == 'development', + load_path_cache: true, + autoload_paths_cache: true, + disable_trace: false, + compile_cache_iseq: true, + compile_cache_yaml: true +) diff --git a/config/locales/de.yml b/config/locales/de.yml index 533663a2704..38c3711c6c7 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -62,6 +62,43 @@ de: - :month - :year datetime: + # used in a custom scope that has been created to fix https://gitlab.com/gitlab-org/gitlab-ce/issues/32747 + time_ago_in_words: + half_a_minute: vor einer halben Minute + less_than_x_seconds: + one: vor weniger als einer Sekunde + other: "vor weniger als %{count} Sekunden" + x_seconds: + one: vor einer Sekunde + other: "vor %{count} Sekunden" + less_than_x_minutes: + one: vor weniger als einer Minute + other: vor weniger als %{count} Minuten + x_minutes: + one: vor einer Minute + other: "vor %{count} Minuten" + about_x_hours: + one: vor etwa einer Stunde + other: "vor etwa %{count} Stunden" + x_days: + one: vor einem Tag + other: "vor %{count} Tagen" + about_x_months: + one: vor etwa einem Monat + other: "vor etwa %{count} Monaten" + x_months: + one: vor einem Monat + other: "vor %{count} Monaten" + about_x_years: + one: vor etwa einem Jahr + other: "vor etwa %{count} Jahren" + over_x_years: + one: vor mehr als einem Jahr + other: "vor mehr als %{count} Jahren" + almost_x_years: + one: vor fast einem Jahr + other: "vor fast %{count} Jahren" + # Used in distance_of_time_in_words(), distance_of_time_in_words_to_now(), time_ago_in_words() distance_in_words: about_x_hours: one: etwa eine Stunde diff --git a/config/locales/es.yml b/config/locales/es.yml index 0f9dc39535d..d71c6eb5047 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -61,6 +61,7 @@ es: - :month - :year datetime: + # used in a custom scope that has been created to fix https://gitlab.com/gitlab-org/gitlab-ce/issues/32747 time_ago_in_words: half_a_minute: "hace medio minuto" less_than_x_seconds: @@ -96,6 +97,7 @@ es: almost_x_years: one: "hace casi 1 año" other: "hace casi %{count} años" + # Used in distance_of_time_in_words(), distance_of_time_in_words_to_now(), time_ago_in_words() distance_in_words: about_x_hours: one: alrededor de 1 hora diff --git a/config/routes/dashboard.rb b/config/routes/dashboard.rb index 8e380a0b0ac..d2437285cdf 100644 --- a/config/routes/dashboard.rb +++ b/config/routes/dashboard.rb @@ -4,7 +4,13 @@ resource :dashboard, controller: 'dashboard', only: [] do get :activity scope module: :dashboard do - resources :milestones, only: [:index, :show] + resources :milestones, only: [:index, :show] do + member do + get :merge_requests + get :participants + get :labels + end + end resources :labels, only: [:index] resources :groups, only: [:index] diff --git a/config/webpack.config.js b/config/webpack.config.js index 7501acb7633..c5060669da1 100644 --- a/config/webpack.config.js +++ b/config/webpack.config.js @@ -18,6 +18,15 @@ var DEV_SERVER_LIVERELOAD = process.env.DEV_SERVER_LIVERELOAD !== 'false'; var WEBPACK_REPORT = process.env.WEBPACK_REPORT; var NO_COMPRESSION = process.env.NO_COMPRESSION; +// optional dependency `node-zopfli` is unavailable on CentOS 6 +var ZOPFLI_AVAILABLE; +try { + require.resolve('node-zopfli'); + ZOPFLI_AVAILABLE = true; +} catch(err) { + ZOPFLI_AVAILABLE = false; +} + var config = { // because sqljs requires fs. node: { @@ -44,6 +53,7 @@ var config = { groups_list: './groups_list.js', issue_show: './issue_show/index.js', integrations: './integrations', + job_details: './jobs/job_details_bundle.js', locale: './locale/index.js', main: './main.js', merge_conflicts: './merge_conflicts/merge_conflicts_bundle.js', @@ -158,6 +168,7 @@ var config = { 'filtered_search', 'groups', 'issue_show', + 'job_details', 'merge_conflicts', 'notebook_viewer', 'pdf_viewer', @@ -224,7 +235,7 @@ if (IS_PRODUCTION) { config.plugins.push( new CompressionPlugin({ asset: '[path].gz[query]', - algorithm: 'zopfli', + algorithm: ZOPFLI_AVAILABLE ? 'zopfli' : 'gzip', }) ); } diff --git a/doc/api/projects.md b/doc/api/projects.md index bf21aa0e179..58f18105e21 100644 --- a/doc/api/projects.md +++ b/doc/api/projects.md @@ -2,10 +2,10 @@ ### Project visibility level -Project in GitLab has be either private, internal or public. -You can determine it by `visibility` field in project. +Project in GitLab can be either private, internal or public. +This is determined by the `visibility` field in the project. -Constants for project visibility levels are next: +Values for the project visibility level are: * `private`: Project access must be granted explicitly for each user. @@ -18,7 +18,7 @@ Constants for project visibility levels are next: ## List projects -Get a list of visible projects for authenticated user. When being accessed without authentication, all public projects are returned. +Get a list of visible projects for authenticated user. When accessed without authentication, only public projects are returned. ``` GET /projects @@ -343,6 +343,7 @@ Parameters: | `lfs_enabled` | boolean | no | Enable LFS | | `request_access_enabled` | boolean | no | Allow users to request member access | | `tag_list` | array | no | The list of tags for a project; put array of tags, that should be finally assigned to a project | +| `avatar` | mixed | no | Image file for avatar of the project | ### Create project for user @@ -377,6 +378,7 @@ Parameters: | `lfs_enabled` | boolean | no | Enable LFS | | `request_access_enabled` | boolean | no | Allow users to request member access | | `tag_list` | array | no | The list of tags for a project; put array of tags, that should be finally assigned to a project | +| `avatar` | mixed | no | Image file for avatar of the project | ### Edit project @@ -410,6 +412,7 @@ Parameters: | `lfs_enabled` | boolean | no | Enable LFS | | `request_access_enabled` | boolean | no | Allow users to request member access | | `tag_list` | array | no | The list of tags for a project; put array of tags, that should be finally assigned to a project | +| `avatar` | mixed | no | Image file for avatar of the project | ### Fork project diff --git a/doc/development/i18n_guide.md b/doc/development/i18n_guide.md index bfb0779fbfa..756535e28bc 100644 --- a/doc/development/i18n_guide.md +++ b/doc/development/i18n_guide.md @@ -127,6 +127,14 @@ New translations will be added with their default content and will be marked fuzzy. To use the translation, look for the `#, fuzzy` mention in `gitlab.edit.po` and remove it. +We need to make sure we remove the `fuzzy` translations before generating the +`locale/**/gitlab.po` file. When they aren't removed, the resulting `.po` will +be treated as a binary file which could overwrite translations that were merged +before the new translations. + +When we are just preparing a page to be translated, but not actually adding any +translations. There's no need to generate `.po` files. + Translations that aren't used in the source code anymore will be marked with `~#`; these can be removed to keep our translation files clutter-free. diff --git a/doc/integration/google.md b/doc/integration/google.md index 1e7ad90c5a8..d5b523e6dc0 100644 --- a/doc/integration/google.md +++ b/doc/integration/google.md @@ -72,6 +72,21 @@ To enable the Google OAuth2 OmniAuth provider you must register your application 1. Change 'YOUR_APP_SECRET' to the client secret from the Google Developer page from step 10. +1. Make sure that you configure GitLab to use an FQDN as Google will not accept raw IP addresses. + + For Omnibus packages: + + ```ruby + external_url 'https://gitlab.example.com' + ``` + + For installations from source: + + ```yaml + gitlab: + host: https://gitlab.example.com + ``` + 1. Save the configuration file. 1. [Reconfigure][] or [restart GitLab][] for the changes to take effect if you diff --git a/doc/university/glossary/README.md b/doc/university/glossary/README.md index 591d1524061..9544de41b9a 100644 --- a/doc/university/glossary/README.md +++ b/doc/university/glossary/README.md @@ -1,4 +1,3 @@ - ## What is the Glossary This contains a simplified list and definitions of some of the terms that you will encounter in your day to day activities when working with GitLab. @@ -10,7 +9,7 @@ User authentication by combination of 2 different steps during login. This allow ### Access Levels -Process of selective restriction to create, view, modify or delete a resource based on a set of assigned permissions. See [GitLab's Permission Guidelines](../../permissions/permissions.md +Process of selective restriction to create, view, modify or delete a resource based on a set of assigned permissions. See [GitLab's Permission Guidelines](../../user/permissions.md) ### Active Directory (AD) diff --git a/doc/update/9.1-to-9.2.md b/doc/update/9.1-to-9.2.md index 19db6e5763e..e7d97fde14e 100644 --- a/doc/update/9.1-to-9.2.md +++ b/doc/update/9.1-to-9.2.md @@ -110,8 +110,8 @@ sudo -u git -H bin/compile ### 7. Update gitlab-workhorse Install and compile gitlab-workhorse. This requires -[Go 1.5](https://golang.org/dl) which should already be on your system from -GitLab 8.1. GitLab-Workhorse uses [GNU Make](https://www.gnu.org/software/make/). +[Go 1.8](https://golang.org/dl). Go (at least 1.5) should already be on your system from +GitLab 8.1 and shall be upgraded if necessary. Please note that starting in Gitlab 9.3, only Go 1.8.3 and above will be supported. GitLab-Workhorse uses [GNU Make](https://www.gnu.org/software/make/). If you are not using Linux you may have to run `gmake` instead of `make` below. diff --git a/doc/user/project/container_registry.md b/doc/user/project/container_registry.md index 10c281448a3..75ea911b9bc 100644 --- a/doc/user/project/container_registry.md +++ b/doc/user/project/container_registry.md @@ -39,6 +39,14 @@ You can read more about Docker Registry at https://docs.docker.com/registry/intr ## Build and push images +>**Notes:** +- Moving or renaming existing container registry repositories is not supported +once you have pushed images because the images are signed, and the +signature includes the repository name. +- To move or rename a repository with a container registry you will have to +delete all existing images. + + If you visit the **Registry** link under your project's menu, you can see the explicit instructions to login to the Container Registry using your GitLab credentials. diff --git a/doc/user/project/pipelines/schedules.md b/doc/user/project/pipelines/schedules.md index d19d184f9b0..17cc21238ff 100644 --- a/doc/user/project/pipelines/schedules.md +++ b/doc/user/project/pipelines/schedules.md @@ -31,6 +31,26 @@ is installed on. ![Schedules list](img/pipeline_schedules_list.png) +## Using only and except + +To configure that a job can be executed only when the pipeline has been +scheduled (or the opposite), you can use +[only and except](../../../ci/yaml/README.md#only-and-except) configuration keywords. + +``` +job:on-schedule: + only: + - schedules + script: + - make world + +job: + except: + - schedules + script: + - make build +``` + ## Taking ownership Pipelines are executed as a user, who owns a schedule. This influences what diff --git a/doc/workflow/groups.md b/doc/workflow/groups.md index 1cb3c940f00..1645e7e8d65 100644 --- a/doc/workflow/groups.md +++ b/doc/workflow/groups.md @@ -23,9 +23,10 @@ You can use the 'New project' button to add a project to the new group. ## Transferring an existing project into a group -You can transfer an existing project into a group you own from the project settings page. The option to transfer a project is only available if you are the Owner of the project. +You can transfer an existing project into a group you have at least Master access in from the project settings page. +The option to transfer a project is only available if you are the Owner of the project. First scroll down to the 'Dangerous settings' and click 'Show them to me'. -Now you can pick any of the groups you manage as the new namespace for the group. +Now you can pick any of the groups you have at least Master access in as the new namespace for the group. ![Transfer a project to a new namespace](groups/transfer_project.png) diff --git a/features/project/builds/permissions.feature b/features/project/builds/permissions.feature index 3c7f72335d9..db15968db06 100644 --- a/features/project/builds/permissions.feature +++ b/features/project/builds/permissions.feature @@ -27,6 +27,7 @@ Feature: Project Builds Permissions When I visit project builds page Then page status code should be 404 + @javascript Scenario: I try to visit build details of internal project with access to builds Given The project is internal And public access for builds is enabled diff --git a/features/project/builds/summary.feature b/features/project/builds/summary.feature index 550ebccf0d7..3bf15b0cf87 100644 --- a/features/project/builds/summary.feature +++ b/features/project/builds/summary.feature @@ -6,16 +6,19 @@ Feature: Project Builds Summary And project has coverage enabled And project has a recent build + @javascript Scenario: I browse build details page When I visit recent build details page Then I see details of a build And I see build trace + @javascript Scenario: I browse project builds page When I visit project builds page Then I see coverage Then I see button to CI Lint + @javascript Scenario: I erase a build Given recent build is successful And recent build has a build trace diff --git a/features/steps/project/builds/summary.rb b/features/steps/project/builds/summary.rb index 229e5d7cdf4..20a5c873ecd 100644 --- a/features/steps/project/builds/summary.rb +++ b/features/steps/project/builds/summary.rb @@ -13,7 +13,7 @@ class Spinach::Features::ProjectBuildsSummary < Spinach::FeatureSteps step 'I see button to CI Lint' do page.within('.nav-controls') do ci_lint_tool_link = page.find_link('CI lint') - expect(ci_lint_tool_link[:href]).to eq ci_lint_path + expect(ci_lint_tool_link[:href]).to end_with(ci_lint_path) end end diff --git a/features/steps/project/source/browse_files.rb b/features/steps/project/source/browse_files.rb index d099d7af167..80aa3a047a0 100644 --- a/features/steps/project/source/browse_files.rb +++ b/features/steps/project/source/browse_files.rb @@ -89,10 +89,7 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps end step 'I fill the new branch name' do - first('button.js-target-branch', visible: true).click - find('.create-new-branch', visible: true).click - find('#new_branch_name', visible: true).set('new_branch_name') - find('.js-new-branch-btn', visible: true).click + fill_in :branch_name, with: 'new_branch_name', visible: true end step 'I fill the new file name with an illegal name' do diff --git a/features/steps/project/source/markdown_render.rb b/features/steps/project/source/markdown_render.rb index 0fee158d590..cf31e61437e 100644 --- a/features/steps/project/source/markdown_render.rb +++ b/features/steps/project/source/markdown_render.rb @@ -90,6 +90,8 @@ class Spinach::Features::ProjectSourceMarkdownRender < Spinach::FeatureSteps click_link "api" end + wait_for_requests + page.within '.tree-table' do click_link "README.md" end diff --git a/lib/api/projects.rb b/lib/api/projects.rb index 56046742e08..50d34e8a738 100644 --- a/lib/api/projects.rb +++ b/lib/api/projects.rb @@ -22,6 +22,7 @@ module API optional :only_allow_merge_if_pipeline_succeeds, type: Boolean, desc: 'Only allow to merge if builds succeed' optional :only_allow_merge_if_all_discussions_are_resolved, type: Boolean, desc: 'Only allow to merge if all discussions are resolved' optional :tag_list, type: Array[String], desc: 'The list of tags for a project' + optional :avatar, type: File, desc: 'Avatar image for project' end params :optional_params do diff --git a/lib/gitlab.rb b/lib/gitlab.rb index c3064163e07..11f7c8b9510 100644 --- a/lib/gitlab.rb +++ b/lib/gitlab.rb @@ -1,9 +1,11 @@ require_dependency 'gitlab/git' module Gitlab + COM_URL = 'https://gitlab.com'.freeze + def self.com? # Check `staging?` as well to keep parity with gitlab.com - Gitlab.config.gitlab.url == 'https://gitlab.com' || staging? + Gitlab.config.gitlab.url == COM_URL || staging? end def self.staging? diff --git a/lib/gitlab/auth.rb b/lib/gitlab/auth.rb index da07ba2f2a3..3933c3b04dd 100644 --- a/lib/gitlab/auth.rb +++ b/lib/gitlab/auth.rb @@ -37,7 +37,11 @@ module Gitlab rate_limit!(ip, success: result.success?, login: login) Gitlab::Auth::UniqueIpsLimiter.limit_user!(result.actor) - result + return result if result.success? || current_application_settings.signin_enabled? || Gitlab::LDAP::Config.enabled? + + # If sign-in is disabled and LDAP is not configured, recommend a + # personal access token on failed auth attempts + raise Gitlab::Auth::MissingPersonalTokenError end def find_with_user_password(login, password) diff --git a/lib/gitlab/ee_compat_check.rb b/lib/gitlab/ee_compat_check.rb index 38e27513281..6d326ee213a 100644 --- a/lib/gitlab/ee_compat_check.rb +++ b/lib/gitlab/ee_compat_check.rb @@ -76,13 +76,9 @@ module Gitlab step( "Generating the patch against origin/master in #{patch_path}", - %w[git format-patch origin/master --stdout] + %W[git diff --binary origin/master > #{patch_path}] ) do |output, status| - throw(:halt_check, :ko) unless status.zero? - - File.write(patch_path, output) - - throw(:halt_check, :ko) unless File.exist?(patch_path) + throw(:halt_check, :ko) unless status.zero? && File.exist?(patch_path) end end @@ -296,7 +292,7 @@ module Gitlab # In the CE repo $ git fetch origin master - $ git format-patch origin/master --stdout > #{ce_branch}.patch + $ git diff --binary origin/master > #{ce_branch}.patch # In the EE repo $ git fetch origin master diff --git a/lib/gitlab/git/blob.rb b/lib/gitlab/git/blob.rb index d60e607b02b..33a7624e303 100644 --- a/lib/gitlab/git/blob.rb +++ b/lib/gitlab/git/blob.rb @@ -123,6 +123,7 @@ module Gitlab @loaded_all_data = true @data = repository.lookup(id).content @loaded_size = @data.bytesize + @binary = nil end def name diff --git a/lib/gitlab/git/diff.rb b/lib/gitlab/git/diff.rb index 8926aa19925..88ad760bea3 100644 --- a/lib/gitlab/git/diff.rb +++ b/lib/gitlab/git/diff.rb @@ -23,6 +23,23 @@ module Gitlab class << self # The maximum size of a diff to display. def size_limit + if RequestStore.active? + RequestStore['gitlab_git_diff_size_limit'] ||= find_size_limit + else + find_size_limit + end + end + + # The maximum size before a diff is collapsed. + def collapse_limit + if RequestStore.active? + RequestStore['gitlab_git_diff_collapse_limit'] ||= find_collapse_limit + else + find_collapse_limit + end + end + + def find_size_limit if Feature.enabled?('gitlab_git_diff_size_limit_increase') 200.kilobytes else @@ -30,8 +47,7 @@ module Gitlab end end - # The maximum size before a diff is collapsed. - def collapse_limit + def find_collapse_limit if Feature.enabled?('gitlab_git_diff_size_limit_increase') 100.kilobytes else diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake index 63c5e9b9c83..858f1cd7b34 100644 --- a/lib/tasks/gitlab/check.rake +++ b/lib/tasks/gitlab/check.rake @@ -336,12 +336,9 @@ namespace :gitlab do ######################## def check_initd_configured_correctly - print "Init.d configured correctly? ... " + return if omnibus_gitlab? - if omnibus_gitlab? - puts 'skipped (omnibus-gitlab has no init script)'.color(:magenta) - return - end + print "Init.d configured correctly? ... " path = "/etc/default/gitlab" @@ -379,6 +376,8 @@ namespace :gitlab do end def check_mail_room_running + return if omnibus_gitlab? + print "MailRoom running? ... " path = "/etc/default/gitlab" diff --git a/locale/de/gitlab.po b/locale/de/gitlab.po Binary files differindex f9c14210958..9a660571db9 100644 --- a/locale/de/gitlab.po +++ b/locale/de/gitlab.po diff --git a/locale/en/gitlab.po b/locale/en/gitlab.po index ed0ccc61e67..4e44731fc5a 100644 --- a/locale/en/gitlab.po +++ b/locale/en/gitlab.po @@ -17,169 +17,23 @@ msgstr "" "Plural-Forms: nplurals=2; plural=n != 1;\n" "\n" -msgid "About auto deploy" -msgstr "" - -msgid "Activity" -msgstr "" - -msgid "Add Changelog" -msgstr "" - -msgid "Add Contribution guide" -msgstr "" - -msgid "Add License" -msgstr "" - -msgid "Add an SSH key to your profile to pull or push via SSH." -msgstr "" - -msgid "Add new directory" -msgstr "" - -msgid "Archived project! Repository is read-only" -msgstr "" - msgid "Are you sure you want to delete this pipeline schedule?" msgstr "" -msgid "Branch" -msgid_plural "Branches" -msgstr[0] "" -msgstr[1] "" - -msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}" -msgstr "" - -msgid "Branches" -msgstr "" - msgid "ByAuthor|by" msgstr "" -msgid "CI configuration" -msgstr "" - msgid "Cancel" msgstr "" -msgid "Changelog" -msgstr "" - -msgid "Charts" -msgstr "" - -msgid "CiStatusLabel|canceled" -msgstr "" - -msgid "CiStatusLabel|created" -msgstr "" - -msgid "CiStatusLabel|failed" -msgstr "" - -msgid "CiStatusLabel|manual action" -msgstr "" - -msgid "CiStatusLabel|passed" -msgstr "" - -msgid "CiStatusLabel|passed with warnings" -msgstr "" - -msgid "CiStatusLabel|pending" -msgstr "" - -msgid "CiStatusLabel|skipped" -msgstr "" - -msgid "CiStatusLabel|waiting for manual action" -msgstr "" - -msgid "CiStatusText|blocked" -msgstr "" - -msgid "CiStatusText|canceled" -msgstr "" - -msgid "CiStatusText|created" -msgstr "" - -msgid "CiStatusText|failed" -msgstr "" - -msgid "CiStatusText|manual" -msgstr "" - -msgid "CiStatusText|passed" -msgstr "" - -msgid "CiStatusText|pending" -msgstr "" - -msgid "CiStatusText|skipped" -msgstr "" - -msgid "CiStatus|running" -msgstr "" - msgid "Commit" msgid_plural "Commits" msgstr[0] "" msgstr[1] "" -msgid "CommitMessage|Add %{file_name}" -msgstr "" - -msgid "Commits" -msgstr "" - -msgid "Commits|History" -msgstr "" - -msgid "Compare" -msgstr "" - -msgid "Contribution guide" -msgstr "" - -msgid "Contributors" -msgstr "" - -msgid "Copy URL to clipboard" -msgstr "" - -msgid "Copy commit SHA to clipboard" -msgstr "" - -msgid "Create New Directory" -msgstr "" - -msgid "Create directory" -msgstr "" - -msgid "Create empty bare repository" -msgstr "" - -msgid "Create merge request" -msgstr "" - -msgid "CreateNewFork|Fork" -msgstr "" - msgid "Cron Timezone" msgstr "" -msgid "Custom notification events" -msgstr "" - -msgid "Custom notification levels are the same as participating levels. With custom notification levels you will also receive notifications for select events. To find out more, check out %{notification_link}." -msgstr "" - -msgid "Cycle Analytics" -msgstr "" - msgid "Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project." msgstr "" @@ -215,30 +69,6 @@ msgstr[1] "" msgid "Description" msgstr "" -msgid "Directory name" -msgstr "" - -msgid "Don't show again" -msgstr "" - -msgid "Download tar" -msgstr "" - -msgid "Download tar.bz2" -msgstr "" - -msgid "Download tar.gz" -msgstr "" - -msgid "Download zip" -msgstr "" - -msgid "DownloadArtifacts|Download" -msgstr "" - -msgid "DownloadSource|Download" -msgstr "" - msgid "Edit" msgstr "" @@ -251,63 +81,27 @@ msgstr "" msgid "Failed to remove the pipeline schedule" msgstr "" -msgid "Files" -msgstr "" - msgid "Filter" msgstr "" -msgid "Find by path" -msgstr "" - -msgid "Find file" -msgstr "" - msgid "FirstPushedBy|First" msgstr "" msgid "FirstPushedBy|pushed by" msgstr "" -msgid "ForkedFromProjectPath|Forked from" -msgstr "" - -msgid "Forks" -msgstr "" - msgid "From issue creation until deploy to production" msgstr "" msgid "From merge request merge until deploy to production" msgstr "" -msgid "Go to your fork" -msgstr "" - -msgid "GoToYourFork|Fork" -msgstr "" - -msgid "Home" -msgstr "" - -msgid "Housekeeping successfully started" -msgstr "" - -msgid "Import repository" -msgstr "" - msgid "Interval Pattern" msgstr "" msgid "Introducing Cycle Analytics" msgstr "" -msgid "LFSStatus|Disabled" -msgstr "" - -msgid "LFSStatus|Enabled" -msgstr "" - msgid "Last %d day" msgid_plural "Last %d days" msgstr[0] "" @@ -316,18 +110,6 @@ msgstr[1] "" msgid "Last Pipeline" msgstr "" -msgid "Last Update" -msgstr "" - -msgid "Last commit" -msgstr "" - -msgid "Leave group" -msgstr "" - -msgid "Leave project" -msgstr "" - msgid "Limited to showing %d event at most" msgid_plural "Limited to showing %d events at most" msgstr[0] "" @@ -336,9 +118,6 @@ msgstr[1] "" msgid "Median" msgstr "" -msgid "MissingSSHKeyWarningLink|add an SSH key" -msgstr "" - msgid "New Issue" msgid_plural "New Issues" msgstr[0] "" @@ -347,30 +126,6 @@ msgstr[1] "" msgid "New Pipeline Schedule" msgstr "" -msgid "New branch" -msgstr "" - -msgid "New directory" -msgstr "" - -msgid "New file" -msgstr "" - -msgid "New issue" -msgstr "" - -msgid "New merge request" -msgstr "" - -msgid "New snippet" -msgstr "" - -msgid "New tag" -msgstr "" - -msgid "No repository" -msgstr "" - msgid "No schedules" msgstr "" @@ -380,60 +135,6 @@ msgstr "" msgid "Not enough data" msgstr "" -msgid "Notification events" -msgstr "" - -msgid "NotificationEvent|Close issue" -msgstr "" - -msgid "NotificationEvent|Close merge request" -msgstr "" - -msgid "NotificationEvent|Failed pipeline" -msgstr "" - -msgid "NotificationEvent|Merge merge request" -msgstr "" - -msgid "NotificationEvent|New issue" -msgstr "" - -msgid "NotificationEvent|New merge request" -msgstr "" - -msgid "NotificationEvent|New note" -msgstr "" - -msgid "NotificationEvent|Reassign issue" -msgstr "" - -msgid "NotificationEvent|Reassign merge request" -msgstr "" - -msgid "NotificationEvent|Reopen issue" -msgstr "" - -msgid "NotificationEvent|Successful pipeline" -msgstr "" - -msgid "NotificationLevel|Custom" -msgstr "" - -msgid "NotificationLevel|Disabled" -msgstr "" - -msgid "NotificationLevel|Global" -msgstr "" - -msgid "NotificationLevel|On mention" -msgstr "" - -msgid "NotificationLevel|Participate" -msgstr "" - -msgid "NotificationLevel|Watch" -msgstr "" - msgid "OpenedNDaysAgo|Opened" msgstr "" @@ -476,69 +177,12 @@ msgstr "" msgid "PipelineSchedules|Target" msgstr "" -msgid "Project '%{project_name}' queued for deletion." -msgstr "" - -msgid "Project '%{project_name}' was successfully created." -msgstr "" - -msgid "Project '%{project_name}' was successfully updated." -msgstr "" - -msgid "Project '%{project_name}' will be deleted." -msgstr "" - -msgid "Project access must be granted explicitly to each user." -msgstr "" - -msgid "Project export could not be deleted." -msgstr "" - -msgid "Project export has been deleted." -msgstr "" - -msgid "Project export link has expired. Please generate a new export from your project settings." -msgstr "" - -msgid "Project export started. A download link will be sent by email." -msgstr "" - -msgid "Project home" -msgstr "" - -msgid "ProjectFeature|Disabled" -msgstr "" - -msgid "ProjectFeature|Everyone with access" -msgstr "" - -msgid "ProjectFeature|Only team members" -msgstr "" - -msgid "ProjectFileTree|Name" -msgstr "" - -msgid "ProjectLastActivity|Never" -msgstr "" - msgid "ProjectLifecycle|Stage" msgstr "" -msgid "ProjectNetworkGraph|Graph" -msgstr "" - msgid "Read more" msgstr "" -msgid "Readme" -msgstr "" - -msgid "RefSwitcher|Branches" -msgstr "" - -msgid "RefSwitcher|Tags" -msgstr "" - msgid "Related Commits" msgstr "" @@ -557,70 +201,23 @@ msgstr "" msgid "Related Merged Requests" msgstr "" -msgid "Remind later" -msgstr "" - -msgid "Remove project" -msgstr "" - -msgid "Request Access" -msgstr "" - msgid "Save pipeline schedule" msgstr "" msgid "Schedule a new pipeline" msgstr "" -msgid "Search branches and tags" -msgstr "" - -msgid "Select Archive Format" -msgstr "" - msgid "Select a timezone" msgstr "" msgid "Select target branch" msgstr "" -msgid "Set a password on your account to pull or push via %{protocol}" -msgstr "" - -msgid "Set up CI" -msgstr "" - -msgid "Set up Koding" -msgstr "" - -msgid "Set up auto deploy" -msgstr "" - -msgid "SetPasswordToCloneLink|set a password" -msgstr "" - msgid "Showing %d event" msgid_plural "Showing %d events" msgstr[0] "" msgstr[1] "" -msgid "Source code" -msgstr "" - -msgid "StarProject|Star" -msgstr "" - -msgid "Switch branch/tag" -msgstr "" - -msgid "Tag" -msgid_plural "Tags" -msgstr[0] "" -msgstr[1] "" - -msgid "Tags" -msgstr "" - msgid "Target Branch" msgstr "" @@ -630,9 +227,6 @@ msgstr "" msgid "The collection of events added to the data gathered for that stage." msgstr "" -msgid "The fork relationship has been removed." -msgstr "" - msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage." msgstr "" @@ -645,15 +239,6 @@ msgstr "" msgid "The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle." msgstr "" -msgid "The project can be accessed by any logged in user." -msgstr "" - -msgid "The project can be accessed without any authentication." -msgstr "" - -msgid "The repository for this project does not exist." -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 "" @@ -669,9 +254,6 @@ msgstr "" msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6." msgstr "" -msgid "This means you can not push code until you create an empty repository or import existing one." -msgstr "" - msgid "Time before an issue gets scheduled" msgstr "" @@ -684,129 +266,6 @@ msgstr "" msgid "Time until first merge request" msgstr "" -msgid "Timeago|%s days ago" -msgstr "" - -msgid "Timeago|%s days remaining" -msgstr "" - -msgid "Timeago|%s hours remaining" -msgstr "" - -msgid "Timeago|%s minutes ago" -msgstr "" - -msgid "Timeago|%s minutes remaining" -msgstr "" - -msgid "Timeago|%s months ago" -msgstr "" - -msgid "Timeago|%s months remaining" -msgstr "" - -msgid "Timeago|%s seconds remaining" -msgstr "" - -msgid "Timeago|%s weeks ago" -msgstr "" - -msgid "Timeago|%s weeks remaining" -msgstr "" - -msgid "Timeago|%s years ago" -msgstr "" - -msgid "Timeago|%s years remaining" -msgstr "" - -msgid "Timeago|1 day remaining" -msgstr "" - -msgid "Timeago|1 hour remaining" -msgstr "" - -msgid "Timeago|1 minute remaining" -msgstr "" - -msgid "Timeago|1 month remaining" -msgstr "" - -msgid "Timeago|1 week remaining" -msgstr "" - -msgid "Timeago|1 year remaining" -msgstr "" - -msgid "Timeago|Past due" -msgstr "" - -msgid "Timeago|a day ago" -msgstr "" - -msgid "Timeago|a month ago" -msgstr "" - -msgid "Timeago|a week ago" -msgstr "" - -msgid "Timeago|a while" -msgstr "" - -msgid "Timeago|a year ago" -msgstr "" - -msgid "Timeago|about %s hours ago" -msgstr "" - -msgid "Timeago|about a minute ago" -msgstr "" - -msgid "Timeago|about an hour ago" -msgstr "" - -msgid "Timeago|in %s days" -msgstr "" - -msgid "Timeago|in %s hours" -msgstr "" - -msgid "Timeago|in %s minutes" -msgstr "" - -msgid "Timeago|in %s months" -msgstr "" - -msgid "Timeago|in %s seconds" -msgstr "" - -msgid "Timeago|in %s weeks" -msgstr "" - -msgid "Timeago|in %s years" -msgstr "" - -msgid "Timeago|in 1 day" -msgstr "" - -msgid "Timeago|in 1 hour" -msgstr "" - -msgid "Timeago|in 1 minute" -msgstr "" - -msgid "Timeago|in 1 month" -msgstr "" - -msgid "Timeago|in 1 week" -msgstr "" - -msgid "Timeago|in 1 year" -msgstr "" - -msgid "Timeago|less than a minute ago" -msgstr "" - msgid "Time|hr" msgid_plural "Time|hrs" msgstr[0] "" @@ -826,88 +285,16 @@ msgstr "" msgid "Total test time for all commits/merges" msgstr "" -msgid "Unstar" -msgstr "" - -msgid "Upload New File" -msgstr "" - -msgid "Upload file" -msgstr "" - -msgid "Use your global notification setting" -msgstr "" - -msgid "VisibilityLevel|Internal" -msgstr "" - -msgid "VisibilityLevel|Private" -msgstr "" - -msgid "VisibilityLevel|Public" -msgstr "" - msgid "Want to see the data? Please ask an administrator for access." msgstr "" msgid "We don't have enough data to show this stage." msgstr "" -msgid "Withdraw Access Request" -msgstr "" - -msgid "" -"You are going to remove %{project_name_with_namespace}.\n" -"Removed project CANNOT be restored!\n" -"Are you ABSOLUTELY sure?" -msgstr "" - -msgid "You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?" -msgstr "" - -msgid "You are going to transfer %{project_name_with_namespace} to another owner. Are you ABSOLUTELY sure?" -msgstr "" - -msgid "You can only add files when you are on a branch" -msgstr "" - -msgid "You must sign in to star a project" -msgstr "" - msgid "You need permission." msgstr "" -msgid "You will not get any notifications via email" -msgstr "" - -msgid "You will only receive notifications for the events you choose" -msgstr "" - -msgid "You will only receive notifications for threads you have participated in" -msgstr "" - -msgid "You will receive notifications for any activity" -msgstr "" - -msgid "You will receive notifications only for comments in which you were @mentioned" -msgstr "" - -msgid "You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account" -msgstr "" - -msgid "You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile" -msgstr "" - -msgid "Your name" -msgstr "" - -msgid "committed" -msgstr "" - msgid "day" msgid_plural "days" msgstr[0] "" msgstr[1] "" - -msgid "notification emails" -msgstr "" diff --git a/locale/es/gitlab.po b/locale/es/gitlab.po Binary files differindex 1bbc413e24c..78d28d69885 100644 --- a/locale/es/gitlab.po +++ b/locale/es/gitlab.po diff --git a/locale/gitlab.pot b/locale/gitlab.pot index c967b720885..050f6c446c1 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -8,8 +8,8 @@ msgid "" msgstr "" "Project-Id-Version: gitlab 1.0.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2017-06-08 09:42+0200\n" -"PO-Revision-Date: 2017-06-08 09:42+0200\n" +"POT-Creation-Date: 2017-06-07 21:22+0200\n" +"PO-Revision-Date: 2017-06-07 21:22+0200\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" "Language: \n" @@ -18,169 +18,23 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" -msgid "About auto deploy" -msgstr "" - -msgid "Activity" -msgstr "" - -msgid "Add Changelog" -msgstr "" - -msgid "Add Contribution guide" -msgstr "" - -msgid "Add License" -msgstr "" - -msgid "Add an SSH key to your profile to pull or push via SSH." -msgstr "" - -msgid "Add new directory" -msgstr "" - -msgid "Archived project! Repository is read-only" -msgstr "" - msgid "Are you sure you want to delete this pipeline schedule?" msgstr "" -msgid "Branch" -msgid_plural "Branches" -msgstr[0] "" -msgstr[1] "" - -msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}" -msgstr "" - -msgid "Branches" -msgstr "" - msgid "ByAuthor|by" msgstr "" -msgid "CI configuration" -msgstr "" - msgid "Cancel" msgstr "" -msgid "Changelog" -msgstr "" - -msgid "Charts" -msgstr "" - -msgid "CiStatusLabel|canceled" -msgstr "" - -msgid "CiStatusLabel|created" -msgstr "" - -msgid "CiStatusLabel|failed" -msgstr "" - -msgid "CiStatusLabel|manual action" -msgstr "" - -msgid "CiStatusLabel|passed" -msgstr "" - -msgid "CiStatusLabel|passed with warnings" -msgstr "" - -msgid "CiStatusLabel|pending" -msgstr "" - -msgid "CiStatusLabel|skipped" -msgstr "" - -msgid "CiStatusLabel|waiting for manual action" -msgstr "" - -msgid "CiStatusText|blocked" -msgstr "" - -msgid "CiStatusText|canceled" -msgstr "" - -msgid "CiStatusText|created" -msgstr "" - -msgid "CiStatusText|failed" -msgstr "" - -msgid "CiStatusText|manual" -msgstr "" - -msgid "CiStatusText|passed" -msgstr "" - -msgid "CiStatusText|pending" -msgstr "" - -msgid "CiStatusText|skipped" -msgstr "" - -msgid "CiStatus|running" -msgstr "" - msgid "Commit" msgid_plural "Commits" msgstr[0] "" msgstr[1] "" -msgid "CommitMessage|Add %{file_name}" -msgstr "" - -msgid "Commits" -msgstr "" - -msgid "Commits|History" -msgstr "" - -msgid "Compare" -msgstr "" - -msgid "Contribution guide" -msgstr "" - -msgid "Contributors" -msgstr "" - -msgid "Copy URL to clipboard" -msgstr "" - -msgid "Copy commit SHA to clipboard" -msgstr "" - -msgid "Create New Directory" -msgstr "" - -msgid "Create directory" -msgstr "" - -msgid "Create empty bare repository" -msgstr "" - -msgid "Create merge request" -msgstr "" - -msgid "CreateNewFork|Fork" -msgstr "" - msgid "Cron Timezone" msgstr "" -msgid "Custom notification events" -msgstr "" - -msgid "Custom notification levels are the same as participating levels. With custom notification levels you will also receive notifications for select events. To find out more, check out %{notification_link}." -msgstr "" - -msgid "Cycle Analytics" -msgstr "" - msgid "Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project." msgstr "" @@ -216,30 +70,6 @@ msgstr[1] "" msgid "Description" msgstr "" -msgid "Directory name" -msgstr "" - -msgid "Don't show again" -msgstr "" - -msgid "Download tar" -msgstr "" - -msgid "Download tar.bz2" -msgstr "" - -msgid "Download tar.gz" -msgstr "" - -msgid "Download zip" -msgstr "" - -msgid "DownloadArtifacts|Download" -msgstr "" - -msgid "DownloadSource|Download" -msgstr "" - msgid "Edit" msgstr "" @@ -252,63 +82,27 @@ msgstr "" msgid "Failed to remove the pipeline schedule" msgstr "" -msgid "Files" -msgstr "" - msgid "Filter" msgstr "" -msgid "Find by path" -msgstr "" - -msgid "Find file" -msgstr "" - msgid "FirstPushedBy|First" msgstr "" msgid "FirstPushedBy|pushed by" msgstr "" -msgid "ForkedFromProjectPath|Forked from" -msgstr "" - -msgid "Forks" -msgstr "" - msgid "From issue creation until deploy to production" msgstr "" msgid "From merge request merge until deploy to production" msgstr "" -msgid "Go to your fork" -msgstr "" - -msgid "GoToYourFork|Fork" -msgstr "" - -msgid "Home" -msgstr "" - -msgid "Housekeeping successfully started" -msgstr "" - -msgid "Import repository" -msgstr "" - msgid "Interval Pattern" msgstr "" msgid "Introducing Cycle Analytics" msgstr "" -msgid "LFSStatus|Disabled" -msgstr "" - -msgid "LFSStatus|Enabled" -msgstr "" - msgid "Last %d day" msgid_plural "Last %d days" msgstr[0] "" @@ -317,18 +111,6 @@ msgstr[1] "" msgid "Last Pipeline" msgstr "" -msgid "Last Update" -msgstr "" - -msgid "Last commit" -msgstr "" - -msgid "Leave group" -msgstr "" - -msgid "Leave project" -msgstr "" - msgid "Limited to showing %d event at most" msgid_plural "Limited to showing %d events at most" msgstr[0] "" @@ -337,9 +119,6 @@ msgstr[1] "" msgid "Median" msgstr "" -msgid "MissingSSHKeyWarningLink|add an SSH key" -msgstr "" - msgid "New Issue" msgid_plural "New Issues" msgstr[0] "" @@ -348,30 +127,6 @@ msgstr[1] "" msgid "New Pipeline Schedule" msgstr "" -msgid "New branch" -msgstr "" - -msgid "New directory" -msgstr "" - -msgid "New file" -msgstr "" - -msgid "New issue" -msgstr "" - -msgid "New merge request" -msgstr "" - -msgid "New snippet" -msgstr "" - -msgid "New tag" -msgstr "" - -msgid "No repository" -msgstr "" - msgid "No schedules" msgstr "" @@ -381,60 +136,6 @@ msgstr "" msgid "Not enough data" msgstr "" -msgid "Notification events" -msgstr "" - -msgid "NotificationEvent|Close issue" -msgstr "" - -msgid "NotificationEvent|Close merge request" -msgstr "" - -msgid "NotificationEvent|Failed pipeline" -msgstr "" - -msgid "NotificationEvent|Merge merge request" -msgstr "" - -msgid "NotificationEvent|New issue" -msgstr "" - -msgid "NotificationEvent|New merge request" -msgstr "" - -msgid "NotificationEvent|New note" -msgstr "" - -msgid "NotificationEvent|Reassign issue" -msgstr "" - -msgid "NotificationEvent|Reassign merge request" -msgstr "" - -msgid "NotificationEvent|Reopen issue" -msgstr "" - -msgid "NotificationEvent|Successful pipeline" -msgstr "" - -msgid "NotificationLevel|Custom" -msgstr "" - -msgid "NotificationLevel|Disabled" -msgstr "" - -msgid "NotificationLevel|Global" -msgstr "" - -msgid "NotificationLevel|On mention" -msgstr "" - -msgid "NotificationLevel|Participate" -msgstr "" - -msgid "NotificationLevel|Watch" -msgstr "" - msgid "OpenedNDaysAgo|Opened" msgstr "" @@ -477,69 +178,12 @@ msgstr "" msgid "PipelineSchedules|Target" msgstr "" -msgid "Project '%{project_name}' queued for deletion." -msgstr "" - -msgid "Project '%{project_name}' was successfully created." -msgstr "" - -msgid "Project '%{project_name}' was successfully updated." -msgstr "" - -msgid "Project '%{project_name}' will be deleted." -msgstr "" - -msgid "Project access must be granted explicitly to each user." -msgstr "" - -msgid "Project export could not be deleted." -msgstr "" - -msgid "Project export has been deleted." -msgstr "" - -msgid "Project export link has expired. Please generate a new export from your project settings." -msgstr "" - -msgid "Project export started. A download link will be sent by email." -msgstr "" - -msgid "Project home" -msgstr "" - -msgid "ProjectFeature|Disabled" -msgstr "" - -msgid "ProjectFeature|Everyone with access" -msgstr "" - -msgid "ProjectFeature|Only team members" -msgstr "" - -msgid "ProjectFileTree|Name" -msgstr "" - -msgid "ProjectLastActivity|Never" -msgstr "" - msgid "ProjectLifecycle|Stage" msgstr "" -msgid "ProjectNetworkGraph|Graph" -msgstr "" - msgid "Read more" msgstr "" -msgid "Readme" -msgstr "" - -msgid "RefSwitcher|Branches" -msgstr "" - -msgid "RefSwitcher|Tags" -msgstr "" - msgid "Related Commits" msgstr "" @@ -558,70 +202,23 @@ msgstr "" msgid "Related Merged Requests" msgstr "" -msgid "Remind later" -msgstr "" - -msgid "Remove project" -msgstr "" - -msgid "Request Access" -msgstr "" - msgid "Save pipeline schedule" msgstr "" msgid "Schedule a new pipeline" msgstr "" -msgid "Search branches and tags" -msgstr "" - -msgid "Select Archive Format" -msgstr "" - msgid "Select a timezone" msgstr "" msgid "Select target branch" msgstr "" -msgid "Set a password on your account to pull or push via %{protocol}" -msgstr "" - -msgid "Set up CI" -msgstr "" - -msgid "Set up Koding" -msgstr "" - -msgid "Set up auto deploy" -msgstr "" - -msgid "SetPasswordToCloneLink|set a password" -msgstr "" - msgid "Showing %d event" msgid_plural "Showing %d events" msgstr[0] "" msgstr[1] "" -msgid "Source code" -msgstr "" - -msgid "StarProject|Star" -msgstr "" - -msgid "Switch branch/tag" -msgstr "" - -msgid "Tag" -msgid_plural "Tags" -msgstr[0] "" -msgstr[1] "" - -msgid "Tags" -msgstr "" - msgid "Target Branch" msgstr "" @@ -631,9 +228,6 @@ msgstr "" msgid "The collection of events added to the data gathered for that stage." msgstr "" -msgid "The fork relationship has been removed." -msgstr "" - msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage." msgstr "" @@ -646,15 +240,6 @@ msgstr "" msgid "The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle." msgstr "" -msgid "The project can be accessed by any logged in user." -msgstr "" - -msgid "The project can be accessed without any authentication." -msgstr "" - -msgid "The repository for this project does not exist." -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 "" @@ -670,9 +255,6 @@ msgstr "" msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6." msgstr "" -msgid "This means you can not push code until you create an empty repository or import existing one." -msgstr "" - msgid "Time before an issue gets scheduled" msgstr "" @@ -685,129 +267,6 @@ msgstr "" msgid "Time until first merge request" msgstr "" -msgid "Timeago|%s days ago" -msgstr "" - -msgid "Timeago|%s days remaining" -msgstr "" - -msgid "Timeago|%s hours remaining" -msgstr "" - -msgid "Timeago|%s minutes ago" -msgstr "" - -msgid "Timeago|%s minutes remaining" -msgstr "" - -msgid "Timeago|%s months ago" -msgstr "" - -msgid "Timeago|%s months remaining" -msgstr "" - -msgid "Timeago|%s seconds remaining" -msgstr "" - -msgid "Timeago|%s weeks ago" -msgstr "" - -msgid "Timeago|%s weeks remaining" -msgstr "" - -msgid "Timeago|%s years ago" -msgstr "" - -msgid "Timeago|%s years remaining" -msgstr "" - -msgid "Timeago|1 day remaining" -msgstr "" - -msgid "Timeago|1 hour remaining" -msgstr "" - -msgid "Timeago|1 minute remaining" -msgstr "" - -msgid "Timeago|1 month remaining" -msgstr "" - -msgid "Timeago|1 week remaining" -msgstr "" - -msgid "Timeago|1 year remaining" -msgstr "" - -msgid "Timeago|Past due" -msgstr "" - -msgid "Timeago|a day ago" -msgstr "" - -msgid "Timeago|a month ago" -msgstr "" - -msgid "Timeago|a week ago" -msgstr "" - -msgid "Timeago|a while" -msgstr "" - -msgid "Timeago|a year ago" -msgstr "" - -msgid "Timeago|about %s hours ago" -msgstr "" - -msgid "Timeago|about a minute ago" -msgstr "" - -msgid "Timeago|about an hour ago" -msgstr "" - -msgid "Timeago|in %s days" -msgstr "" - -msgid "Timeago|in %s hours" -msgstr "" - -msgid "Timeago|in %s minutes" -msgstr "" - -msgid "Timeago|in %s months" -msgstr "" - -msgid "Timeago|in %s seconds" -msgstr "" - -msgid "Timeago|in %s weeks" -msgstr "" - -msgid "Timeago|in %s years" -msgstr "" - -msgid "Timeago|in 1 day" -msgstr "" - -msgid "Timeago|in 1 hour" -msgstr "" - -msgid "Timeago|in 1 minute" -msgstr "" - -msgid "Timeago|in 1 month" -msgstr "" - -msgid "Timeago|in 1 week" -msgstr "" - -msgid "Timeago|in 1 year" -msgstr "" - -msgid "Timeago|less than a minute ago" -msgstr "" - msgid "Time|hr" msgid_plural "Time|hrs" msgstr[0] "" @@ -827,88 +286,16 @@ msgstr "" msgid "Total test time for all commits/merges" msgstr "" -msgid "Unstar" -msgstr "" - -msgid "Upload New File" -msgstr "" - -msgid "Upload file" -msgstr "" - -msgid "Use your global notification setting" -msgstr "" - -msgid "VisibilityLevel|Internal" -msgstr "" - -msgid "VisibilityLevel|Private" -msgstr "" - -msgid "VisibilityLevel|Public" -msgstr "" - msgid "Want to see the data? Please ask an administrator for access." msgstr "" msgid "We don't have enough data to show this stage." msgstr "" -msgid "Withdraw Access Request" -msgstr "" - -msgid "" -"You are going to remove %{project_name_with_namespace}.\n" -"Removed project CANNOT be restored!\n" -"Are you ABSOLUTELY sure?" -msgstr "" - -msgid "You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?" -msgstr "" - -msgid "You are going to transfer %{project_name_with_namespace} to another owner. Are you ABSOLUTELY sure?" -msgstr "" - -msgid "You can only add files when you are on a branch" -msgstr "" - -msgid "You must sign in to star a project" -msgstr "" - msgid "You need permission." msgstr "" -msgid "You will not get any notifications via email" -msgstr "" - -msgid "You will only receive notifications for the events you choose" -msgstr "" - -msgid "You will only receive notifications for threads you have participated in" -msgstr "" - -msgid "You will receive notifications for any activity" -msgstr "" - -msgid "You will receive notifications only for comments in which you were @mentioned" -msgstr "" - -msgid "You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account" -msgstr "" - -msgid "You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile" -msgstr "" - -msgid "Your name" -msgstr "" - -msgid "committed" -msgstr "" - msgid "day" msgid_plural "days" msgstr[0] "" msgstr[1] "" - -msgid "notification emails" -msgstr "" diff --git a/locale/zh_CN/gitlab.po b/locale/zh_CN/gitlab.po index 176dd68b52f..11434460207 100644 --- a/locale/zh_CN/gitlab.po +++ b/locale/zh_CN/gitlab.po @@ -17,172 +17,22 @@ msgstr "" "Language: zh_CN\n" "Plural-Forms: nplurals=1; plural=0;\n" -msgid "About auto deploy" -msgstr "" - -msgid "Activity" -msgstr "" - -msgid "Add Changelog" -msgstr "" - -msgid "Add Contribution guide" -msgstr "" - -msgid "Add License" -msgstr "" - -msgid "Add an SSH key to your profile to pull or push via SSH." -msgstr "" - -msgid "Add new directory" -msgstr "" - -msgid "Archived project! Repository is read-only" -msgstr "" - msgid "Are you sure you want to delete this pipeline schedule?" msgstr "" -msgid "Branch" -msgid_plural "Branches" -msgstr[0] "" -msgstr[1] "" - -msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}" -msgstr "" - -msgid "Branches" -msgstr "" - msgid "ByAuthor|by" msgstr "作者:" -msgid "CI configuration" -msgstr "" - msgid "Cancel" msgstr "" -msgid "Changelog" -msgstr "" - -msgid "Charts" -msgstr "" - -msgid "CiStatusLabel|canceled" -msgstr "" - -msgid "CiStatusLabel|created" -msgstr "" - -msgid "CiStatusLabel|failed" -msgstr "" - -msgid "CiStatusLabel|manual action" -msgstr "" - -msgid "CiStatusLabel|passed" -msgstr "" - -msgid "CiStatusLabel|passed with warnings" -msgstr "" - -msgid "CiStatusLabel|pending" -msgstr "" - -msgid "CiStatusLabel|skipped" -msgstr "" - -msgid "CiStatusLabel|waiting for manual action" -msgstr "" - -msgid "CiStatusText|blocked" -msgstr "" - -msgid "CiStatusText|canceled" -msgstr "" - -msgid "CiStatusText|created" -msgstr "" - -msgid "CiStatusText|failed" -msgstr "" - -msgid "CiStatusText|manual" -msgstr "" - -msgid "CiStatusText|passed" -msgstr "" - -msgid "CiStatusText|pending" -msgstr "" - -msgid "CiStatusText|skipped" -msgstr "" - -msgid "CiStatus|running" -msgstr "" - msgid "Commit" msgid_plural "Commits" msgstr[0] "提交" -#, fuzzy -msgid "CommitMessage|Add %{file_name}" -msgstr "提交" - -#, fuzzy -msgid "Commits" -msgstr "提交" - -#, fuzzy -msgid "Commits|History" -msgstr "提交" - -msgid "Compare" -msgstr "" - -msgid "Contribution guide" -msgstr "" - -msgid "Contributors" -msgstr "" - -msgid "Copy URL to clipboard" -msgstr "" - -msgid "Copy commit SHA to clipboard" -msgstr "" - -msgid "Create New Directory" -msgstr "" - -msgid "Create directory" -msgstr "" - -msgid "Create empty bare repository" -msgstr "" - -#, fuzzy -msgid "Create merge request" -msgstr "相关的合并请求" - -msgid "CreateNewFork|Fork" -msgstr "" - msgid "Cron Timezone" msgstr "" -msgid "Custom notification events" -msgstr "" - -msgid "Custom notification levels are the same as participating levels. With custom notification levels you will also receive notifications for select events. To find out more, check out %{notification_link}." -msgstr "" - -msgid "Cycle Analytics" -msgstr "" - msgid "Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project." msgstr "周期分析概述了项目从想法到产品实现的各阶段所需的时间。" @@ -217,30 +67,6 @@ msgstr[0] "部署" msgid "Description" msgstr "" -msgid "Directory name" -msgstr "" - -msgid "Don't show again" -msgstr "" - -msgid "Download tar" -msgstr "" - -msgid "Download tar.bz2" -msgstr "" - -msgid "Download tar.gz" -msgstr "" - -msgid "Download zip" -msgstr "" - -msgid "DownloadArtifacts|Download" -msgstr "" - -msgid "DownloadSource|Download" -msgstr "" - msgid "Edit" msgstr "" @@ -253,63 +79,27 @@ msgstr "" msgid "Failed to remove the pipeline schedule" msgstr "" -msgid "Files" -msgstr "" - msgid "Filter" msgstr "" -msgid "Find by path" -msgstr "" - -msgid "Find file" -msgstr "" - msgid "FirstPushedBy|First" msgstr "首次推送" msgid "FirstPushedBy|pushed by" msgstr "推送者:" -msgid "ForkedFromProjectPath|Forked from" -msgstr "" - -msgid "Forks" -msgstr "" - msgid "From issue creation until deploy to production" msgstr "从创建议题到部署至生产环境" msgid "From merge request merge until deploy to production" msgstr "从合并请求被合并后到部署至生产环境" -msgid "Go to your fork" -msgstr "" - -msgid "GoToYourFork|Fork" -msgstr "" - -msgid "Home" -msgstr "" - -msgid "Housekeeping successfully started" -msgstr "" - -msgid "Import repository" -msgstr "" - msgid "Interval Pattern" msgstr "" msgid "Introducing Cycle Analytics" msgstr "周期分析简介" -msgid "LFSStatus|Disabled" -msgstr "" - -msgid "LFSStatus|Enabled" -msgstr "" - msgid "Last %d day" msgid_plural "Last %d days" msgstr[0] "最后 %d 天" @@ -317,18 +107,6 @@ msgstr[0] "最后 %d 天" msgid "Last Pipeline" msgstr "" -msgid "Last Update" -msgstr "" - -msgid "Last commit" -msgstr "" - -msgid "Leave group" -msgstr "" - -msgid "Leave project" -msgstr "" - msgid "Limited to showing %d event at most" msgid_plural "Limited to showing %d events at most" msgstr[0] "最多显示 %d 个事件" @@ -336,9 +114,6 @@ msgstr[0] "最多显示 %d 个事件" msgid "Median" msgstr "中位数" -msgid "MissingSSHKeyWarningLink|add an SSH key" -msgstr "" - msgid "New Issue" msgid_plural "New Issues" msgstr[0] "新议题" @@ -346,31 +121,6 @@ msgstr[0] "新议题" msgid "New Pipeline Schedule" msgstr "" -msgid "New branch" -msgstr "" - -msgid "New directory" -msgstr "" - -msgid "New file" -msgstr "" - -#, fuzzy -msgid "New issue" -msgstr "新议题" - -msgid "New merge request" -msgstr "" - -msgid "New snippet" -msgstr "" - -msgid "New tag" -msgstr "" - -msgid "No repository" -msgstr "" - msgid "No schedules" msgstr "" @@ -380,60 +130,6 @@ msgstr "数据不足" msgid "Not enough data" msgstr "数据不足" -msgid "Notification events" -msgstr "" - -msgid "NotificationEvent|Close issue" -msgstr "" - -msgid "NotificationEvent|Close merge request" -msgstr "" - -msgid "NotificationEvent|Failed pipeline" -msgstr "" - -msgid "NotificationEvent|Merge merge request" -msgstr "" - -msgid "NotificationEvent|New issue" -msgstr "" - -msgid "NotificationEvent|New merge request" -msgstr "" - -msgid "NotificationEvent|New note" -msgstr "" - -msgid "NotificationEvent|Reassign issue" -msgstr "" - -msgid "NotificationEvent|Reassign merge request" -msgstr "" - -msgid "NotificationEvent|Reopen issue" -msgstr "" - -msgid "NotificationEvent|Successful pipeline" -msgstr "" - -msgid "NotificationLevel|Custom" -msgstr "" - -msgid "NotificationLevel|Disabled" -msgstr "" - -msgid "NotificationLevel|Global" -msgstr "" - -msgid "NotificationLevel|On mention" -msgstr "" - -msgid "NotificationLevel|Participate" -msgstr "" - -msgid "NotificationLevel|Watch" -msgstr "" - msgid "OpenedNDaysAgo|Opened" msgstr "开始于" @@ -476,70 +172,12 @@ msgstr "" msgid "PipelineSchedules|Target" msgstr "" -msgid "Project '%{project_name}' queued for deletion." -msgstr "" - -msgid "Project '%{project_name}' was successfully created." -msgstr "" - -msgid "Project '%{project_name}' was successfully updated." -msgstr "" - -msgid "Project '%{project_name}' will be deleted." -msgstr "" - -msgid "Project access must be granted explicitly to each user." -msgstr "" - -msgid "Project export could not be deleted." -msgstr "" - -msgid "Project export has been deleted." -msgstr "" - -msgid "Project export link has expired. Please generate a new export from your project settings." -msgstr "" - -msgid "Project export started. A download link will be sent by email." -msgstr "" - -msgid "Project home" -msgstr "" - -msgid "ProjectFeature|Disabled" -msgstr "" - -msgid "ProjectFeature|Everyone with access" -msgstr "" - -msgid "ProjectFeature|Only team members" -msgstr "" - -msgid "ProjectFileTree|Name" -msgstr "" - -msgid "ProjectLastActivity|Never" -msgstr "" - msgid "ProjectLifecycle|Stage" msgstr "项目生命周期" -msgid "ProjectNetworkGraph|Graph" -msgstr "" - msgid "Read more" msgstr "了解更多" -#, fuzzy -msgid "Readme" -msgstr "了解更多" - -msgid "RefSwitcher|Branches" -msgstr "" - -msgid "RefSwitcher|Tags" -msgstr "" - msgid "Related Commits" msgstr "相关的提交" @@ -558,69 +196,22 @@ msgstr "相关的合并请求" msgid "Related Merged Requests" msgstr "相关已合并的合并请求" -msgid "Remind later" -msgstr "" - -msgid "Remove project" -msgstr "" - -msgid "Request Access" -msgstr "" - msgid "Save pipeline schedule" msgstr "" msgid "Schedule a new pipeline" msgstr "" -msgid "Search branches and tags" -msgstr "" - -msgid "Select Archive Format" -msgstr "" - msgid "Select a timezone" msgstr "" msgid "Select target branch" msgstr "" -msgid "Set a password on your account to pull or push via %{protocol}" -msgstr "" - -msgid "Set up CI" -msgstr "" - -msgid "Set up Koding" -msgstr "" - -msgid "Set up auto deploy" -msgstr "" - -msgid "SetPasswordToCloneLink|set a password" -msgstr "" - msgid "Showing %d event" msgid_plural "Showing %d events" msgstr[0] "显示 %d 个事件" -msgid "Source code" -msgstr "" - -msgid "StarProject|Star" -msgstr "" - -msgid "Switch branch/tag" -msgstr "" - -msgid "Tag" -msgid_plural "Tags" -msgstr[0] "" -msgstr[1] "" - -msgid "Tags" -msgstr "" - msgid "Target Branch" msgstr "" @@ -630,9 +221,6 @@ msgstr "编码阶段概述了从第一次提交到创建合并请求的时间。 msgid "The collection of events added to the data gathered for that stage." msgstr "与该阶段相关的事件。" -msgid "The fork relationship has been removed." -msgstr "" - msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage." msgstr "议题阶段概述了从创建议题到将议题设置里程碑或将议题添加到议题看板的时间。开始创建议题以查看此阶段的数据。" @@ -645,15 +233,6 @@ msgstr "计划阶段概述了从议题添加到日程后到推送首次提交的 msgid "The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle." msgstr "生产阶段概述了从创建一个议题到将代码部署到生产环境的总时间。当完成想法到部署生产的循环,数据将自动添加到此处。" -msgid "The project can be accessed by any logged in user." -msgstr "" - -msgid "The project can be accessed without any authentication." -msgstr "" - -msgid "The repository for this project does not exist." -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 "评审阶段概述了从创建合并请求到被合并的时间。当创建第一个合并请求后,数据将自动添加到此处。" @@ -669,9 +248,6 @@ msgstr "该阶段每条数据所花的时间" msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6." msgstr "中位数是一个数列中最中间的值。例如在 3、5、9 之间,中位数是 5。在 3、5、7、8 之间,中位数是 (5 + 7)/ 2 = 6。" -msgid "This means you can not push code until you create an empty repository or import existing one." -msgstr "" - msgid "Time before an issue gets scheduled" msgstr "议题被列入日程表的时间" @@ -684,135 +260,6 @@ msgstr "从创建合并请求到被合并或关闭的时间" msgid "Time until first merge request" msgstr "创建第一个合并请求之前的时间" -#, fuzzy -msgid "Timeago|%s days ago" -msgstr "天" - -#, fuzzy -msgid "Timeago|%s days remaining" -msgstr "天" - -msgid "Timeago|%s hours remaining" -msgstr "" - -msgid "Timeago|%s minutes ago" -msgstr "" - -msgid "Timeago|%s minutes remaining" -msgstr "" - -msgid "Timeago|%s months ago" -msgstr "" - -msgid "Timeago|%s months remaining" -msgstr "" - -msgid "Timeago|%s seconds remaining" -msgstr "" - -msgid "Timeago|%s weeks ago" -msgstr "" - -msgid "Timeago|%s weeks remaining" -msgstr "" - -msgid "Timeago|%s years ago" -msgstr "" - -msgid "Timeago|%s years remaining" -msgstr "" - -#, fuzzy -msgid "Timeago|1 day remaining" -msgstr "天" - -msgid "Timeago|1 hour remaining" -msgstr "" - -msgid "Timeago|1 minute remaining" -msgstr "" - -msgid "Timeago|1 month remaining" -msgstr "" - -msgid "Timeago|1 week remaining" -msgstr "" - -msgid "Timeago|1 year remaining" -msgstr "" - -msgid "Timeago|Past due" -msgstr "" - -#, fuzzy -msgid "Timeago|a day ago" -msgstr "天" - -msgid "Timeago|a month ago" -msgstr "" - -msgid "Timeago|a week ago" -msgstr "" - -msgid "Timeago|a while" -msgstr "" - -msgid "Timeago|a year ago" -msgstr "" - -msgid "Timeago|about %s hours ago" -msgstr "" - -msgid "Timeago|about a minute ago" -msgstr "" - -msgid "Timeago|about an hour ago" -msgstr "" - -#, fuzzy -msgid "Timeago|in %s days" -msgstr "天" - -msgid "Timeago|in %s hours" -msgstr "" - -msgid "Timeago|in %s minutes" -msgstr "" - -msgid "Timeago|in %s months" -msgstr "" - -msgid "Timeago|in %s seconds" -msgstr "" - -msgid "Timeago|in %s weeks" -msgstr "" - -msgid "Timeago|in %s years" -msgstr "" - -#, fuzzy -msgid "Timeago|in 1 day" -msgstr "天" - -msgid "Timeago|in 1 hour" -msgstr "" - -msgid "Timeago|in 1 minute" -msgstr "" - -msgid "Timeago|in 1 month" -msgstr "" - -msgid "Timeago|in 1 week" -msgstr "" - -msgid "Timeago|in 1 year" -msgstr "" - -msgid "Timeago|less than a minute ago" -msgstr "" - msgid "Time|hr" msgid_plural "Time|hrs" msgstr[0] "小时" @@ -830,87 +277,15 @@ msgstr "总时间" msgid "Total test time for all commits/merges" msgstr "所有提交和合并的总测试时间" -msgid "Unstar" -msgstr "" - -msgid "Upload New File" -msgstr "" - -msgid "Upload file" -msgstr "" - -msgid "Use your global notification setting" -msgstr "" - -msgid "VisibilityLevel|Internal" -msgstr "" - -msgid "VisibilityLevel|Private" -msgstr "" - -msgid "VisibilityLevel|Public" -msgstr "" - msgid "Want to see the data? Please ask an administrator for access." msgstr "权限不足。如需查看相关数据,请向管理员申请权限。" msgid "We don't have enough data to show this stage." msgstr "该阶段的数据不足,无法显示。" -msgid "Withdraw Access Request" -msgstr "" - -msgid "" -"You are going to remove %{project_name_with_namespace}.\n" -"Removed project CANNOT be restored!\n" -"Are you ABSOLUTELY sure?" -msgstr "" - -msgid "You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?" -msgstr "" - -msgid "You are going to transfer %{project_name_with_namespace} to another owner. Are you ABSOLUTELY sure?" -msgstr "" - -msgid "You can only add files when you are on a branch" -msgstr "" - -msgid "You must sign in to star a project" -msgstr "" - msgid "You need permission." msgstr "您需要相关的权限。" -msgid "You will not get any notifications via email" -msgstr "" - -msgid "You will only receive notifications for the events you choose" -msgstr "" - -msgid "You will only receive notifications for threads you have participated in" -msgstr "" - -msgid "You will receive notifications for any activity" -msgstr "" - -msgid "You will receive notifications only for comments in which you were @mentioned" -msgstr "" - -msgid "You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account" -msgstr "" - -msgid "You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile" -msgstr "" - -msgid "Your name" -msgstr "" - -msgid "committed" -msgstr "" - msgid "day" msgid_plural "days" msgstr[0] "天" - -msgid "notification emails" -msgstr "" diff --git a/locale/zh_HK/gitlab.po b/locale/zh_HK/gitlab.po index 311d44afb42..81b2ff863ea 100644 --- a/locale/zh_HK/gitlab.po +++ b/locale/zh_HK/gitlab.po @@ -17,172 +17,22 @@ msgstr "" "Language: zh_HK\n" "Plural-Forms: nplurals=1; plural=0;\n" -msgid "About auto deploy" -msgstr "" - -msgid "Activity" -msgstr "" - -msgid "Add Changelog" -msgstr "" - -msgid "Add Contribution guide" -msgstr "" - -msgid "Add License" -msgstr "" - -msgid "Add an SSH key to your profile to pull or push via SSH." -msgstr "" - -msgid "Add new directory" -msgstr "" - -msgid "Archived project! Repository is read-only" -msgstr "" - msgid "Are you sure you want to delete this pipeline schedule?" msgstr "" -msgid "Branch" -msgid_plural "Branches" -msgstr[0] "" -msgstr[1] "" - -msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}" -msgstr "" - -msgid "Branches" -msgstr "" - msgid "ByAuthor|by" msgstr "作者:" -msgid "CI configuration" -msgstr "" - msgid "Cancel" msgstr "" -msgid "Changelog" -msgstr "" - -msgid "Charts" -msgstr "" - -msgid "CiStatusLabel|canceled" -msgstr "" - -msgid "CiStatusLabel|created" -msgstr "" - -msgid "CiStatusLabel|failed" -msgstr "" - -msgid "CiStatusLabel|manual action" -msgstr "" - -msgid "CiStatusLabel|passed" -msgstr "" - -msgid "CiStatusLabel|passed with warnings" -msgstr "" - -msgid "CiStatusLabel|pending" -msgstr "" - -msgid "CiStatusLabel|skipped" -msgstr "" - -msgid "CiStatusLabel|waiting for manual action" -msgstr "" - -msgid "CiStatusText|blocked" -msgstr "" - -msgid "CiStatusText|canceled" -msgstr "" - -msgid "CiStatusText|created" -msgstr "" - -msgid "CiStatusText|failed" -msgstr "" - -msgid "CiStatusText|manual" -msgstr "" - -msgid "CiStatusText|passed" -msgstr "" - -msgid "CiStatusText|pending" -msgstr "" - -msgid "CiStatusText|skipped" -msgstr "" - -msgid "CiStatus|running" -msgstr "" - msgid "Commit" msgid_plural "Commits" msgstr[0] "提交" -#, fuzzy -msgid "CommitMessage|Add %{file_name}" -msgstr "提交" - -#, fuzzy -msgid "Commits" -msgstr "提交" - -#, fuzzy -msgid "Commits|History" -msgstr "提交" - -msgid "Compare" -msgstr "" - -msgid "Contribution guide" -msgstr "" - -msgid "Contributors" -msgstr "" - -msgid "Copy URL to clipboard" -msgstr "" - -msgid "Copy commit SHA to clipboard" -msgstr "" - -msgid "Create New Directory" -msgstr "" - -msgid "Create directory" -msgstr "" - -msgid "Create empty bare repository" -msgstr "" - -#, fuzzy -msgid "Create merge request" -msgstr "相關的合併請求" - -msgid "CreateNewFork|Fork" -msgstr "" - msgid "Cron Timezone" msgstr "" -msgid "Custom notification events" -msgstr "" - -msgid "Custom notification levels are the same as participating levels. With custom notification levels you will also receive notifications for select events. To find out more, check out %{notification_link}." -msgstr "" - -msgid "Cycle Analytics" -msgstr "" - msgid "Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project." msgstr "週期分析概述了項目從想法到產品實現的各階段所需的時間。" @@ -217,30 +67,6 @@ msgstr[0] "部署" msgid "Description" msgstr "" -msgid "Directory name" -msgstr "" - -msgid "Don't show again" -msgstr "" - -msgid "Download tar" -msgstr "" - -msgid "Download tar.bz2" -msgstr "" - -msgid "Download tar.gz" -msgstr "" - -msgid "Download zip" -msgstr "" - -msgid "DownloadArtifacts|Download" -msgstr "" - -msgid "DownloadSource|Download" -msgstr "" - msgid "Edit" msgstr "" @@ -253,63 +79,27 @@ msgstr "" msgid "Failed to remove the pipeline schedule" msgstr "" -msgid "Files" -msgstr "" - msgid "Filter" msgstr "" -msgid "Find by path" -msgstr "" - -msgid "Find file" -msgstr "" - msgid "FirstPushedBy|First" msgstr "首次推送" msgid "FirstPushedBy|pushed by" msgstr "推送者:" -msgid "ForkedFromProjectPath|Forked from" -msgstr "" - -msgid "Forks" -msgstr "" - msgid "From issue creation until deploy to production" msgstr "從創建議題到部署到生產環境" msgid "From merge request merge until deploy to production" msgstr "從合併請求的合併到部署至生產環境" -msgid "Go to your fork" -msgstr "" - -msgid "GoToYourFork|Fork" -msgstr "" - -msgid "Home" -msgstr "" - -msgid "Housekeeping successfully started" -msgstr "" - -msgid "Import repository" -msgstr "" - msgid "Interval Pattern" msgstr "" msgid "Introducing Cycle Analytics" msgstr "週期分析簡介" -msgid "LFSStatus|Disabled" -msgstr "" - -msgid "LFSStatus|Enabled" -msgstr "" - msgid "Last %d day" msgid_plural "Last %d days" msgstr[0] "最後 %d 天" @@ -317,18 +107,6 @@ msgstr[0] "最後 %d 天" msgid "Last Pipeline" msgstr "" -msgid "Last Update" -msgstr "" - -msgid "Last commit" -msgstr "" - -msgid "Leave group" -msgstr "" - -msgid "Leave project" -msgstr "" - msgid "Limited to showing %d event at most" msgid_plural "Limited to showing %d events at most" msgstr[0] "最多顯示 %d 個事件" @@ -336,9 +114,6 @@ msgstr[0] "最多顯示 %d 個事件" msgid "Median" msgstr "中位數" -msgid "MissingSSHKeyWarningLink|add an SSH key" -msgstr "" - msgid "New Issue" msgid_plural "New Issues" msgstr[0] "新議題" @@ -346,31 +121,6 @@ msgstr[0] "新議題" msgid "New Pipeline Schedule" msgstr "" -msgid "New branch" -msgstr "" - -msgid "New directory" -msgstr "" - -msgid "New file" -msgstr "" - -#, fuzzy -msgid "New issue" -msgstr "新議題" - -msgid "New merge request" -msgstr "" - -msgid "New snippet" -msgstr "" - -msgid "New tag" -msgstr "" - -msgid "No repository" -msgstr "" - msgid "No schedules" msgstr "" @@ -380,60 +130,6 @@ msgstr "不可用" msgid "Not enough data" msgstr "數據不足" -msgid "Notification events" -msgstr "" - -msgid "NotificationEvent|Close issue" -msgstr "" - -msgid "NotificationEvent|Close merge request" -msgstr "" - -msgid "NotificationEvent|Failed pipeline" -msgstr "" - -msgid "NotificationEvent|Merge merge request" -msgstr "" - -msgid "NotificationEvent|New issue" -msgstr "" - -msgid "NotificationEvent|New merge request" -msgstr "" - -msgid "NotificationEvent|New note" -msgstr "" - -msgid "NotificationEvent|Reassign issue" -msgstr "" - -msgid "NotificationEvent|Reassign merge request" -msgstr "" - -msgid "NotificationEvent|Reopen issue" -msgstr "" - -msgid "NotificationEvent|Successful pipeline" -msgstr "" - -msgid "NotificationLevel|Custom" -msgstr "" - -msgid "NotificationLevel|Disabled" -msgstr "" - -msgid "NotificationLevel|Global" -msgstr "" - -msgid "NotificationLevel|On mention" -msgstr "" - -msgid "NotificationLevel|Participate" -msgstr "" - -msgid "NotificationLevel|Watch" -msgstr "" - msgid "OpenedNDaysAgo|Opened" msgstr "開始於" @@ -476,70 +172,12 @@ msgstr "" msgid "PipelineSchedules|Target" msgstr "" -msgid "Project '%{project_name}' queued for deletion." -msgstr "" - -msgid "Project '%{project_name}' was successfully created." -msgstr "" - -msgid "Project '%{project_name}' was successfully updated." -msgstr "" - -msgid "Project '%{project_name}' will be deleted." -msgstr "" - -msgid "Project access must be granted explicitly to each user." -msgstr "" - -msgid "Project export could not be deleted." -msgstr "" - -msgid "Project export has been deleted." -msgstr "" - -msgid "Project export link has expired. Please generate a new export from your project settings." -msgstr "" - -msgid "Project export started. A download link will be sent by email." -msgstr "" - -msgid "Project home" -msgstr "" - -msgid "ProjectFeature|Disabled" -msgstr "" - -msgid "ProjectFeature|Everyone with access" -msgstr "" - -msgid "ProjectFeature|Only team members" -msgstr "" - -msgid "ProjectFileTree|Name" -msgstr "" - -msgid "ProjectLastActivity|Never" -msgstr "" - msgid "ProjectLifecycle|Stage" msgstr "項目生命週期" -msgid "ProjectNetworkGraph|Graph" -msgstr "" - msgid "Read more" msgstr "了解更多" -#, fuzzy -msgid "Readme" -msgstr "了解更多" - -msgid "RefSwitcher|Branches" -msgstr "" - -msgid "RefSwitcher|Tags" -msgstr "" - msgid "Related Commits" msgstr "相關的提交" @@ -558,69 +196,22 @@ msgstr "相關的合併請求" msgid "Related Merged Requests" msgstr "相關已合併的合並請求" -msgid "Remind later" -msgstr "" - -msgid "Remove project" -msgstr "" - -msgid "Request Access" -msgstr "" - msgid "Save pipeline schedule" msgstr "" msgid "Schedule a new pipeline" msgstr "" -msgid "Search branches and tags" -msgstr "" - -msgid "Select Archive Format" -msgstr "" - msgid "Select a timezone" msgstr "" msgid "Select target branch" msgstr "" -msgid "Set a password on your account to pull or push via %{protocol}" -msgstr "" - -msgid "Set up CI" -msgstr "" - -msgid "Set up Koding" -msgstr "" - -msgid "Set up auto deploy" -msgstr "" - -msgid "SetPasswordToCloneLink|set a password" -msgstr "" - msgid "Showing %d event" msgid_plural "Showing %d events" msgstr[0] "顯示 %d 個事件" -msgid "Source code" -msgstr "" - -msgid "StarProject|Star" -msgstr "" - -msgid "Switch branch/tag" -msgstr "" - -msgid "Tag" -msgid_plural "Tags" -msgstr[0] "" -msgstr[1] "" - -msgid "Tags" -msgstr "" - msgid "Target Branch" msgstr "" @@ -630,9 +221,6 @@ msgstr "編碼階段概述了從第一次提交到創建合併請求的時間。 msgid "The collection of events added to the data gathered for that stage." msgstr "與該階段相關的事件。" -msgid "The fork relationship has been removed." -msgstr "" - msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage." msgstr "議題階段概述了從創建議題到將議題設置裏程碑或將議題添加到議題看板的時間。創建一個議題後,數據將自動添加到此處。" @@ -645,15 +233,6 @@ msgstr "計劃階段概述了從議題添加到日程後到推送首次提交的 msgid "The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle." msgstr "生產階段概述了從創建議題到將代碼部署到生產環境的時間。當完成完整的想法到部署生產,數據將自動添加到此處。" -msgid "The project can be accessed by any logged in user." -msgstr "" - -msgid "The project can be accessed without any authentication." -msgstr "" - -msgid "The repository for this project does not exist." -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 "評審階段概述了從創建合並請求到合併的時間。當創建第壹個合並請求後,數據將自動添加到此處。" @@ -669,9 +248,6 @@ msgstr "該階段每條數據所花的時間" msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6." msgstr "中位數是一個數列中最中間的值。例如在 3、5、9 之間,中位數是 5。在 3、5、7、8 之間,中位數是 (5 + 7)/ 2 = 6。" -msgid "This means you can not push code until you create an empty repository or import existing one." -msgstr "" - msgid "Time before an issue gets scheduled" msgstr "議題被列入日程表的時間" @@ -684,135 +260,6 @@ msgstr "從創建合併請求到被合並或關閉的時間" msgid "Time until first merge request" msgstr "創建第壹個合併請求之前的時間" -#, fuzzy -msgid "Timeago|%s days ago" -msgstr "天" - -#, fuzzy -msgid "Timeago|%s days remaining" -msgstr "天" - -msgid "Timeago|%s hours remaining" -msgstr "" - -msgid "Timeago|%s minutes ago" -msgstr "" - -msgid "Timeago|%s minutes remaining" -msgstr "" - -msgid "Timeago|%s months ago" -msgstr "" - -msgid "Timeago|%s months remaining" -msgstr "" - -msgid "Timeago|%s seconds remaining" -msgstr "" - -msgid "Timeago|%s weeks ago" -msgstr "" - -msgid "Timeago|%s weeks remaining" -msgstr "" - -msgid "Timeago|%s years ago" -msgstr "" - -msgid "Timeago|%s years remaining" -msgstr "" - -#, fuzzy -msgid "Timeago|1 day remaining" -msgstr "天" - -msgid "Timeago|1 hour remaining" -msgstr "" - -msgid "Timeago|1 minute remaining" -msgstr "" - -msgid "Timeago|1 month remaining" -msgstr "" - -msgid "Timeago|1 week remaining" -msgstr "" - -msgid "Timeago|1 year remaining" -msgstr "" - -msgid "Timeago|Past due" -msgstr "" - -#, fuzzy -msgid "Timeago|a day ago" -msgstr "天" - -msgid "Timeago|a month ago" -msgstr "" - -msgid "Timeago|a week ago" -msgstr "" - -msgid "Timeago|a while" -msgstr "" - -msgid "Timeago|a year ago" -msgstr "" - -msgid "Timeago|about %s hours ago" -msgstr "" - -msgid "Timeago|about a minute ago" -msgstr "" - -msgid "Timeago|about an hour ago" -msgstr "" - -#, fuzzy -msgid "Timeago|in %s days" -msgstr "天" - -msgid "Timeago|in %s hours" -msgstr "" - -msgid "Timeago|in %s minutes" -msgstr "" - -msgid "Timeago|in %s months" -msgstr "" - -msgid "Timeago|in %s seconds" -msgstr "" - -msgid "Timeago|in %s weeks" -msgstr "" - -msgid "Timeago|in %s years" -msgstr "" - -#, fuzzy -msgid "Timeago|in 1 day" -msgstr "天" - -msgid "Timeago|in 1 hour" -msgstr "" - -msgid "Timeago|in 1 minute" -msgstr "" - -msgid "Timeago|in 1 month" -msgstr "" - -msgid "Timeago|in 1 week" -msgstr "" - -msgid "Timeago|in 1 year" -msgstr "" - -msgid "Timeago|less than a minute ago" -msgstr "" - msgid "Time|hr" msgid_plural "Time|hrs" msgstr[0] "小時" @@ -830,87 +277,15 @@ msgstr "總時間" msgid "Total test time for all commits/merges" msgstr "所有提交和合併的總測試時間" -msgid "Unstar" -msgstr "" - -msgid "Upload New File" -msgstr "" - -msgid "Upload file" -msgstr "" - -msgid "Use your global notification setting" -msgstr "" - -msgid "VisibilityLevel|Internal" -msgstr "" - -msgid "VisibilityLevel|Private" -msgstr "" - -msgid "VisibilityLevel|Public" -msgstr "" - msgid "Want to see the data? Please ask an administrator for access." msgstr "權限不足。如需查看相關數據,請向管理員申請權限。" msgid "We don't have enough data to show this stage." msgstr "該階段的數據不足,無法顯示。" -msgid "Withdraw Access Request" -msgstr "" - -msgid "" -"You are going to remove %{project_name_with_namespace}.\n" -"Removed project CANNOT be restored!\n" -"Are you ABSOLUTELY sure?" -msgstr "" - -msgid "You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?" -msgstr "" - -msgid "You are going to transfer %{project_name_with_namespace} to another owner. Are you ABSOLUTELY sure?" -msgstr "" - -msgid "You can only add files when you are on a branch" -msgstr "" - -msgid "You must sign in to star a project" -msgstr "" - msgid "You need permission." msgstr "您需要相關的權限。" -msgid "You will not get any notifications via email" -msgstr "" - -msgid "You will only receive notifications for the events you choose" -msgstr "" - -msgid "You will only receive notifications for threads you have participated in" -msgstr "" - -msgid "You will receive notifications for any activity" -msgstr "" - -msgid "You will receive notifications only for comments in which you were @mentioned" -msgstr "" - -msgid "You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account" -msgstr "" - -msgid "You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile" -msgstr "" - -msgid "Your name" -msgstr "" - -msgid "committed" -msgstr "" - msgid "day" msgid_plural "days" msgstr[0] "天" - -msgid "notification emails" -msgstr "" diff --git a/locale/zh_TW/gitlab.po b/locale/zh_TW/gitlab.po index 47d8b889b61..e40723a9d8d 100644 --- a/locale/zh_TW/gitlab.po +++ b/locale/zh_TW/gitlab.po @@ -17,172 +17,22 @@ msgstr "" "Language: zh_TW\n" "Plural-Forms: nplurals=1; plural=0;\n" -msgid "About auto deploy" -msgstr "" - -msgid "Activity" -msgstr "" - -msgid "Add Changelog" -msgstr "" - -msgid "Add Contribution guide" -msgstr "" - -msgid "Add License" -msgstr "" - -msgid "Add an SSH key to your profile to pull or push via SSH." -msgstr "" - -msgid "Add new directory" -msgstr "" - -msgid "Archived project! Repository is read-only" -msgstr "" - msgid "Are you sure you want to delete this pipeline schedule?" msgstr "" -msgid "Branch" -msgid_plural "Branches" -msgstr[0] "" -msgstr[1] "" - -msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}" -msgstr "" - -msgid "Branches" -msgstr "" - msgid "ByAuthor|by" msgstr "作者:" -msgid "CI configuration" -msgstr "" - msgid "Cancel" msgstr "" -msgid "Changelog" -msgstr "" - -msgid "Charts" -msgstr "" - -msgid "CiStatusLabel|canceled" -msgstr "" - -msgid "CiStatusLabel|created" -msgstr "" - -msgid "CiStatusLabel|failed" -msgstr "" - -msgid "CiStatusLabel|manual action" -msgstr "" - -msgid "CiStatusLabel|passed" -msgstr "" - -msgid "CiStatusLabel|passed with warnings" -msgstr "" - -msgid "CiStatusLabel|pending" -msgstr "" - -msgid "CiStatusLabel|skipped" -msgstr "" - -msgid "CiStatusLabel|waiting for manual action" -msgstr "" - -msgid "CiStatusText|blocked" -msgstr "" - -msgid "CiStatusText|canceled" -msgstr "" - -msgid "CiStatusText|created" -msgstr "" - -msgid "CiStatusText|failed" -msgstr "" - -msgid "CiStatusText|manual" -msgstr "" - -msgid "CiStatusText|passed" -msgstr "" - -msgid "CiStatusText|pending" -msgstr "" - -msgid "CiStatusText|skipped" -msgstr "" - -msgid "CiStatus|running" -msgstr "" - msgid "Commit" msgid_plural "Commits" msgstr[0] "送交" -#, fuzzy -msgid "CommitMessage|Add %{file_name}" -msgstr "送交" - -#, fuzzy -msgid "Commits" -msgstr "送交" - -#, fuzzy -msgid "Commits|History" -msgstr "送交" - -msgid "Compare" -msgstr "" - -msgid "Contribution guide" -msgstr "" - -msgid "Contributors" -msgstr "" - -msgid "Copy URL to clipboard" -msgstr "" - -msgid "Copy commit SHA to clipboard" -msgstr "" - -msgid "Create New Directory" -msgstr "" - -msgid "Create directory" -msgstr "" - -msgid "Create empty bare repository" -msgstr "" - -#, fuzzy -msgid "Create merge request" -msgstr "相關的合併請求" - -msgid "CreateNewFork|Fork" -msgstr "" - msgid "Cron Timezone" msgstr "" -msgid "Custom notification events" -msgstr "" - -msgid "Custom notification levels are the same as participating levels. With custom notification levels you will also receive notifications for select events. To find out more, check out %{notification_link}." -msgstr "" - -msgid "Cycle Analytics" -msgstr "" - msgid "Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project." msgstr "週期分析概述了你的專案從想法到產品實現,各階段所需的時間。" @@ -217,30 +67,6 @@ msgstr[0] "部署" msgid "Description" msgstr "" -msgid "Directory name" -msgstr "" - -msgid "Don't show again" -msgstr "" - -msgid "Download tar" -msgstr "" - -msgid "Download tar.bz2" -msgstr "" - -msgid "Download tar.gz" -msgstr "" - -msgid "Download zip" -msgstr "" - -msgid "DownloadArtifacts|Download" -msgstr "" - -msgid "DownloadSource|Download" -msgstr "" - msgid "Edit" msgstr "" @@ -253,63 +79,27 @@ msgstr "" msgid "Failed to remove the pipeline schedule" msgstr "" -msgid "Files" -msgstr "" - msgid "Filter" msgstr "" -msgid "Find by path" -msgstr "" - -msgid "Find file" -msgstr "" - msgid "FirstPushedBy|First" msgstr "首次推送" msgid "FirstPushedBy|pushed by" msgstr "推送者:" -msgid "ForkedFromProjectPath|Forked from" -msgstr "" - -msgid "Forks" -msgstr "" - msgid "From issue creation until deploy to production" msgstr "從議題建立至線上部署" msgid "From merge request merge until deploy to production" msgstr "從請求被合併後至線上部署" -msgid "Go to your fork" -msgstr "" - -msgid "GoToYourFork|Fork" -msgstr "" - -msgid "Home" -msgstr "" - -msgid "Housekeeping successfully started" -msgstr "" - -msgid "Import repository" -msgstr "" - msgid "Interval Pattern" msgstr "" msgid "Introducing Cycle Analytics" msgstr "週期分析簡介" -msgid "LFSStatus|Disabled" -msgstr "" - -msgid "LFSStatus|Enabled" -msgstr "" - msgid "Last %d day" msgid_plural "Last %d days" msgstr[0] "最後 %d 天" @@ -317,18 +107,6 @@ msgstr[0] "最後 %d 天" msgid "Last Pipeline" msgstr "" -msgid "Last Update" -msgstr "" - -msgid "Last commit" -msgstr "" - -msgid "Leave group" -msgstr "" - -msgid "Leave project" -msgstr "" - msgid "Limited to showing %d event at most" msgid_plural "Limited to showing %d events at most" msgstr[0] "最多顯示 %d 個事件" @@ -336,9 +114,6 @@ msgstr[0] "最多顯示 %d 個事件" msgid "Median" msgstr "中位數" -msgid "MissingSSHKeyWarningLink|add an SSH key" -msgstr "" - msgid "New Issue" msgid_plural "New Issues" msgstr[0] "新議題" @@ -346,31 +121,6 @@ msgstr[0] "新議題" msgid "New Pipeline Schedule" msgstr "" -msgid "New branch" -msgstr "" - -msgid "New directory" -msgstr "" - -msgid "New file" -msgstr "" - -#, fuzzy -msgid "New issue" -msgstr "新議題" - -msgid "New merge request" -msgstr "" - -msgid "New snippet" -msgstr "" - -msgid "New tag" -msgstr "" - -msgid "No repository" -msgstr "" - msgid "No schedules" msgstr "" @@ -380,60 +130,6 @@ msgstr "無法使用" msgid "Not enough data" msgstr "資料不足" -msgid "Notification events" -msgstr "" - -msgid "NotificationEvent|Close issue" -msgstr "" - -msgid "NotificationEvent|Close merge request" -msgstr "" - -msgid "NotificationEvent|Failed pipeline" -msgstr "" - -msgid "NotificationEvent|Merge merge request" -msgstr "" - -msgid "NotificationEvent|New issue" -msgstr "" - -msgid "NotificationEvent|New merge request" -msgstr "" - -msgid "NotificationEvent|New note" -msgstr "" - -msgid "NotificationEvent|Reassign issue" -msgstr "" - -msgid "NotificationEvent|Reassign merge request" -msgstr "" - -msgid "NotificationEvent|Reopen issue" -msgstr "" - -msgid "NotificationEvent|Successful pipeline" -msgstr "" - -msgid "NotificationLevel|Custom" -msgstr "" - -msgid "NotificationLevel|Disabled" -msgstr "" - -msgid "NotificationLevel|Global" -msgstr "" - -msgid "NotificationLevel|On mention" -msgstr "" - -msgid "NotificationLevel|Participate" -msgstr "" - -msgid "NotificationLevel|Watch" -msgstr "" - msgid "OpenedNDaysAgo|Opened" msgstr "開始於" @@ -476,70 +172,12 @@ msgstr "" msgid "PipelineSchedules|Target" msgstr "" -msgid "Project '%{project_name}' queued for deletion." -msgstr "" - -msgid "Project '%{project_name}' was successfully created." -msgstr "" - -msgid "Project '%{project_name}' was successfully updated." -msgstr "" - -msgid "Project '%{project_name}' will be deleted." -msgstr "" - -msgid "Project access must be granted explicitly to each user." -msgstr "" - -msgid "Project export could not be deleted." -msgstr "" - -msgid "Project export has been deleted." -msgstr "" - -msgid "Project export link has expired. Please generate a new export from your project settings." -msgstr "" - -msgid "Project export started. A download link will be sent by email." -msgstr "" - -msgid "Project home" -msgstr "" - -msgid "ProjectFeature|Disabled" -msgstr "" - -msgid "ProjectFeature|Everyone with access" -msgstr "" - -msgid "ProjectFeature|Only team members" -msgstr "" - -msgid "ProjectFileTree|Name" -msgstr "" - -msgid "ProjectLastActivity|Never" -msgstr "" - msgid "ProjectLifecycle|Stage" msgstr "專案生命週期" -msgid "ProjectNetworkGraph|Graph" -msgstr "" - msgid "Read more" msgstr "了解更多" -#, fuzzy -msgid "Readme" -msgstr "了解更多" - -msgid "RefSwitcher|Branches" -msgstr "" - -msgid "RefSwitcher|Tags" -msgstr "" - msgid "Related Commits" msgstr "相關的送交" @@ -558,69 +196,22 @@ msgstr "相關的合併請求" msgid "Related Merged Requests" msgstr "相關已合併的請求" -msgid "Remind later" -msgstr "" - -msgid "Remove project" -msgstr "" - -msgid "Request Access" -msgstr "" - msgid "Save pipeline schedule" msgstr "" msgid "Schedule a new pipeline" msgstr "" -msgid "Search branches and tags" -msgstr "" - -msgid "Select Archive Format" -msgstr "" - msgid "Select a timezone" msgstr "" msgid "Select target branch" msgstr "" -msgid "Set a password on your account to pull or push via %{protocol}" -msgstr "" - -msgid "Set up CI" -msgstr "" - -msgid "Set up Koding" -msgstr "" - -msgid "Set up auto deploy" -msgstr "" - -msgid "SetPasswordToCloneLink|set a password" -msgstr "" - msgid "Showing %d event" msgid_plural "Showing %d events" msgstr[0] "顯示 %d 個事件" -msgid "Source code" -msgstr "" - -msgid "StarProject|Star" -msgstr "" - -msgid "Switch branch/tag" -msgstr "" - -msgid "Tag" -msgid_plural "Tags" -msgstr[0] "" -msgstr[1] "" - -msgid "Tags" -msgstr "" - msgid "Target Branch" msgstr "" @@ -630,9 +221,6 @@ msgstr "程式開發階段顯示從第一次送交到建立合併請求的時間 msgid "The collection of events added to the data gathered for that stage." msgstr "與該階段相關的事件。" -msgid "The fork relationship has been removed." -msgstr "" - msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage." msgstr "議題階段顯示從議題建立到設置里程碑、或將該議題加至議題看板的時間。建立第一個議題後,資料將自動填入。" @@ -640,20 +228,11 @@ msgid "The phase of the development lifecycle." msgstr "專案開發生命週期的各個階段。" msgid "The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit." -msgstr "計劃階段顯示從議題添加到日程後至推送第一個送交的時間。當第一次推送送交後,資料將自動填入。" +msgstr "計劃階段所顯示的是議題被排程後至第一個送交被推送的時間。一旦完成(或執行)首次的推送,資料將自動填入。" msgid "The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle." msgstr "上線階段顯示從建立一個議題到部署程式至線上的總時間。當完成從想法到產品實現的循環後,資料將自動填入。" -msgid "The project can be accessed by any logged in user." -msgstr "" - -msgid "The project can be accessed without any authentication." -msgstr "" - -msgid "The repository for this project does not exist." -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 "複閱階段顯示從合併請求建立後至被合併的時間。當建立第一個合併請求後,資料將自動填入。" @@ -669,11 +248,8 @@ msgstr "每筆該階段相關資料所花的時間。" msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6." msgstr "中位數是一個數列中最中間的值。例如在 3、5、9 之間,中位數是 5。在 3、5、7、8 之間,中位數是 (5 + 7)/ 2 = 6。" -msgid "This means you can not push code until you create an empty repository or import existing one." -msgstr "" - msgid "Time before an issue gets scheduled" -msgstr "議題被列入日程表的時間" +msgstr "議題等待排程的時間" msgid "Time before an issue starts implementation" msgstr "議題等待開始實作的時間" @@ -684,135 +260,6 @@ msgstr "合併請求被合併或是關閉的時間" msgid "Time until first merge request" msgstr "第一個合併請求被建立前的時間" -#, fuzzy -msgid "Timeago|%s days ago" -msgstr "天" - -#, fuzzy -msgid "Timeago|%s days remaining" -msgstr "天" - -msgid "Timeago|%s hours remaining" -msgstr "" - -msgid "Timeago|%s minutes ago" -msgstr "" - -msgid "Timeago|%s minutes remaining" -msgstr "" - -msgid "Timeago|%s months ago" -msgstr "" - -msgid "Timeago|%s months remaining" -msgstr "" - -msgid "Timeago|%s seconds remaining" -msgstr "" - -msgid "Timeago|%s weeks ago" -msgstr "" - -msgid "Timeago|%s weeks remaining" -msgstr "" - -msgid "Timeago|%s years ago" -msgstr "" - -msgid "Timeago|%s years remaining" -msgstr "" - -#, fuzzy -msgid "Timeago|1 day remaining" -msgstr "天" - -msgid "Timeago|1 hour remaining" -msgstr "" - -msgid "Timeago|1 minute remaining" -msgstr "" - -msgid "Timeago|1 month remaining" -msgstr "" - -msgid "Timeago|1 week remaining" -msgstr "" - -msgid "Timeago|1 year remaining" -msgstr "" - -msgid "Timeago|Past due" -msgstr "" - -#, fuzzy -msgid "Timeago|a day ago" -msgstr "天" - -msgid "Timeago|a month ago" -msgstr "" - -msgid "Timeago|a week ago" -msgstr "" - -msgid "Timeago|a while" -msgstr "" - -msgid "Timeago|a year ago" -msgstr "" - -msgid "Timeago|about %s hours ago" -msgstr "" - -msgid "Timeago|about a minute ago" -msgstr "" - -msgid "Timeago|about an hour ago" -msgstr "" - -#, fuzzy -msgid "Timeago|in %s days" -msgstr "天" - -msgid "Timeago|in %s hours" -msgstr "" - -msgid "Timeago|in %s minutes" -msgstr "" - -msgid "Timeago|in %s months" -msgstr "" - -msgid "Timeago|in %s seconds" -msgstr "" - -msgid "Timeago|in %s weeks" -msgstr "" - -msgid "Timeago|in %s years" -msgstr "" - -#, fuzzy -msgid "Timeago|in 1 day" -msgstr "天" - -msgid "Timeago|in 1 hour" -msgstr "" - -msgid "Timeago|in 1 minute" -msgstr "" - -msgid "Timeago|in 1 month" -msgstr "" - -msgid "Timeago|in 1 week" -msgstr "" - -msgid "Timeago|in 1 year" -msgstr "" - -msgid "Timeago|less than a minute ago" -msgstr "" - msgid "Time|hr" msgid_plural "Time|hrs" msgstr[0] "小時" @@ -830,87 +277,15 @@ msgstr "總時間" msgid "Total test time for all commits/merges" msgstr "所有送交和合併的總測試時間" -msgid "Unstar" -msgstr "" - -msgid "Upload New File" -msgstr "" - -msgid "Upload file" -msgstr "" - -msgid "Use your global notification setting" -msgstr "" - -msgid "VisibilityLevel|Internal" -msgstr "" - -msgid "VisibilityLevel|Private" -msgstr "" - -msgid "VisibilityLevel|Public" -msgstr "" - msgid "Want to see the data? Please ask an administrator for access." msgstr "權限不足。如需查看相關資料,請向管理員申請權限。" msgid "We don't have enough data to show this stage." msgstr "因該階段的資料不足而無法顯示相關資訊" -msgid "Withdraw Access Request" -msgstr "" - -msgid "" -"You are going to remove %{project_name_with_namespace}.\n" -"Removed project CANNOT be restored!\n" -"Are you ABSOLUTELY sure?" -msgstr "" - -msgid "You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?" -msgstr "" - -msgid "You are going to transfer %{project_name_with_namespace} to another owner. Are you ABSOLUTELY sure?" -msgstr "" - -msgid "You can only add files when you are on a branch" -msgstr "" - -msgid "You must sign in to star a project" -msgstr "" - msgid "You need permission." msgstr "您需要相關的權限。" -msgid "You will not get any notifications via email" -msgstr "" - -msgid "You will only receive notifications for the events you choose" -msgstr "" - -msgid "You will only receive notifications for threads you have participated in" -msgstr "" - -msgid "You will receive notifications for any activity" -msgstr "" - -msgid "You will receive notifications only for comments in which you were @mentioned" -msgstr "" - -msgid "You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account" -msgstr "" - -msgid "You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile" -msgstr "" - -msgid "Your name" -msgstr "" - -msgid "committed" -msgstr "" - msgid "day" msgid_plural "days" msgstr[0] "天" - -msgid "notification emails" -msgstr "" diff --git a/scripts/trigger-build b/scripts/trigger-build index e4603533872..dcda70d7ed8 100755 --- a/scripts/trigger-build +++ b/scripts/trigger-build @@ -9,7 +9,7 @@ params = { "token" => ENV["BUILD_TRIGGER_TOKEN"], "variables[GITLAB_VERSION]" => ENV["CI_COMMIT_SHA"], "variables[ALTERNATIVE_SOURCES]" => true, - "variables[ee]" => ENV["EE_PACKAGE"] + "variables[ee]" => ENV["EE_PACKAGE"] || "false" } Dir.glob("*_VERSION").each do |version_file| @@ -19,4 +19,9 @@ end res = Net::HTTP.post_form(uri, params) pipeline_id = JSON.parse(res.body)['id'] -puts "Triggered pipeline can be found at https://gitlab.com/gitlab-org/omnibus-gitlab/pipelines/#{pipeline_id}" +unless pipeline_id.nil? + puts "Triggered pipeline can be found at https://gitlab.com/gitlab-org/omnibus-gitlab/pipelines/#{pipeline_id}" +else + puts "Trigger failed. The response from trigger is: " + puts res.body +end diff --git a/spec/controllers/dashboard/milestones_controller_spec.rb b/spec/controllers/dashboard/milestones_controller_spec.rb new file mode 100644 index 00000000000..424f39fd3b8 --- /dev/null +++ b/spec/controllers/dashboard/milestones_controller_spec.rb @@ -0,0 +1,38 @@ +require 'spec_helper' + +describe Dashboard::MilestonesController do + let(:project) { create(:empty_project) } + let(:user) { create(:user) } + let(:project_milestone) { create(:milestone, project: project) } + let(:milestone) do + DashboardMilestone.build( + [project], + project_milestone.title + ) + end + let(:issue) { create(:issue, project: project, milestone: project_milestone) } + let!(:label) { create(:label, project: project, title: 'Issue Label', issues: [issue]) } + let!(:merge_request) { create(:merge_request, source_project: project, target_project: project, milestone: project_milestone) } + let(:milestone_path) { dashboard_milestone_path(milestone.safe_title, title: milestone.title) } + + before do + sign_in(user) + project.team << [user, :master] + end + + it_behaves_like 'milestone tabs' + + describe "#show" do + render_views + + def view_milestone + get :show, id: milestone.safe_title, title: milestone.title + end + + it 'shows milestone page' do + view_milestone + + expect(response).to have_http_status(200) + end + end +end diff --git a/spec/controllers/projects/branches_controller_spec.rb b/spec/controllers/projects/branches_controller_spec.rb index f285e5333d6..f9e21f9d8f6 100644 --- a/spec/controllers/projects/branches_controller_spec.rb +++ b/spec/controllers/projects/branches_controller_spec.rb @@ -367,19 +367,5 @@ describe Projects::BranchesController do expect(parsed_response.first).to eq 'master' end end - - context 'show_all = true' do - it 'returns all the branches name' do - get :index, - namespace_id: project.namespace, - project_id: project, - format: :json, - show_all: true - - parsed_response = JSON.parse(response.body) - - expect(parsed_response.length).to eq(project.repository.branches.count) - end - end end end diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb index a38ae2eb990..b65e9e0dfc0 100644 --- a/spec/controllers/projects/issues_controller_spec.rb +++ b/spec/controllers/projects/issues_controller_spec.rb @@ -260,6 +260,7 @@ describe Projects::IssuesController do before { allow_any_instance_of(described_class).to receive(:verify_recaptcha).and_return(false) } it 'rejects an issue recognized as a spam' do + expect(Gitlab::Recaptcha).to receive(:load_configurations!).and_return(true) expect { update_spam_issue }.not_to change{ issue.reload.title } end diff --git a/spec/features/dashboard/milestone_tabs_spec.rb b/spec/features/dashboard/milestone_tabs_spec.rb new file mode 100644 index 00000000000..0c7b992c500 --- /dev/null +++ b/spec/features/dashboard/milestone_tabs_spec.rb @@ -0,0 +1,40 @@ +require 'spec_helper' + +describe 'Dashboard milestone tabs', :js, :feature do + let(:user) { create(:user) } + let(:project) { create(:empty_project) } + let!(:label) { create(:label, project: project) } + let(:project_milestone) { create(:milestone, project: project) } + let(:milestone) do + DashboardMilestone.build( + [project], + project_milestone.title + ) + end + let!(:merge_request) { create(:labeled_merge_request, source_project: project, target_project: project, milestone: project_milestone, labels: [label]) } + + before do + project.add_master(user) + login_as(user) + + visit dashboard_milestone_path(milestone.safe_title, title: milestone.title) + end + + it 'loads merge requests async' do + click_link 'Merge Requests' + + expect(page).to have_selector('.merge_requests-sortable-list') + end + + it 'loads participants async' do + click_link 'Participants' + + expect(page).to have_selector('#tab-participants .bordered-list') + end + + it 'loads labels async' do + click_link 'Labels' + + expect(page).to have_selector('#tab-labels .bordered-list') + end +end diff --git a/spec/features/projects/blobs/blob_show_spec.rb b/spec/features/projects/blobs/blob_show_spec.rb index 82cfbfda157..45fdb36e506 100644 --- a/spec/features/projects/blobs/blob_show_spec.rb +++ b/spec/features/projects/blobs/blob_show_spec.rb @@ -3,8 +3,8 @@ require 'spec_helper' feature 'File blob', :js, feature: true do let(:project) { create(:project, :public) } - def visit_blob(path, fragment = nil) - visit namespace_project_blob_path(project.namespace, project, File.join('master', path), anchor: fragment) + def visit_blob(path, anchor: nil, ref: 'master') + visit namespace_project_blob_path(project.namespace, project, File.join(ref, path), anchor: anchor) wait_for_requests end @@ -101,7 +101,7 @@ feature 'File blob', :js, feature: true do context 'visiting with a line number anchor' do before do - visit_blob('files/markdown/ruby-style-guide.md', 'L1') + visit_blob('files/markdown/ruby-style-guide.md', anchor: 'L1') end it 'displays the blob using the simple viewer' do @@ -352,6 +352,37 @@ feature 'File blob', :js, feature: true do end end + context 'binary file that appears to be text in the first 1024 bytes' do + before do + visit_blob('encoding/binary-1.bin', ref: 'binary-encoding') + end + + it 'displays the blob' do + aggregate_failures do + # shows a download link + expect(page).to have_link('Download (23.8 KB)') + + # does not show a viewer switcher + expect(page).not_to have_selector('.js-blob-viewer-switcher') + + # The specs below verify an arguably incorrect result, but since we only + # learn that the file is not actually text once the text viewer content + # is loaded asynchronously, there is no straightforward way to get these + # synchronously loaded elements to display correctly. + # + # Clicking the copy button will result in nothing being copied. + # Clicking the raw button will result in the binary file being downloaded, + # as expected. + + # shows an enabled copy button, incorrectly + expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)') + + # shows a raw button, incorrectly + expect(page).to have_link('Open raw') + end + end + end + context '.gitlab-ci.yml' do before do project.add_master(project.creator) diff --git a/spec/features/projects/blobs/edit_spec.rb b/spec/features/projects/blobs/edit_spec.rb index 1a38997450d..d04c3248ead 100644 --- a/spec/features/projects/blobs/edit_spec.rb +++ b/spec/features/projects/blobs/edit_spec.rb @@ -102,7 +102,7 @@ feature 'Editing file blob', feature: true, js: true do it 'shows blob editor with same branch' do expect(page).to have_current_path(namespace_project_edit_blob_path(project.namespace, project, tree_join(branch, file_path))) - expect(find('.js-target-branch .dropdown-toggle-text').text).to eq(branch) + expect(find('.js-branch-name').value).to eq(branch) end end @@ -112,7 +112,7 @@ feature 'Editing file blob', feature: true, js: true do end it 'shows blob editor with patch branch' do - expect(find('.js-target-branch .dropdown-toggle-text').text).to eq('patch-1') + expect(find('.js-branch-name').value).to eq('patch-1') end end end @@ -128,7 +128,7 @@ feature 'Editing file blob', feature: true, js: true do it 'shows blob editor with same branch' do expect(page).to have_current_path(namespace_project_edit_blob_path(project.namespace, project, tree_join(branch, file_path))) - expect(find('.js-target-branch .dropdown-toggle-text').text).to eq(branch) + expect(find('.js-branch-name').value).to eq(branch) end end end diff --git a/spec/features/projects/blobs/user_create_spec.rb b/spec/features/projects/blobs/user_create_spec.rb deleted file mode 100644 index 4b6c55f5f44..00000000000 --- a/spec/features/projects/blobs/user_create_spec.rb +++ /dev/null @@ -1,94 +0,0 @@ -require 'spec_helper' - -feature 'New blob creation', feature: true, js: true do - include TargetBranchHelpers - - given(:user) { create(:user) } - given(:role) { :developer } - given(:project) { create(:project) } - given(:content) { 'class NextFeature\nend\n' } - - background do - login_as(user) - project.team << [user, role] - visit namespace_project_new_blob_path(project.namespace, project, 'master') - end - - def edit_file - wait_for_requests - fill_in 'file_name', with: 'feature.rb' - execute_script("ace.edit('editor').setValue('#{content}')") - end - - def commit_file - click_button 'Commit changes' - end - - context 'with default target branch' do - background do - edit_file - commit_file - end - - scenario 'creates the blob in the default branch' do - expect(page).to have_content 'master' - expect(page).to have_content 'successfully created' - expect(page).to have_content 'NextFeature' - end - end - - context 'with different target branch' do - background do - edit_file - select_branch('feature') - commit_file - end - - scenario 'creates the blob in the different branch' do - expect(page).to have_content 'feature' - expect(page).to have_content 'successfully created' - end - end - - context 'with a new target branch' do - given(:new_branch_name) { 'new-feature' } - - background do - edit_file - create_new_branch(new_branch_name) - commit_file - end - - scenario 'creates the blob in the new branch' do - expect(page).to have_content new_branch_name - expect(page).to have_content 'successfully created' - end - scenario 'returns you to the mr' do - expect(page).to have_content 'New Merge Request' - expect(page).to have_content "From #{new_branch_name} into master" - expect(page).to have_content 'Add new file' - end - end - - context 'the file already exist in the source branch' do - background do - Files::CreateService.new( - project, - user, - start_branch: 'master', - branch_name: 'master', - commit_message: 'Create file', - file_path: 'feature.rb', - file_content: content - ).execute - edit_file - commit_file - end - - scenario 'shows error message' do - expect(page).to have_content('A file with this name already exists') - expect(page).to have_content('New file') - expect(page).to have_content('NextFeature') - end - end -end diff --git a/spec/features/projects/jobs_spec.rb b/spec/features/projects/jobs_spec.rb index 0eda46649db..727ae7081b0 100644 --- a/spec/features/projects/jobs_spec.rb +++ b/spec/features/projects/jobs_spec.rb @@ -5,6 +5,7 @@ feature 'Jobs', :feature do let(:user) { create(:user) } let(:user_access_level) { :developer } let(:project) { create(:project) } + let(:namespace) { project.namespace } let(:pipeline) { create(:ci_pipeline, project: project) } let(:build) { create(:ci_build, :trace, pipeline: pipeline) } @@ -113,10 +114,16 @@ feature 'Jobs', :feature do describe "GET /:project/jobs/:id" do context "Job from project" do + let(:build) { create(:ci_build, :success, pipeline: pipeline) } + before do visit namespace_project_job_path(project.namespace, project, build) end + it 'shows status name', :js do + expect(page).to have_css('.ci-status.ci-success', text: 'passed') + end + it 'shows commit`s data' do expect(page.status_code).to eq(200) expect(page).to have_content pipeline.sha[0..7] @@ -129,6 +136,48 @@ feature 'Jobs', :feature do end end + context 'when job is not running', :js do + let(:build) { create(:ci_build, :success, pipeline: pipeline) } + + before do + visit namespace_project_job_path(project.namespace, project, build) + end + + it 'shows retry button' do + expect(page).to have_link('Retry') + end + + context 'if build passed' do + it 'does not show New issue button' do + expect(page).not_to have_link('New issue') + end + end + + context 'if build failed' do + let(:build) { create(:ci_build, :failed, pipeline: pipeline) } + + before do + visit namespace_project_job_path(namespace, project, build) + end + + it 'shows New issue button' do + expect(page).to have_link('New issue') + end + + it 'links to issues/new with the title and description filled in' do + button_title = "Build Failed ##{build.id}" + build_path = namespace_project_job_path(namespace, project, build) + options = { issue: { title: button_title, description: build_path } } + + href = new_namespace_project_issue_path(namespace, project, options) + + page.within('.header-action-buttons') do + expect(find('.js-new-issue')['href']).to include(href) + end + end + end + end + context "Job from other project" do before do visit namespace_project_job_path(project.namespace, project, build2) @@ -305,63 +354,38 @@ feature 'Jobs', :feature do end end - describe "POST /:project/jobs/:id/cancel" do + describe "POST /:project/jobs/:id/cancel", :js do context "Job from project" do before do build.run! visit namespace_project_job_path(project.namespace, project, build) - click_link "Cancel" + find('.js-cancel-job').click() end it 'loads the page and shows all needed controls' do expect(page.status_code).to eq(200) - expect(page).to have_content 'canceled' expect(page).to have_content 'Retry' end end - - context "Job from other project" do - before do - build.run! - visit namespace_project_job_path(project.namespace, project, build) - page.driver.post(cancel_namespace_project_job_path(project.namespace, project, build2)) - end - - it { expect(page.status_code).to eq(404) } - end end describe "POST /:project/jobs/:id/retry" do - context "Job from project" do + context "Job from project", :js do before do build.run! visit namespace_project_job_path(project.namespace, project, build) - click_link 'Cancel' - page.within('.build-header') do - click_link 'Retry job' - end + find('.js-cancel-job').click() + find('.js-retry-button').trigger('click') end - it 'shows the right status and buttons' do + it 'shows the right status and buttons', :js do expect(page).to have_http_status(200) - expect(page).to have_content 'pending' page.within('aside.right-sidebar') do expect(page).to have_content 'Cancel' end end end - context "Job from other project" do - before do - build.run! - visit namespace_project_job_path(project.namespace, project, build) - click_link 'Cancel' - page.driver.post(retry_namespace_project_job_path(project.namespace, project, build2)) - end - - it { expect(page).to have_http_status(404) } - end - context "Job that current user is not allowed to retry" do before do build.run! @@ -435,20 +459,17 @@ feature 'Jobs', :feature do Capybara.current_session.driver.headers = { 'X-Sendfile-Type' => 'X-Sendfile' } build.run! - - allow_any_instance_of(Gitlab::Ci::Trace).to receive(:paths) - .and_return(paths) - - visit namespace_project_job_path(project.namespace, project, build) end context 'when build has trace in file', :js do - let(:paths) do - [existing_file] - end - before do - find('.js-raw-link-controller').click() + allow_any_instance_of(Gitlab::Ci::Trace) + .to receive(:paths) + .and_return([existing_file]) + + visit namespace_project_job_path(namespace, project, build) + + find('.js-raw-link-controller').click end it 'sends the right headers' do @@ -458,11 +479,17 @@ feature 'Jobs', :feature do end end - context 'when job has trace in DB' do - let(:paths) { [] } + context 'when job has trace in the database', :js do + before do + allow_any_instance_of(Gitlab::Ci::Trace) + .to receive(:paths) + .and_return([]) + + visit namespace_project_job_path(namespace, project, build) + end it 'sends the right headers' do - expect(page.status_code).not_to have_selector('.js-raw-link-controller') + expect(page).not_to have_selector('.js-raw-link-controller') end end end diff --git a/spec/features/projects/user_create_dir_spec.rb b/spec/features/projects/user_create_dir_spec.rb index 5dfdc465d7d..aeb7e0b7c33 100644 --- a/spec/features/projects/user_create_dir_spec.rb +++ b/spec/features/projects/user_create_dir_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' feature 'New directory creation', feature: true, js: true do - include TargetBranchHelpers - given(:user) { create(:user) } given(:role) { :developer } given(:project) { create(:project) } @@ -36,23 +34,11 @@ feature 'New directory creation', feature: true, js: true do end end - context 'with different target branch' do - background do - select_branch('feature') - create_directory - end - - scenario 'creates the directory in the different branch' do - expect(page).to have_content 'feature' - expect(page).to have_content 'The directory has been successfully created' - end - end - context 'with a new target branch' do given(:new_branch_name) { 'new-feature' } background do - create_new_branch(new_branch_name) + fill_in :branch_name, with: new_branch_name create_directory end diff --git a/spec/features/projects/wiki/markdown_preview_spec.rb b/spec/features/projects/wiki/markdown_preview_spec.rb index 49d7ef09e64..94f6bb16730 100644 --- a/spec/features/projects/wiki/markdown_preview_spec.rb +++ b/spec/features/projects/wiki/markdown_preview_spec.rb @@ -14,11 +14,12 @@ feature 'Projects > Wiki > User previews markdown changes', feature: true, js: t background do project.team << [user, :master] + WikiPages::CreateService.new(project, user, title: 'home', content: 'Home page').execute + login_as(user) visit namespace_project_path(project.namespace, project) find('.shortcuts-wiki').trigger('click') - WikiPages::CreateService.new(project, user, title: 'home', content: 'Home page').execute end context "while creating a new wiki page" do diff --git a/spec/features/todos/todos_spec.rb b/spec/features/todos/todos_spec.rb index bb4b2aed0e3..feb2fe8a7d1 100644 --- a/spec/features/todos/todos_spec.rb +++ b/spec/features/todos/todos_spec.rb @@ -333,29 +333,6 @@ describe 'Dashboard Todos', feature: true do end end - context 'User have large number of todos' do - before do - create_list(:todo, 101, :mentioned, user: user, project: project, target: issue, author: author) - - login_as(user) - visit dashboard_todos_path - end - - it 'shows 99+ for count >= 100 in notification' do - expect(page).to have_selector('.todos-count', text: '99+') - end - - it 'shows exact number in To do tab' do - expect(page).to have_selector('.todos-pending .badge', text: '101') - end - - it 'shows exact number for count < 100' do - 3.times { first('.js-done-todo').click } - - expect(page).to have_selector('.todos-count', text: '98') - end - end - context 'User has a Build Failed todo' do let!(:todo) { create(:todo, :build_failed, user: user, project: project, author: author) } diff --git a/spec/helpers/todos_helper_spec.rb b/spec/helpers/todos_helper_spec.rb index 50060a0925d..18a41ca24e3 100644 --- a/spec/helpers/todos_helper_spec.rb +++ b/spec/helpers/todos_helper_spec.rb @@ -1,6 +1,19 @@ require "spec_helper" describe TodosHelper do + describe '#todos_count_format' do + it 'shows fuzzy count for 100 or more items' do + expect(helper.todos_count_format(100)).to eq '99+' + expect(helper.todos_count_format(1000)).to eq '99+' + end + + it 'shows exact count for 99 or fewer items' do + expect(helper.todos_count_format(99)).to eq '99' + expect(helper.todos_count_format(50)).to eq '50' + expect(helper.todos_count_format(1)).to eq '1' + end + end + describe '#todo_projects_options' do let(:projects) { create_list(:empty_project, 3) } let(:user) { create(:user) } diff --git a/spec/helpers/u2f_helper_spec.rb b/spec/helpers/u2f_helper_spec.rb new file mode 100644 index 00000000000..0d65b4fe0b8 --- /dev/null +++ b/spec/helpers/u2f_helper_spec.rb @@ -0,0 +1,49 @@ +require 'spec_helper' + +describe U2fHelper do + describe 'when not on mobile' do + it 'does not inject u2f on chrome 40' do + device = double(mobile?: false) + browser = double(chrome?: true, opera?: false, version: 40, device: device) + allow(helper).to receive(:browser).and_return(browser) + expect(helper.inject_u2f_api?).to eq false + end + + it 'injects u2f on chrome 41' do + device = double(mobile?: false) + browser = double(chrome?: true, opera?: false, version: 41, device: device) + allow(helper).to receive(:browser).and_return(browser) + expect(helper.inject_u2f_api?).to eq true + end + + it 'does not inject u2f on opera 39' do + device = double(mobile?: false) + browser = double(chrome?: false, opera?: true, version: 39, device: device) + allow(helper).to receive(:browser).and_return(browser) + expect(helper.inject_u2f_api?).to eq false + end + + it 'injects u2f on opera 40' do + device = double(mobile?: false) + browser = double(chrome?: false, opera?: true, version: 40, device: device) + allow(helper).to receive(:browser).and_return(browser) + expect(helper.inject_u2f_api?).to eq true + end + end + + describe 'when on mobile' do + it 'does not inject u2f on chrome 41' do + device = double(mobile?: true) + browser = double(chrome?: true, opera?: false, version: 41, device: device) + allow(helper).to receive(:browser).and_return(browser) + expect(helper.inject_u2f_api?).to eq false + end + + it 'does not inject u2f on opera 40' do + device = double(mobile?: true) + browser = double(chrome?: false, opera?: true, version: 40, device: device) + allow(helper).to receive(:browser).and_return(browser) + expect(helper.inject_u2f_api?).to eq false + end + end +end diff --git a/spec/javascripts/blob/create_branch_dropdown_spec.js b/spec/javascripts/blob/create_branch_dropdown_spec.js deleted file mode 100644 index 6dbaa47c544..00000000000 --- a/spec/javascripts/blob/create_branch_dropdown_spec.js +++ /dev/null @@ -1,106 +0,0 @@ -import '~/gl_dropdown'; -import '~/blob/create_branch_dropdown'; -import '~/blob/target_branch_dropdown'; - -describe('CreateBranchDropdown', () => { - const fixtureTemplate = 'static/target_branch_dropdown.html.raw'; - // selectors - const createBranchSel = '.js-new-branch-btn'; - const backBtnSel = '.dropdown-menu-back'; - const cancelBtnSel = '.js-cancel-branch-btn'; - const branchNameSel = '#new_branch_name'; - const branchName = 'new_name'; - let dropdown; - - function createDropdown() { - const dropdownEl = document.querySelector('.js-project-branches-dropdown'); - const projectBranches = getJSONFixture('project_branches.json'); - dropdown = new gl.TargetBranchDropDown(dropdownEl); - dropdown.cachedRefs = projectBranches; - return dropdown; - } - - function createBranchBtn() { - return document.querySelector(createBranchSel); - } - - function backBtn() { - return document.querySelector(backBtnSel); - } - - function cancelBtn() { - return document.querySelector(cancelBtnSel); - } - - function branchNameEl() { - return document.querySelector(branchNameSel); - } - - function changeBranchName(text) { - branchNameEl().value = text; - branchNameEl().dispatchEvent(new Event('change')); - } - - preloadFixtures(fixtureTemplate); - - beforeEach(() => { - loadFixtures(fixtureTemplate); - createDropdown(); - }); - - it('disable submit when branch name is empty', () => { - expect(createBranchBtn()).toBeDisabled(); - }); - - it('enable submit when branch name is present', () => { - changeBranchName(branchName); - - expect(createBranchBtn()).not.toBeDisabled(); - }); - - it('resets the form when cancel btn is clicked and triggers dropdownback', () => { - const spyBackEvent = spyOnEvent(backBtnSel, 'click'); - changeBranchName(branchName); - - cancelBtn().click(); - - expect(branchNameEl()).toHaveValue(''); - expect(spyBackEvent).toHaveBeenTriggered(); - }); - - it('resets the form when back btn is clicked', () => { - changeBranchName(branchName); - - backBtn().click(); - - expect(branchNameEl()).toHaveValue(''); - }); - - describe('new branch creation', () => { - beforeEach(() => { - changeBranchName(branchName); - }); - it('sets the new branch name and updates the dropdown', () => { - spyOn(dropdown, 'setNewBranch'); - - createBranchBtn().click(); - - expect(dropdown.setNewBranch).toHaveBeenCalledWith(branchName); - }); - - it('resets the form', () => { - createBranchBtn().click(); - - expect(branchNameEl()).toHaveValue(''); - }); - - it('is triggered with enter keypress', () => { - spyOn(dropdown, 'setNewBranch'); - const enterEvent = new Event('keydown'); - enterEvent.which = 13; - branchNameEl().dispatchEvent(enterEvent); - - expect(dropdown.setNewBranch).toHaveBeenCalledWith(branchName); - }); - }); -}); diff --git a/spec/javascripts/blob/target_branch_dropdown_spec.js b/spec/javascripts/blob/target_branch_dropdown_spec.js deleted file mode 100644 index 99c9537d2ec..00000000000 --- a/spec/javascripts/blob/target_branch_dropdown_spec.js +++ /dev/null @@ -1,118 +0,0 @@ -import '~/gl_dropdown'; -import '~/blob/create_branch_dropdown'; -import '~/blob/target_branch_dropdown'; - -describe('TargetBranchDropdown', () => { - const fixtureTemplate = 'static/target_branch_dropdown.html.raw'; - let dropdown; - - function createDropdown() { - const projectBranches = getJSONFixture('project_branches.json'); - const dropdownEl = document.querySelector('.js-project-branches-dropdown'); - dropdown = new gl.TargetBranchDropDown(dropdownEl); - dropdown.cachedRefs = projectBranches; - dropdown.refreshData(); - return dropdown; - } - - function submitBtn() { - return document.querySelector('button[type="submit"]'); - } - - function searchField() { - return document.querySelector('.dropdown-page-one .dropdown-input-field'); - } - - function element() { - return document.querySelectorAll('div.dropdown-content li a'); - } - - function elementAtIndex(index) { - return element()[index]; - } - - function clickElementAtIndex(index) { - elementAtIndex(index).click(); - } - - preloadFixtures(fixtureTemplate); - - beforeEach(() => { - loadFixtures(fixtureTemplate); - createDropdown(); - }); - - it('disable submit when branch is not selected', () => { - document.querySelector('input[name="target_branch"]').value = null; - clickElementAtIndex(1); - - expect(submitBtn().getAttribute('disabled')).toEqual(''); - }); - - it('enable submit when a branch is selected', () => { - clickElementAtIndex(1); - - expect(submitBtn().getAttribute('disabled')).toBe(null); - }); - - it('triggers change.branch event on a branch click', () => { - spyOnEvent(dropdown.$dropdown, 'change.branch'); - clickElementAtIndex(0); - - expect('change.branch').toHaveBeenTriggeredOn(dropdown.$dropdown); - }); - - describe('dropdownData', () => { - it('cache the refs', () => { - const refs = dropdown.cachedRefs; - dropdown.cachedRefs = null; - - dropdown.dropdownData(refs); - - expect(dropdown.cachedRefs).toEqual(refs); - }); - - it('returns the Branches with the newBranch and defaultBranch', () => { - const refs = dropdown.cachedRefs; - dropdown.branchInput.value = 'master'; - dropdown.newBranch = { id: 'new_branch', text: 'new_branch', title: 'new_branch' }; - - const branches = dropdown.dropdownData(refs).Branches; - - expect(branches.length).toEqual(4); - expect(branches[0]).toEqual(dropdown.newBranch); - expect(branches[1]).toEqual({ id: 'master', text: 'master', title: 'master' }); - expect(branches[2]).toEqual({ id: 'development', text: 'development', title: 'development' }); - expect(branches[3]).toEqual({ id: 'staging', text: 'staging', title: 'staging' }); - }); - }); - - describe('setNewBranch', () => { - it('adds the new branch and select it', () => { - const branchName = 'new_branch'; - - dropdown.setNewBranch(branchName); - - expect(elementAtIndex(0)).toHaveClass('is-active'); - expect(elementAtIndex(0)).toContainHtml(branchName); - }); - - it("doesn't add a new branch if already exists in the list", () => { - const branchName = elementAtIndex(0).text; - const initialLength = element().length; - - dropdown.setNewBranch(branchName); - - expect(element().length).toEqual(initialLength); - }); - - it('clears the search filter', () => { - const branchName = elementAtIndex(0).text; - searchField().value = 'searching'; - - dropdown.setNewBranch(branchName); - - expect(searchField().value).toEqual(''); - }); - }); -}); diff --git a/spec/javascripts/build_spec.js b/spec/javascripts/build_spec.js index 4c8a48580d7..be90dbdd88a 100644 --- a/spec/javascripts/build_spec.js +++ b/spec/javascripts/build_spec.js @@ -132,23 +132,6 @@ describe('Build', () => { expect($('#build-trace .js-build-output').text()).not.toMatch(/Update/); expect($('#build-trace .js-build-output').text()).toMatch(/Different/); }); - - it('reloads the page when the build is done', () => { - spyOn(gl.utils, 'visitUrl'); - const deferred = $.Deferred(); - - spyOn($, 'ajax').and.returnValue(deferred.promise()); - deferred.resolve({ - html: '<span>Final</span>', - status: 'passed', - append: true, - complete: true, - }); - - this.build = new Build(); - - expect(gl.utils.visitUrl).toHaveBeenCalledWith(BUILD_URL); - }); }); describe('truncated information', () => { diff --git a/spec/javascripts/datetime_utility_spec.js b/spec/javascripts/datetime_utility_spec.js index c82ad0bea48..e54ea11b08c 100644 --- a/spec/javascripts/datetime_utility_spec.js +++ b/spec/javascripts/datetime_utility_spec.js @@ -1,4 +1,4 @@ -import '~/lib/utils/datetime_utility'; +import { timeIntervalInWords } from '~/lib/utils/datetime_utility'; (() => { describe('Date time utils', () => { @@ -82,4 +82,13 @@ import '~/lib/utils/datetime_utility'; }); }); }); + + describe('timeIntervalInWords', () => { + it('should return string with number of minutes and seconds', () => { + expect(timeIntervalInWords(9.54)).toEqual('9 seconds'); + expect(timeIntervalInWords(1)).toEqual('1 second'); + expect(timeIntervalInWords(200)).toEqual('3 minutes 20 seconds'); + expect(timeIntervalInWords(6008)).toEqual('100 minutes 8 seconds'); + }); + }); })(); diff --git a/spec/javascripts/fixtures/project_branches.json b/spec/javascripts/fixtures/project_branches.json deleted file mode 100644 index a96a4c0c095..00000000000 --- a/spec/javascripts/fixtures/project_branches.json +++ /dev/null @@ -1,5 +0,0 @@ -[ - "master", - "development", - "staging" -] diff --git a/spec/javascripts/fixtures/target_branch_dropdown.html.haml b/spec/javascripts/fixtures/target_branch_dropdown.html.haml deleted file mode 100644 index 821fb7940a0..00000000000 --- a/spec/javascripts/fixtures/target_branch_dropdown.html.haml +++ /dev/null @@ -1,28 +0,0 @@ -%form.js-edit-blob-form - %input{type: 'hidden', name: 'target_branch', value: 'master'} - %div - .dropdown - %button.dropdown-menu-toggle.js-project-branches-dropdown.js-target-branch{type: 'button', data: {toggle: 'dropdown', selected: 'master', field_name: 'target_branch', form_id: '.js-edit-blob-form'}} - .dropdown-menu.dropdown-menu-selectable.dropdown-menu-paging - .dropdown-page-one - .dropdown-title 'Select branch' - .dropdown-input - %input.dropdown-input-field{type: 'search', value: ''} - %i.fa.fa-search.dropdown-input-search - %i.fa.fa-times-dropdown-input-clear.js-dropdown-input-clear{role: 'button'} - .dropdown-content - .dropdown-footer - %ul.dropdown-footer-list - %li - %a.create-new-branch.dropdown-toggle-page{href: "#"} - Create new branch - .dropdown-page-two.dropdown-new-branch - %button.dropdown-title-button.dropdown-menu-back{type: 'button'} - .dropdown_title 'Create new branch' - .dropdown_content - %input#new_branch_name.default-dropdown-input{ type: "text", placeholder: "Name new branch" } - %button.btn.btn-primary.pull-left.js-new-branch-btn{ type: "button" } - Create - %button.btn.btn-default.pull-right.js-cancel-branch-btn{ type: "button" } - Cancel - %button{type: 'submit'} diff --git a/spec/javascripts/gl_dropdown_spec.js b/spec/javascripts/gl_dropdown_spec.js index 3292590b9ed..10fcc590c89 100644 --- a/spec/javascripts/gl_dropdown_spec.js +++ b/spec/javascripts/gl_dropdown_spec.js @@ -185,7 +185,7 @@ import '~/lib/utils/url_utility'; expect($(document.activeElement)).toEqual($(SEARCH_INPUT_SELECTOR)); }); - it('should focus on input when opening for the second time', () => { + it('should focus on input when opening for the second time after transition', () => { remoteCallback(); this.dropdownContainerElement.trigger({ type: 'keyup', @@ -193,6 +193,7 @@ import '~/lib/utils/url_utility'; keyCode: ARROW_KEYS.ESC }); this.dropdownButtonElement.click(); + this.dropdownContainerElement.trigger('transitionend'); expect($(document.activeElement)).toEqual($(SEARCH_INPUT_SELECTOR)); }); }); @@ -201,6 +202,7 @@ import '~/lib/utils/url_utility'; it('should focus input when passing array data to drop down', () => { initDropDown.call(this, false, true); this.dropdownButtonElement.click(); + this.dropdownContainerElement.trigger('transitionend'); expect($(document.activeElement)).toEqual($(SEARCH_INPUT_SELECTOR)); }); }); diff --git a/spec/javascripts/jobs/header_spec.js b/spec/javascripts/jobs/header_spec.js new file mode 100644 index 00000000000..c7179b3e03d --- /dev/null +++ b/spec/javascripts/jobs/header_spec.js @@ -0,0 +1,63 @@ +import Vue from 'vue'; +import headerComponent from '~/jobs/components/header.vue'; + +describe('Job details header', () => { + let HeaderComponent; + let vm; + let props; + + beforeEach(() => { + HeaderComponent = Vue.extend(headerComponent); + + const threeWeeksAgo = new Date(); + threeWeeksAgo.setDate(threeWeeksAgo.getDate() - 21); + + props = { + job: { + status: { + group: 'failed', + icon: 'ci-status-failed', + label: 'failed', + text: 'failed', + details_path: 'path', + }, + id: 123, + created_at: threeWeeksAgo.toISOString(), + user: { + web_url: 'path', + name: 'Foo', + username: 'foobar', + email: 'foo@bar.com', + avatar_url: 'link', + }, + retry_path: 'path', + new_issue_path: 'path', + }, + isLoading: false, + }; + + vm = new HeaderComponent({ propsData: props }).$mount(); + }); + + afterEach(() => { + vm.$destroy(); + }); + + it('should render provided job information', () => { + expect( + vm.$el.querySelector('.header-main-content').textContent.replace(/\s+/g, ' ').trim(), + ).toEqual('failed Job #123 triggered 3 weeks ago by Foo'); + }); + + it('should render retry link', () => { + expect( + vm.$el.querySelector('.js-retry-button').getAttribute('href'), + ).toEqual(props.job.retry_path); + }); + + it('should render new issue link', () => { + expect( + vm.$el.querySelector('.js-new-issue').getAttribute('href'), + ).toEqual(props.job.new_issue_path); + }); +}); diff --git a/spec/javascripts/jobs/job_details_mediator_spec.js b/spec/javascripts/jobs/job_details_mediator_spec.js new file mode 100644 index 00000000000..1d7fa7e12fc --- /dev/null +++ b/spec/javascripts/jobs/job_details_mediator_spec.js @@ -0,0 +1,43 @@ +import Vue from 'vue'; +import JobMediator from '~/jobs/job_details_mediator'; +import job from './mock_data'; + +describe('JobMediator', () => { + let mediator; + + beforeEach(() => { + mediator = new JobMediator({ endpoint: 'foo' }); + }); + + it('should set defaults', () => { + expect(mediator.store).toBeDefined(); + expect(mediator.service).toBeDefined(); + expect(mediator.options).toEqual({ endpoint: 'foo' }); + expect(mediator.state.isLoading).toEqual(false); + }); + + describe('request and store data', () => { + const interceptor = (request, next) => { + next(request.respondWith(JSON.stringify(job), { + status: 200, + })); + }; + + beforeEach(() => { + Vue.http.interceptors.push(interceptor); + }); + + afterEach(() => { + Vue.http.interceptors = _.without(Vue.http.interceptor, interceptor); + }); + + it('should store received data', (done) => { + mediator.fetchJob(); + + setTimeout(() => { + expect(mediator.store.state.job).toEqual(job); + done(); + }, 0); + }); + }); +}); diff --git a/spec/javascripts/jobs/job_store_spec.js b/spec/javascripts/jobs/job_store_spec.js new file mode 100644 index 00000000000..d00faf29d1e --- /dev/null +++ b/spec/javascripts/jobs/job_store_spec.js @@ -0,0 +1,26 @@ +import JobStore from '~/jobs/stores/job_store'; +import job from './mock_data'; + +describe('Job Store', () => { + let store; + + beforeEach(() => { + store = new JobStore(); + }); + + it('should set defaults', () => { + expect(store.state.job).toEqual({}); + }); + + describe('storeJob', () => { + it('should store empty object if none is provided', () => { + store.storeJob(); + expect(store.state.job).toEqual({}); + }); + + it('should store provided argument', () => { + store.storeJob(job); + expect(store.state.job).toEqual(job); + }); + }); +}); diff --git a/spec/javascripts/jobs/mock_data.js b/spec/javascripts/jobs/mock_data.js new file mode 100644 index 00000000000..17e4ef26b2c --- /dev/null +++ b/spec/javascripts/jobs/mock_data.js @@ -0,0 +1,123 @@ +const threeWeeksAgo = new Date(); +threeWeeksAgo.setDate(threeWeeksAgo.getDate() - 21); + +export default { + id: 4757, + name: 'test', + build_path: '/root/ci-mock/-/jobs/4757', + retry_path: '/root/ci-mock/-/jobs/4757/retry', + cancel_path: '/root/ci-mock/-/jobs/4757/cancel', + new_issue_path: '/root/ci-mock/issues/new', + playable: false, + created_at: threeWeeksAgo.toISOString(), + updated_at: threeWeeksAgo.toISOString(), + finished_at: threeWeeksAgo.toISOString(), + queued: 9.54, + status: { + icon: 'icon_status_success', + text: 'passed', + label: 'passed', + group: 'success', + has_details: true, + details_path: '/root/ci-mock/-/jobs/4757', + favicon: '/assets/ci_favicons/dev/favicon_status_success-308b4fc054cdd1b68d0865e6cfb7b02e92e3472f201507418f8eddb74ac11a59.ico', + action: { + icon: 'icon_action_retry', + title: 'Retry', + path: '/root/ci-mock/-/jobs/4757/retry', + method: 'post', + }, + }, + coverage: 20, + erased_at: threeWeeksAgo.toISOString(), + duration: 6.785563, + tags: ['tag'], + user: { + name: 'Root', + username: 'root', + id: 1, + state: 'active', + avatar_url: 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon', + web_url: 'http://localhost:3000/root', + }, + erase_path: '/root/ci-mock/-/jobs/4757/erase', + artifacts: [null], + runner: { + id: 1, + description: 'local ci runner', + edit_path: '/root/ci-mock/runners/1/edit', + }, + pipeline: { + id: 140, + user: { + name: 'Root', + username: 'root', + id: 1, + state: 'active', + avatar_url: 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon', + web_url: 'http://localhost:3000/root', + }, + active: false, + coverage: null, + source: 'unknown', + created_at: '2017-05-24T09:59:58.634Z', + updated_at: '2017-06-01T17:32:00.062Z', + path: '/root/ci-mock/pipelines/140', + flags: { + latest: true, + stuck: false, + yaml_errors: false, + retryable: false, + cancelable: false, + }, + details: { + status: { + icon: 'icon_status_success', + text: 'passed', + label: 'passed', + group: 'success', + has_details: true, + details_path: '/root/ci-mock/pipelines/140', + favicon: '/assets/ci_favicons/dev/favicon_status_success-308b4fc054cdd1b68d0865e6cfb7b02e92e3472f201507418f8eddb74ac11a59.ico', + }, + duration: 6, + finished_at: '2017-06-01T17:32:00.042Z', + }, + ref: { + name: 'abc', + path: '/root/ci-mock/commits/abc', + tag: false, + branch: true, + }, + commit: { + id: 'c58647773a6b5faf066d4ad6ff2c9fbba5f180f6', + short_id: 'c5864777', + title: 'Add new file', + created_at: '2017-05-24T10:59:52.000+01:00', + parent_ids: ['798e5f902592192afaba73f4668ae30e56eae492'], + message: 'Add new file', + author_name: 'Root', + author_email: 'admin@example.com', + authored_date: '2017-05-24T10:59:52.000+01:00', + committer_name: 'Root', + committer_email: 'admin@example.com', + committed_date: '2017-05-24T10:59:52.000+01:00', + author: { + name: 'Root', + username: 'root', + id: 1, + state: 'active', + avatar_url: 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon', + web_url: 'http://localhost:3000/root', + }, + author_gravatar_url: 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon', + commit_url: 'http://localhost:3000/root/ci-mock/commit/c58647773a6b5faf066d4ad6ff2c9fbba5f180f6', + commit_path: '/root/ci-mock/commit/c58647773a6b5faf066d4ad6ff2c9fbba5f180f6', + }, + }, + merge_request: { + iid: 2, + path: '/root/ci-mock/merge_requests/2', + }, + raw_path: '/root/ci-mock/builds/4757/raw', +}; diff --git a/spec/javascripts/jobs/sidebar_detail_row_spec.js b/spec/javascripts/jobs/sidebar_detail_row_spec.js new file mode 100644 index 00000000000..3ac65709c4a --- /dev/null +++ b/spec/javascripts/jobs/sidebar_detail_row_spec.js @@ -0,0 +1,40 @@ +import Vue from 'vue'; +import sidebarDetailRow from '~/jobs/components/sidebar_detail_row.vue'; + +describe('Sidebar detail row', () => { + let SidebarDetailRow; + let vm; + + beforeEach(() => { + SidebarDetailRow = Vue.extend(sidebarDetailRow); + }); + + afterEach(() => { + vm.$destroy(); + }); + + it('should render no title', () => { + vm = new SidebarDetailRow({ + propsData: { + value: 'this is the value', + }, + }).$mount(); + + expect(vm.$el.textContent.replace(/\s+/g, ' ').trim()).toEqual('this is the value'); + }); + + beforeEach(() => { + vm = new SidebarDetailRow({ + propsData: { + title: 'this is the title', + value: 'this is the value', + }, + }).$mount(); + }); + + it('should render provided title and value', () => { + expect( + vm.$el.textContent.replace(/\s+/g, ' ').trim(), + ).toEqual('this is the title: this is the value'); + }); +}); diff --git a/spec/javascripts/jobs/sidebar_details_block_spec.js b/spec/javascripts/jobs/sidebar_details_block_spec.js new file mode 100644 index 00000000000..95532ef5382 --- /dev/null +++ b/spec/javascripts/jobs/sidebar_details_block_spec.js @@ -0,0 +1,111 @@ +import Vue from 'vue'; +import sidebarDetailsBlock from '~/jobs/components/sidebar_details_block.vue'; +import job from './mock_data'; + +describe('Sidebar details block', () => { + let SidebarComponent; + let vm; + + function trimWhitespace(element) { + return element.textContent.replace(/\s+/g, ' ').trim(); + } + + beforeEach(() => { + SidebarComponent = Vue.extend(sidebarDetailsBlock); + }); + + afterEach(() => { + vm.$destroy(); + }); + + describe('when it is loading', () => { + it('should render a loading spinner', () => { + vm = new SidebarComponent({ + propsData: { + job: {}, + isLoading: true, + }, + }).$mount(); + + expect(vm.$el.querySelector('.fa-spinner')).toBeDefined(); + }); + }); + + beforeEach(() => { + vm = new SidebarComponent({ + propsData: { + job, + isLoading: false, + }, + }).$mount(); + }); + + describe('actions', () => { + it('should render link to new issue', () => { + expect(vm.$el.querySelector('.js-new-issue').getAttribute('href')).toEqual(job.new_issue_path); + expect(vm.$el.querySelector('.js-new-issue').textContent.trim()).toEqual('New issue'); + }); + + it('should render link to retry job', () => { + expect(vm.$el.querySelector('.js-retry-job').getAttribute('href')).toEqual(job.retry_path); + }); + + it('should render link to cancel job', () => { + expect(vm.$el.querySelector('.js-cancel-job').getAttribute('href')).toEqual(job.cancel_path); + }); + }); + + describe('information', () => { + it('should render merge request link', () => { + expect( + trimWhitespace(vm.$el.querySelector('.js-job-mr')), + ).toEqual('Merge Request: !2'); + + expect( + vm.$el.querySelector('.js-job-mr a').getAttribute('href'), + ).toEqual(job.merge_request.path); + }); + + it('should render job duration', () => { + expect( + trimWhitespace(vm.$el.querySelector('.js-job-duration')), + ).toEqual('Duration: 6 seconds'); + }); + + it('should render erased date', () => { + expect( + trimWhitespace(vm.$el.querySelector('.js-job-erased')), + ).toEqual('Erased: 3 weeks ago'); + }); + + it('should render finished date', () => { + expect( + trimWhitespace(vm.$el.querySelector('.js-job-finished')), + ).toEqual('Finished: 3 weeks ago'); + }); + + it('should render queued date', () => { + expect( + trimWhitespace(vm.$el.querySelector('.js-job-queued')), + ).toEqual('Queued: 9 seconds'); + }); + + it('should render runner ID', () => { + expect( + trimWhitespace(vm.$el.querySelector('.js-job-runner')), + ).toEqual('Runner: #1'); + }); + + it('should render coverage', () => { + expect( + trimWhitespace(vm.$el.querySelector('.js-job-coverage')), + ).toEqual('Coverage: 20%'); + }); + + it('should render tags', () => { + expect( + trimWhitespace(vm.$el.querySelector('.js-job-tags')), + ).toEqual('Tags: tag'); + }); + }); +}); diff --git a/spec/javascripts/pipelines/nav_controls_spec.js b/spec/javascripts/pipelines/nav_controls_spec.js index 601eebce38a..f1697840fcd 100644 --- a/spec/javascripts/pipelines/nav_controls_spec.js +++ b/spec/javascripts/pipelines/nav_controls_spec.js @@ -1,5 +1,5 @@ import Vue from 'vue'; -import navControlsComp from '~/pipelines/components/nav_controls'; +import navControlsComp from '~/pipelines/components/nav_controls.vue'; describe('Pipelines Nav Controls', () => { let NavControlsComponent; diff --git a/spec/javascripts/vue_shared/components/header_ci_component_spec.js b/spec/javascripts/vue_shared/components/header_ci_component_spec.js index 2b51c89f311..e28639f12f3 100644 --- a/spec/javascripts/vue_shared/components/header_ci_component_spec.js +++ b/spec/javascripts/vue_shared/components/header_ci_component_spec.js @@ -43,6 +43,7 @@ describe('Header CI Component', () => { isLoading: false, }, ], + hasSidebarButton: true, }; vm = new HeaderCi({ @@ -90,4 +91,8 @@ describe('Header CI Component', () => { done(); }); }); + + it('should render sidebar toggle button', () => { + expect(vm.$el.querySelector('.js-sidebar-build-toggle')).toBeDefined(); + }); }); diff --git a/spec/lib/gitlab/auth_spec.rb b/spec/lib/gitlab/auth_spec.rb index d6006eab0c9..d09da951869 100644 --- a/spec/lib/gitlab/auth_spec.rb +++ b/spec/lib/gitlab/auth_spec.rb @@ -204,6 +204,12 @@ describe Gitlab::Auth, lib: true do expect(gl_auth).to receive(:rate_limit!).with('ip', success: false, login: login) expect(gl_auth.find_for_git_client(login, 'bar', project: nil, ip: 'ip')).to eq(Gitlab::Auth::Result.new) end + + it 'throws an error suggesting user create a PAT when internal auth is disabled' do + allow_any_instance_of(ApplicationSetting).to receive(:signin_enabled?) { false } + + expect { gl_auth.find_for_git_client('foo', 'bar', project: nil, ip: 'ip') }.to raise_error(Gitlab::Auth::MissingPersonalTokenError) + end end describe 'find_with_user_password' do diff --git a/spec/models/blob_viewer/base_spec.rb b/spec/models/blob_viewer/base_spec.rb index d56379eb59d..574438838d8 100644 --- a/spec/models/blob_viewer/base_spec.rb +++ b/spec/models/blob_viewer/base_spec.rb @@ -106,9 +106,9 @@ describe BlobViewer::Base, model: true do end describe '#render_error' do - context 'when expanded' do + context 'when the blob is expanded' do before do - viewer.expanded = true + blob.expand! end context 'when the blob size is larger than the size limit' do diff --git a/spec/presenters/merge_request_presenter_spec.rb b/spec/presenters/merge_request_presenter_spec.rb index 44720fc4448..f5a14b1d04d 100644 --- a/spec/presenters/merge_request_presenter_spec.rb +++ b/spec/presenters/merge_request_presenter_spec.rb @@ -132,6 +132,11 @@ describe MergeRequestPresenter do it 'does not present related issues links' do is_expected.not_to match("#{project.full_path}/issues/#{issue_b.iid}") end + + it 'appends status when closing issue is already closed' do + issue_a.close + is_expected.to match('(closed)') + end end describe '#mentioned_issues_links' do @@ -147,6 +152,11 @@ describe MergeRequestPresenter do it 'does not present closing issues links' do is_expected.not_to match("#{project.full_path}/issues/#{issue_a.iid}") end + + it 'appends status when mentioned issue is already closed' do + issue_b.close + is_expected.to match('(closed)') + end end describe '#assign_to_closing_issues_link' do diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index 86c57204971..3e831373514 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -398,6 +398,15 @@ describe API::Projects do expect(json_response['tag_list']).to eq(%w[tagFirst tagSecond]) end + it 'uploads avatar for project a project' do + project = attributes_for(:project, avatar: fixture_file_upload(Rails.root + 'spec/fixtures/banana_sample.gif', 'image/gif')) + + post api('/projects', user), project + + project_id = json_response['id'] + expect(json_response['avatar_url']).to eq("http://localhost/uploads/system/project/avatar/#{project_id}/banana_sample.gif") + end + it 'sets a project as allowing merge even if build fails' do project = attributes_for(:project, { only_allow_merge_if_pipeline_succeeds: false }) post api('/projects', user), project diff --git a/spec/requests/git_http_spec.rb b/spec/requests/git_http_spec.rb index c09be0ce1b9..6a83024d0d5 100644 --- a/spec/requests/git_http_spec.rb +++ b/spec/requests/git_http_spec.rb @@ -418,17 +418,17 @@ describe 'Git HTTP requests', lib: true do end context 'when username and password are provided' do - it 'rejects pulls with 2FA error message' do + it 'rejects pulls with personal access token error message' do download(path, user: user.username, password: user.password) do |response| expect(response).to have_http_status(:unauthorized) - expect(response.body).to include('You have 2FA enabled, please use a personal access token for Git over HTTP') + expect(response.body).to include('You must use a personal access token with \'api\' scope for Git over HTTP') end end - it 'rejects the push attempt' do + it 'rejects the push attempt with personal access token error message' do upload(path, user: user.username, password: user.password) do |response| expect(response).to have_http_status(:unauthorized) - expect(response.body).to include('You have 2FA enabled, please use a personal access token for Git over HTTP') + expect(response.body).to include('You must use a personal access token with \'api\' scope for Git over HTTP') end end end @@ -441,6 +441,41 @@ describe 'Git HTTP requests', lib: true do end end + context 'when internal auth is disabled' do + before do + allow_any_instance_of(ApplicationSetting).to receive(:signin_enabled?) { false } + end + + it 'rejects pulls with personal access token error message' do + download(path, user: 'foo', password: 'bar') do |response| + expect(response).to have_http_status(:unauthorized) + expect(response.body).to include('You must use a personal access token with \'api\' scope for Git over HTTP') + end + end + + it 'rejects pushes with personal access token error message' do + upload(path, user: 'foo', password: 'bar') do |response| + expect(response).to have_http_status(:unauthorized) + expect(response.body).to include('You must use a personal access token with \'api\' scope for Git over HTTP') + end + end + + context 'when LDAP is configured' do + before do + allow(Gitlab::LDAP::Config).to receive(:enabled?).and_return(true) + allow_any_instance_of(Gitlab::LDAP::Authentication). + to receive(:login).and_return(nil) + end + + it 'does not display the personal access token error message' do + upload(path, user: 'foo', password: 'bar') do |response| + expect(response).to have_http_status(:unauthorized) + expect(response.body).not_to include('You must use a personal access token with \'api\' scope for Git over HTTP') + end + end + end + end + context "when blank password attempts follow a valid login" do def attempt_login(include_password) password = include_password ? user.password : "" diff --git a/spec/requests/jwt_controller_spec.rb b/spec/requests/jwt_controller_spec.rb index e056353fa6f..54d7cf5f10d 100644 --- a/spec/requests/jwt_controller_spec.rb +++ b/spec/requests/jwt_controller_spec.rb @@ -70,7 +70,7 @@ describe JwtController do context 'without personal token' do it 'rejects the authorization attempt' do expect(response).to have_http_status(401) - expect(response.body).to include('You have 2FA enabled, please use a personal access token for Git over HTTP') + expect(response.body).to include('You must use a personal access token with \'api\' scope for Git over HTTP') end end @@ -88,9 +88,24 @@ describe JwtController do context 'using invalid login' do let(:headers) { { authorization: credentials('invalid', 'password') } } - subject! { get '/jwt/auth', parameters, headers } + context 'when internal auth is enabled' do + it 'rejects the authorization attempt' do + get '/jwt/auth', parameters, headers + + expect(response).to have_http_status(401) + expect(response.body).not_to include('You must use a personal access token with \'api\' scope for Git over HTTP') + end + end - it { expect(response).to have_http_status(401) } + context 'when internal auth is disabled' do + it 'rejects the authorization attempt with personal access token message' do + allow_any_instance_of(ApplicationSetting).to receive(:signin_enabled?) { false } + get '/jwt/auth', parameters, headers + + expect(response).to have_http_status(401) + expect(response.body).to include('You must use a personal access token with \'api\' scope for Git over HTTP') + end + end end end diff --git a/spec/serializers/build_entity_spec.rb b/spec/serializers/build_entity_spec.rb index 46d43a80ef7..e51ff9fc709 100644 --- a/spec/serializers/build_entity_spec.rb +++ b/spec/serializers/build_entity_spec.rb @@ -2,12 +2,13 @@ require 'spec_helper' describe BuildEntity do let(:user) { create(:user) } - let(:build) { create(:ci_build, :failed) } + let(:build) { create(:ci_build) } let(:project) { build.project } let(:request) { double('request') } before do allow(request).to receive(:current_user).and_return(user) + project.add_developer(user) end let(:entity) do @@ -16,9 +17,8 @@ describe BuildEntity do subject { entity.as_json } - it 'contains paths to build page and retry action' do - expect(subject).to include(:build_path, :retry_path) - expect(subject[:retry_path]).not_to be_nil + it 'contains paths to build page action' do + expect(subject).to include(:build_path) end it 'does not contain sensitive information' do @@ -39,12 +39,32 @@ describe BuildEntity do expect(subject[:status]).to include :icon, :favicon, :text, :label end - context 'when build is a regular job' do + context 'when build is retryable' do + before do + build.update(status: :failed) + end + + it 'contains cancel path' do + expect(subject).to include(:retry_path) + end + end + + context 'when build is cancelable' do + before do + build.update(status: :running) + end + + it 'contains cancel path' do + expect(subject).to include(:cancel_path) + end + end + + context 'when build is a regular build' do it 'does not contain path to play action' do expect(subject).not_to include(:play_path) end - it 'is not a playable job' do + it 'is not a playable build' do expect(subject[:playable]).to be false end end diff --git a/spec/support/milestone_tabs_examples.rb b/spec/support/milestone_tabs_examples.rb index 4ad8b0a16e1..7cfc1e06975 100644 --- a/spec/support/milestone_tabs_examples.rb +++ b/spec/support/milestone_tabs_examples.rb @@ -1,10 +1,14 @@ shared_examples 'milestone tabs' do def go(path, extra_params = {}) - params = if milestone.is_a?(GlobalMilestone) - { group_id: group.to_param, id: milestone.safe_title, title: milestone.title } - else - { namespace_id: project.namespace.to_param, project_id: project, id: milestone.iid } - end + params = + case milestone + when DashboardMilestone + { id: milestone.safe_title, title: milestone.title } + when GroupMilestone + { group_id: group.to_param, id: milestone.safe_title, title: milestone.title } + else + { namespace_id: project.namespace.to_param, project_id: project, id: milestone.iid } + end get path, params.merge(extra_params) end diff --git a/spec/support/target_branch_helpers.rb b/spec/support/target_branch_helpers.rb deleted file mode 100644 index 01d1c53fe6c..00000000000 --- a/spec/support/target_branch_helpers.rb +++ /dev/null @@ -1,16 +0,0 @@ -module TargetBranchHelpers - def select_branch(name) - first('button.js-target-branch').click - wait_for_requests - all('a[data-group="Branches"]').find do |el| - el.text == name - end.click - end - - def create_new_branch(name) - first('button.js-target-branch').click - click_link 'Create new branch' - fill_in 'new_branch_name', with: name - click_button 'Create' - end -end diff --git a/spec/views/help/index.html.haml_spec.rb b/spec/views/help/index.html.haml_spec.rb index 6b07fcfc987..1f8261cc46b 100644 --- a/spec/views/help/index.html.haml_spec.rb +++ b/spec/views/help/index.html.haml_spec.rb @@ -21,7 +21,7 @@ describe 'help/index' do render expect(rendered).to match '8.0.2' - expect(rendered).to match 'abcdefg' + expect(rendered).to have_link('abcdefg', 'https://gitlab.com/gitlab-org/gitlab-ce/commits/abcdefg') end end diff --git a/spec/views/projects/jobs/show.html.haml_spec.rb b/spec/views/projects/jobs/show.html.haml_spec.rb index 8f2822f5dc5..d9a7ba265f8 100644 --- a/spec/views/projects/jobs/show.html.haml_spec.rb +++ b/spec/views/projects/jobs/show.html.haml_spec.rb @@ -15,36 +15,6 @@ describe 'projects/jobs/show', :view do allow(view).to receive(:can?).and_return(true) end - describe 'job information in header' do - let(:build) do - create(:ci_build, :success, environment: 'staging') - end - - before do - render - end - - it 'shows status name' do - expect(rendered).to have_css('.ci-status.ci-success', text: 'passed') - end - - it 'does not render a link to the job' do - expect(rendered).not_to have_link('passed') - end - - it 'shows job id' do - expect(rendered).to have_css('.js-build-id', text: build.id) - end - - it 'shows a link to the pipeline' do - expect(rendered).to have_link(build.pipeline.id) - end - - it 'shows a link to the commit' do - expect(rendered).to have_link(build.pipeline.short_sha) - end - end - describe 'environment info in job view' do context 'job with latest deployment' do let(:build) do @@ -215,34 +185,6 @@ describe 'projects/jobs/show', :view do end end - context 'when job is not running' do - before do - build.success! - render - end - - it 'shows retry button' do - expect(rendered).to have_link('Retry') - end - - context 'if build passed' do - it 'does not show New issue button' do - expect(rendered).not_to have_link('New issue') - end - end - - context 'if build failed' do - before do - build.status = 'failed' - render - end - - it 'shows New issue button' do - expect(rendered).to have_link('New issue') - end - end - end - describe 'commit title in sidebar' do let(:commit_title) { project.commit.title } @@ -269,25 +211,4 @@ describe 'projects/jobs/show', :view do expect(rendered).to have_css('.js-build-value', visible: false, text: 'TRIGGER_VALUE_2') end end - - describe 'New issue button' do - before do - build.status = 'failed' - render - end - - it 'links to issues/new with the title and description filled in' do - title = "Build Failed ##{build.id}" - build_url = namespace_project_job_url(project.namespace, project, build) - href = new_namespace_project_issue_path( - project.namespace, - project, - issue: { - title: title, - description: build_url - } - ) - expect(rendered).to have_link('New issue', href: href) - end - end end |