summaryrefslogtreecommitdiff
path: root/app/assets/javascripts
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts')
-rw-r--r--app/assets/javascripts/boards/filtered_search_boards.js1
-rw-r--r--app/assets/javascripts/commit/pipelines/pipelines_bundle.js33
-rw-r--r--app/assets/javascripts/commit/pipelines/pipelines_table.js191
-rw-r--r--app/assets/javascripts/commit/pipelines/pipelines_table.vue90
-rw-r--r--app/assets/javascripts/dispatcher.js29
-rw-r--r--app/assets/javascripts/dropzone_input.js4
-rw-r--r--app/assets/javascripts/environments/components/environment_item.vue15
-rw-r--r--app/assets/javascripts/filtered_search/dropdown_hint.js2
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_manager.js1
-rw-r--r--app/assets/javascripts/gfm_auto_complete.js6
-rw-r--r--app/assets/javascripts/issuable_bulk_update_sidebar.js2
-rw-r--r--app/assets/javascripts/issue_show/components/app.vue12
-rw-r--r--app/assets/javascripts/issue_show/components/description.vue30
-rw-r--r--app/assets/javascripts/issue_show/components/fields/description.vue2
-rw-r--r--app/assets/javascripts/issue_show/index.js1
-rw-r--r--app/assets/javascripts/issue_show/stores/index.js31
-rw-r--r--app/assets/javascripts/lib/utils/datetime_utility.js2
-rw-r--r--app/assets/javascripts/locale/en/app.js2
-rw-r--r--app/assets/javascripts/locale/es/app.js2
-rw-r--r--app/assets/javascripts/locale/zh_CN/app.js2
-rw-r--r--app/assets/javascripts/merge_request_tabs.js13
-rw-r--r--app/assets/javascripts/milestone.js163
-rw-r--r--app/assets/javascripts/notes.js50
-rw-r--r--app/assets/javascripts/pipeline_schedules/components/interval_pattern_input.js15
-rw-r--r--app/assets/javascripts/pipeline_schedules/components/pipeline_schedules_callout.js14
-rw-r--r--app/assets/javascripts/pipelines/components/async_button.vue41
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines.vue87
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_actions.vue16
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_table.vue (renamed from app/assets/javascripts/vue_shared/components/pipelines_table.vue)5
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_table_row.vue (renamed from app/assets/javascripts/vue_shared/components/pipelines_table_row.vue)23
-rw-r--r--app/assets/javascripts/pipelines/mixins/pipelines.js103
-rw-r--r--app/assets/javascripts/preview_markdown.js2
-rw-r--r--app/assets/javascripts/right_sidebar.js21
-rw-r--r--app/assets/javascripts/settings_panels.js25
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/help_state.js4
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/sidebar_time_tracking.js8
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_memory_usage.js4
37 files changed, 417 insertions, 635 deletions
diff --git a/app/assets/javascripts/boards/filtered_search_boards.js b/app/assets/javascripts/boards/filtered_search_boards.js
index b37698fe9ca..3f083655f95 100644
--- a/app/assets/javascripts/boards/filtered_search_boards.js
+++ b/app/assets/javascripts/boards/filtered_search_boards.js
@@ -11,7 +11,6 @@ export default class FilteredSearchBoards extends gl.FilteredSearchManager {
// Issue boards is slightly different, we handle all the requests async
// instead or reloading the page, we just re-fire the list ajax requests
this.isHandledAsync = true;
-
this.cantEdit = cantEdit;
}
diff --git a/app/assets/javascripts/commit/pipelines/pipelines_bundle.js b/app/assets/javascripts/commit/pipelines/pipelines_bundle.js
index 86d99dd87da..2c38440a2af 100644
--- a/app/assets/javascripts/commit/pipelines/pipelines_bundle.js
+++ b/app/assets/javascripts/commit/pipelines/pipelines_bundle.js
@@ -1,29 +1,30 @@
-/* eslint-disable no-param-reassign */
-
import Vue from 'vue';
-import VueResource from 'vue-resource';
-import CommitPipelinesTable from './pipelines_table';
-
-Vue.use(VueResource);
+import commitPipelinesTable from './pipelines_table.vue';
/**
- * Commits View > Pipelines Tab > Pipelines Table.
- *
- * Renders Pipelines table in pipelines tab in the commits show view.
+ * Used in:
+ * - Commit details View > Pipelines Tab > Pipelines Table.
+ * - Merge Request details View > Pipelines Tab > Pipelines Table.
+ * - New Merge Request View > Pipelines Tab > Pipelines Table.
*/
-// export for use in merge_request_tabs.js (TODO: remove this hack)
+const CommitPipelinesTable = Vue.extend(commitPipelinesTable);
+
+// export for use in merge_request_tabs.js (TODO: remove this hack when we understand how to load
+// vue.js in merge_request_tabs.js)
window.gl = window.gl || {};
window.gl.CommitPipelinesTable = CommitPipelinesTable;
-$(() => {
- gl.commits = gl.commits || {};
- gl.commits.pipelines = gl.commits.pipelines || {};
-
+document.addEventListener('DOMContentLoaded', () => {
const pipelineTableViewEl = document.querySelector('#commit-pipeline-table-view');
if (pipelineTableViewEl && pipelineTableViewEl.dataset.disableInitialization === undefined) {
- gl.commits.pipelines.PipelinesTableBundle = new CommitPipelinesTable().$mount();
- pipelineTableViewEl.appendChild(gl.commits.pipelines.PipelinesTableBundle.$el);
+ const table = new CommitPipelinesTable({
+ propsData: {
+ endpoint: pipelineTableViewEl.dataset.endpoint,
+ helpPagePath: pipelineTableViewEl.dataset.helpPagePath,
+ },
+ }).$mount();
+ pipelineTableViewEl.appendChild(table.$el);
}
});
diff --git a/app/assets/javascripts/commit/pipelines/pipelines_table.js b/app/assets/javascripts/commit/pipelines/pipelines_table.js
deleted file mode 100644
index 70ba83ce5b9..00000000000
--- a/app/assets/javascripts/commit/pipelines/pipelines_table.js
+++ /dev/null
@@ -1,191 +0,0 @@
-import Vue from 'vue';
-import Visibility from 'visibilityjs';
-import pipelinesTableComponent from '../../vue_shared/components/pipelines_table.vue';
-import PipelinesService from '../../pipelines/services/pipelines_service';
-import PipelineStore from '../../pipelines/stores/pipelines_store';
-import eventHub from '../../pipelines/event_hub';
-import emptyState from '../../pipelines/components/empty_state.vue';
-import errorState from '../../pipelines/components/error_state.vue';
-import loadingIcon from '../../vue_shared/components/loading_icon.vue';
-import '../../lib/utils/common_utils';
-import '../../vue_shared/vue_resource_interceptor';
-import Poll from '../../lib/utils/poll';
-
-/**
- *
- * Uses `pipelines-table-component` to render Pipelines table with an API call.
- * Endpoint is provided in HTML and passed as `endpoint`.
- * We need a store to store the received environemnts.
- * We need a service to communicate with the server.
- *
- */
-
-export default Vue.component('pipelines-table', {
-
- components: {
- pipelinesTableComponent,
- errorState,
- emptyState,
- loadingIcon,
- },
-
- /**
- * Accesses the DOM to provide the needed data.
- * Returns the necessary props to render `pipelines-table-component` component.
- *
- * @return {Object}
- */
- data() {
- const store = new PipelineStore();
-
- return {
- endpoint: null,
- helpPagePath: null,
- store,
- state: store.state,
- isLoading: false,
- hasError: false,
- isMakingRequest: false,
- updateGraphDropdown: false,
- hasMadeRequest: false,
- };
- },
-
- computed: {
- shouldRenderErrorState() {
- return this.hasError && !this.isLoading;
- },
-
- /**
- * Empty state is only rendered if after the first request we receive no pipelines.
- *
- * @return {Boolean}
- */
- shouldRenderEmptyState() {
- return !this.state.pipelines.length &&
- !this.isLoading &&
- this.hasMadeRequest &&
- !this.hasError;
- },
-
- shouldRenderTable() {
- return !this.isLoading &&
- this.state.pipelines.length > 0 &&
- !this.hasError;
- },
- },
-
- /**
- * When the component is about to be mounted, tell the service to fetch the data
- *
- * A request to fetch the pipelines will be made.
- * In case of a successfull response we will store the data in the provided
- * store, in case of a failed response we need to warn the user.
- *
- */
- beforeMount() {
- const element = document.querySelector('#commit-pipeline-table-view');
-
- this.endpoint = element.dataset.endpoint;
- this.helpPagePath = element.dataset.helpPagePath;
- this.service = new PipelinesService(this.endpoint);
-
- this.poll = new Poll({
- resource: this.service,
- method: 'getPipelines',
- successCallback: this.successCallback,
- errorCallback: this.errorCallback,
- notificationCallback: this.setIsMakingRequest,
- });
-
- if (!Visibility.hidden()) {
- this.isLoading = true;
- this.poll.makeRequest();
- } else {
- // If tab is not visible we need to make the first request so we don't show the empty
- // state without knowing if there are any pipelines
- this.fetchPipelines();
- }
-
- Visibility.change(() => {
- if (!Visibility.hidden()) {
- this.poll.restart();
- } else {
- this.poll.stop();
- }
- });
-
- eventHub.$on('refreshPipelines', this.fetchPipelines);
- },
-
- beforeDestroy() {
- eventHub.$off('refreshPipelines');
- },
-
- destroyed() {
- this.poll.stop();
- },
-
- methods: {
- fetchPipelines() {
- this.isLoading = true;
-
- return this.service.getPipelines()
- .then(response => this.successCallback(response))
- .catch(() => this.errorCallback());
- },
-
- successCallback(resp) {
- const response = resp.json();
-
- this.hasMadeRequest = true;
-
- // depending of the endpoint the response can either bring a `pipelines` key or not.
- const pipelines = response.pipelines || response;
- this.store.storePipelines(pipelines);
- this.isLoading = false;
- this.updateGraphDropdown = true;
- },
-
- errorCallback() {
- this.hasError = true;
- this.isLoading = false;
- this.updateGraphDropdown = false;
- },
-
- setIsMakingRequest(isMakingRequest) {
- this.isMakingRequest = isMakingRequest;
-
- if (isMakingRequest) {
- this.updateGraphDropdown = false;
- }
- },
- },
-
- template: `
- <div class="content-list pipelines">
-
- <loading-icon
- label="Loading pipelines"
- size="3"
- v-if="isLoading"
- />
-
- <empty-state
- v-if="shouldRenderEmptyState"
- :help-page-path="helpPagePath" />
-
- <error-state v-if="shouldRenderErrorState" />
-
- <div
- class="table-holder"
- v-if="shouldRenderTable">
- <pipelines-table-component
- :pipelines="state.pipelines"
- :service="service"
- :update-graph-dropdown="updateGraphDropdown"
- />
- </div>
- </div>
- `,
-});
diff --git a/app/assets/javascripts/commit/pipelines/pipelines_table.vue b/app/assets/javascripts/commit/pipelines/pipelines_table.vue
new file mode 100644
index 00000000000..3c77f14d533
--- /dev/null
+++ b/app/assets/javascripts/commit/pipelines/pipelines_table.vue
@@ -0,0 +1,90 @@
+<script>
+ import PipelinesService from '../../pipelines/services/pipelines_service';
+ import PipelineStore from '../../pipelines/stores/pipelines_store';
+ import pipelinesMixin from '../../pipelines/mixins/pipelines';
+
+ export default {
+ props: {
+ endpoint: {
+ type: String,
+ required: true,
+ },
+ helpPagePath: {
+ type: String,
+ required: true,
+ },
+ },
+ mixins: [
+ pipelinesMixin,
+ ],
+
+ data() {
+ const store = new PipelineStore();
+
+ return {
+ store,
+ state: store.state,
+ };
+ },
+
+ computed: {
+ /**
+ * Empty state is only rendered if after the first request we receive no pipelines.
+ *
+ * @return {Boolean}
+ */
+ shouldRenderEmptyState() {
+ return !this.state.pipelines.length &&
+ !this.isLoading &&
+ this.hasMadeRequest &&
+ !this.hasError;
+ },
+
+ shouldRenderTable() {
+ return !this.isLoading &&
+ this.state.pipelines.length > 0 &&
+ !this.hasError;
+ },
+ },
+ created() {
+ this.service = new PipelinesService(this.endpoint);
+ },
+ methods: {
+ successCallback(resp) {
+ const response = resp.json();
+
+ // depending of the endpoint the response can either bring a `pipelines` key or not.
+ const pipelines = response.pipelines || response;
+ this.setCommonData(pipelines);
+ },
+ },
+ };
+</script>
+<template>
+ <div class="content-list pipelines">
+
+ <loading-icon
+ label="Loading pipelines"
+ size="3"
+ v-if="isLoading"
+ />
+
+ <empty-state
+ v-if="shouldRenderEmptyState"
+ :help-page-path="helpPagePath"
+ />
+
+ <error-state
+ v-if="shouldRenderErrorState"
+ />
+
+ <div
+ class="table-holder"
+ v-if="shouldRenderTable">
+ <pipelines-table-component
+ :pipelines="state.pipelines"
+ :update-graph-dropdown="updateGraphDropdown"
+ />
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/dispatcher.js b/app/assets/javascripts/dispatcher.js
index 5f87a05067b..88b4b567fa9 100644
--- a/app/assets/javascripts/dispatcher.js
+++ b/app/assets/javascripts/dispatcher.js
@@ -79,7 +79,18 @@ import initSettingsPanels from './settings_panels';
path = page.split(':');
shortcut_handler = null;
- new GfmAutoComplete(gl.GfmAutoComplete && gl.GfmAutoComplete.dataSources).setup();
+ $('.js-gfm-input').each((i, el) => {
+ const gfm = new GfmAutoComplete(gl.GfmAutoComplete && gl.GfmAutoComplete.dataSources);
+ const enableGFM = gl.utils.convertPermissionToBoolean(el.dataset.supportsAutocomplete);
+ gfm.setup($(el), {
+ emojis: true,
+ members: enableGFM,
+ issues: enableGFM,
+ milestones: enableGFM,
+ mergeRequests: enableGFM,
+ labels: enableGFM,
+ });
+ });
function initBlob() {
new LineHighlighter();
@@ -176,7 +187,7 @@ import initSettingsPanels from './settings_panels';
case 'groups:milestones:update':
new ZenMode();
new gl.DueDateSelectors();
- new gl.GLForm($('.milestone-form'));
+ new gl.GLForm($('.milestone-form'), true);
break;
case 'projects:compare:show':
new gl.Diff();
@@ -188,7 +199,7 @@ import initSettingsPanels from './settings_panels';
case 'projects:issues:new':
case 'projects:issues:edit':
shortcut_handler = new ShortcutsNavigation();
- new gl.GLForm($('.issue-form'));
+ new gl.GLForm($('.issue-form'), true);
new IssuableForm($('.issue-form'));
new LabelsSelect();
new MilestoneSelect();
@@ -199,7 +210,7 @@ import initSettingsPanels from './settings_panels';
case 'projects:merge_requests:edit':
new gl.Diff();
shortcut_handler = new ShortcutsNavigation();
- new gl.GLForm($('.merge-request-form'));
+ new gl.GLForm($('.merge-request-form'), true);
new IssuableForm($('.merge-request-form'));
new LabelsSelect();
new MilestoneSelect();
@@ -208,22 +219,24 @@ import initSettingsPanels from './settings_panels';
break;
case 'projects:tags:new':
new ZenMode();
- new gl.GLForm($('.tag-form'));
+ new gl.GLForm($('.tag-form'), true);
new RefSelectDropdown($('.js-branch-select'), window.gl.availableRefs);
break;
case 'projects:snippets:new':
case 'projects:snippets:edit':
case 'projects:snippets:create':
case 'projects:snippets:update':
+ new gl.GLForm($('.snippet-form'), true);
+ break;
case 'snippets:new':
case 'snippets:edit':
case 'snippets:create':
case 'snippets:update':
- new gl.GLForm($('.snippet-form'));
+ new gl.GLForm($('.snippet-form'), false);
break;
case 'projects:releases:edit':
new ZenMode();
- new gl.GLForm($('.release-form'));
+ new gl.GLForm($('.release-form'), true);
break;
case 'projects:merge_requests:show':
new gl.Diff();
@@ -471,7 +484,7 @@ import initSettingsPanels from './settings_panels';
new gl.Wikis();
shortcut_handler = new ShortcutsWiki();
new ZenMode();
- new gl.GLForm($('.wiki-form'));
+ new gl.GLForm($('.wiki-form'), true);
break;
case 'snippets':
shortcut_handler = new ShortcutsNavigation();
diff --git a/app/assets/javascripts/dropzone_input.js b/app/assets/javascripts/dropzone_input.js
index 98ddcc20036..73675d300be 100644
--- a/app/assets/javascripts/dropzone_input.js
+++ b/app/assets/javascripts/dropzone_input.js
@@ -287,6 +287,10 @@ window.DropzoneInput = (function() {
$uploadingErrorMessage.html(message);
};
+ closeAlertMessage = function() {
+ return form.find('.div-dropzone-alert').alert('close');
+ };
+
form.find('.markdown-selector').click(function(e) {
e.preventDefault();
$(this).closest('.gfm-form').find('.div-dropzone').click();
diff --git a/app/assets/javascripts/environments/components/environment_item.vue b/app/assets/javascripts/environments/components/environment_item.vue
index 809c147bf25..b25113e0fc6 100644
--- a/app/assets/javascripts/environments/components/environment_item.vue
+++ b/app/assets/javascripts/environments/components/environment_item.vue
@@ -403,6 +403,14 @@ export default {
return '';
},
+ displayEnvironmentActions() {
+ return this.hasManualActions ||
+ this.externalURL ||
+ this.monitoringUrl ||
+ this.hasStopAction ||
+ this.canRetry;
+ },
+
/**
* Constructs folder URL based on the current location and the folder id.
*
@@ -535,9 +543,12 @@ export default {
</span>
</div>
- <div class="table-section section-30 table-button-footer" role="gridcell">
+ <div
+ v-if="!model.isFolder && displayEnvironmentActions"
+ class="table-section section-30 table-button-footer"
+ role="gridcell">
+
<div
- v-if="!model.isFolder"
class="btn-group table-action-buttons"
role="group">
diff --git a/app/assets/javascripts/filtered_search/dropdown_hint.js b/app/assets/javascripts/filtered_search/dropdown_hint.js
index 2af242a69df..5838b1bdbb7 100644
--- a/app/assets/javascripts/filtered_search/dropdown_hint.js
+++ b/app/assets/javascripts/filtered_search/dropdown_hint.js
@@ -56,7 +56,7 @@ class DropdownHint extends gl.FilteredSearchDropdown {
}
renderContent() {
- const dropdownData = gl.FilteredSearchTokenKeys.get()
+ const dropdownData = this.tokenKeys.get()
.map(tokenKey => ({
icon: `fa-${tokenKey.icon}`,
hint: tokenKey.key,
diff --git a/app/assets/javascripts/filtered_search/filtered_search_manager.js b/app/assets/javascripts/filtered_search/filtered_search_manager.js
index 8f547bd8f1f..c7c8d42e677 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_manager.js
+++ b/app/assets/javascripts/filtered_search/filtered_search_manager.js
@@ -487,6 +487,7 @@ class FilteredSearchManager {
}
searchState(e) {
+ e.preventDefault();
const target = e.currentTarget;
// remove focus outline after click
target.blur();
diff --git a/app/assets/javascripts/gfm_auto_complete.js b/app/assets/javascripts/gfm_auto_complete.js
index 401dec1a370..105762cb1ba 100644
--- a/app/assets/javascripts/gfm_auto_complete.js
+++ b/app/assets/javascripts/gfm_auto_complete.js
@@ -34,7 +34,7 @@ class GfmAutoComplete {
const $input = $(input);
$input.off('focus.setupAtWho').on('focus.setupAtWho', this.setupAtWho.bind(this, $input));
// This triggers at.js again
- // Needed for slash commands with suffixes (ex: /label ~)
+ // Needed for quick actions with suffixes (ex: /label ~)
$input.on('inserted-commands.atwho', $input.trigger.bind($input, 'keyup'));
$input.on('clear-commands-cache.atwho', () => this.clearCache());
});
@@ -48,8 +48,8 @@ class GfmAutoComplete {
if (this.enableMap.mergeRequests) this.setupMergeRequests($input);
if (this.enableMap.labels) this.setupLabels($input);
- // We don't instantiate the slash commands autocomplete for note and issue/MR edit forms
- $input.filter('[data-supports-slash-commands="true"]').atwho({
+ // We don't instantiate the quick actions autocomplete for note and issue/MR edit forms
+ $input.filter('[data-supports-quick-actions="true"]').atwho({
at: '/',
alias: 'commands',
searchKey: 'search',
diff --git a/app/assets/javascripts/issuable_bulk_update_sidebar.js b/app/assets/javascripts/issuable_bulk_update_sidebar.js
index 84bd2e092e6..a8856120c5e 100644
--- a/app/assets/javascripts/issuable_bulk_update_sidebar.js
+++ b/app/assets/javascripts/issuable_bulk_update_sidebar.js
@@ -22,6 +22,7 @@ export default class IssuableBulkUpdateSidebar {
initDomElements() {
this.$page = $('.page-with-sidebar');
this.$sidebar = $('.right-sidebar');
+ this.$sidebarInnerContainer = this.$sidebar.find('.issuable-sidebar');
this.$bulkEditCancelBtn = $('.js-bulk-update-menu-hide');
this.$bulkEditSubmitBtn = $('.update-selected-issues');
this.$bulkUpdateEnableBtn = $('.js-bulk-update-toggle');
@@ -113,6 +114,7 @@ export default class IssuableBulkUpdateSidebar {
toggleSidebarDisplay(show) {
this.$page.toggleClass(SIDEBAR_EXPANDED_CLASS, show);
this.$page.toggleClass(SIDEBAR_COLLAPSED_CLASS, !show);
+ this.$sidebarInnerContainer.toggleClass(HIDDEN_CLASS, !show);
this.$sidebar.toggleClass(SIDEBAR_EXPANDED_CLASS, show);
this.$sidebar.toggleClass(SIDEBAR_COLLAPSED_CLASS, !show);
}
diff --git a/app/assets/javascripts/issue_show/components/app.vue b/app/assets/javascripts/issue_show/components/app.vue
index e14414d3f68..3d5fb7f441c 100644
--- a/app/assets/javascripts/issue_show/components/app.vue
+++ b/app/assets/javascripts/issue_show/components/app.vue
@@ -51,6 +51,11 @@ export default {
required: false,
default: '',
},
+ initialTaskStatus: {
+ type: String,
+ required: false,
+ default: '',
+ },
updatedAt: {
type: String,
required: false,
@@ -105,6 +110,7 @@ export default {
updatedAt: this.updatedAt,
updatedByName: this.updatedByName,
updatedByPath: this.updatedByPath,
+ taskStatus: this.initialTaskStatus,
});
return {
@@ -198,13 +204,7 @@ export default {
method: 'getData',
successCallback: (res) => {
const data = res.json();
- const shouldUpdate = this.store.stateShouldUpdate(data);
-
this.store.updateState(data);
-
- if (this.showForm && (shouldUpdate.title || shouldUpdate.description)) {
- this.store.formState.lockedWarningVisible = true;
- }
},
errorCallback(err) {
throw new Error(err);
diff --git a/app/assets/javascripts/issue_show/components/description.vue b/app/assets/javascripts/issue_show/components/description.vue
index 5ae617356e0..43db66c8e08 100644
--- a/app/assets/javascripts/issue_show/components/description.vue
+++ b/app/assets/javascripts/issue_show/components/description.vue
@@ -37,23 +37,12 @@
});
},
taskStatus() {
- const taskRegexMatches = this.taskStatus.match(/(\d+) of (\d+)/);
- const $issuableHeader = $('.issuable-meta');
- const $tasks = $('#task_status', $issuableHeader);
- const $tasksShort = $('#task_status_short', $issuableHeader);
-
- if (taskRegexMatches) {
- $tasks.text(this.taskStatus);
- $tasksShort.text(`${taskRegexMatches[1]}/${taskRegexMatches[2]} task${taskRegexMatches[2] > 1 ? 's' : ''}`);
- } else {
- $tasks.text('');
- $tasksShort.text('');
- }
+ this.updateTaskStatusText();
},
},
methods: {
renderGFM() {
- $(this.$refs['gfm-entry-content']).renderGFM();
+ $(this.$refs['gfm-content']).renderGFM();
if (this.canUpdate) {
// eslint-disable-next-line no-new
@@ -64,9 +53,24 @@
});
}
},
+ updateTaskStatusText() {
+ const taskRegexMatches = this.taskStatus.match(/(\d+) of ((?!0)\d+)/);
+ const $issuableHeader = $('.issuable-meta');
+ const $tasks = $('#task_status', $issuableHeader);
+ const $tasksShort = $('#task_status_short', $issuableHeader);
+
+ if (taskRegexMatches) {
+ $tasks.text(this.taskStatus);
+ $tasksShort.text(`${taskRegexMatches[1]}/${taskRegexMatches[2]} task${taskRegexMatches[2] > 1 ? 's' : ''}`);
+ } else {
+ $tasks.text('');
+ $tasksShort.text('');
+ }
+ },
},
mounted() {
this.renderGFM();
+ this.updateTaskStatusText();
},
};
</script>
diff --git a/app/assets/javascripts/issue_show/components/fields/description.vue b/app/assets/javascripts/issue_show/components/fields/description.vue
index 30a1be5cb50..54650d2f184 100644
--- a/app/assets/javascripts/issue_show/components/fields/description.vue
+++ b/app/assets/javascripts/issue_show/components/fields/description.vue
@@ -41,7 +41,7 @@
<textarea
id="issue-description"
class="note-textarea js-gfm-input js-autosize markdown-area"
- data-supports-slash-commands="false"
+ data-supports-quick-actionss="false"
aria-label="Description"
v-model="formState.description"
ref="textarea"
diff --git a/app/assets/javascripts/issue_show/index.js b/app/assets/javascripts/issue_show/index.js
index 14b2a1e18e9..ad8cb6465e2 100644
--- a/app/assets/javascripts/issue_show/index.js
+++ b/app/assets/javascripts/issue_show/index.js
@@ -45,6 +45,7 @@ document.addEventListener('DOMContentLoaded', () => {
updatedAt: this.updatedAt,
updatedByName: this.updatedByName,
updatedByPath: this.updatedByPath,
+ initialTaskStatus: this.initialTaskStatus,
},
});
},
diff --git a/app/assets/javascripts/issue_show/stores/index.js b/app/assets/javascripts/issue_show/stores/index.js
index 27c2d349f52..0c8bd6f1cc3 100644
--- a/app/assets/javascripts/issue_show/stores/index.js
+++ b/app/assets/javascripts/issue_show/stores/index.js
@@ -1,23 +1,6 @@
export default class Store {
- constructor({
- titleHtml,
- titleText,
- descriptionHtml,
- descriptionText,
- updatedAt,
- updatedByName,
- updatedByPath,
- }) {
- this.state = {
- titleHtml,
- titleText,
- descriptionHtml,
- descriptionText,
- taskStatus: '',
- updatedAt,
- updatedByName,
- updatedByPath,
- };
+ constructor(initialState) {
+ this.state = initialState;
this.formState = {
title: '',
confidential: false,
@@ -29,6 +12,10 @@ export default class Store {
}
updateState(data) {
+ if (this.stateShouldUpdate(data)) {
+ this.formState.lockedWarningVisible = true;
+ }
+
this.state.titleHtml = data.title;
this.state.titleText = data.title_text;
this.state.descriptionHtml = data.description;
@@ -40,10 +27,8 @@ export default class Store {
}
stateShouldUpdate(data) {
- return {
- title: this.state.titleText !== data.title_text,
- description: this.state.descriptionText !== data.description_text,
- };
+ return this.state.titleText !== data.title_text ||
+ this.state.descriptionText !== data.description_text;
}
setFormState(state) {
diff --git a/app/assets/javascripts/lib/utils/datetime_utility.js b/app/assets/javascripts/lib/utils/datetime_utility.js
index 54c0da3fc9c..bfcc50996cc 100644
--- a/app/assets/javascripts/lib/utils/datetime_utility.js
+++ b/app/assets/javascripts/lib/utils/datetime_utility.js
@@ -34,7 +34,7 @@ window.dateFormat = dateFormat;
w.gl.utils.localTimeAgo = function($timeagoEls, setTimeago = true) {
$timeagoEls.each((i, el) => {
- el.setAttribute('title', gl.utils.formatDate(el.getAttribute('datetime')));
+ el.setAttribute('title', el.getAttribute('title'));
if (setTimeago) {
// Recreate with custom template
diff --git a/app/assets/javascripts/locale/en/app.js b/app/assets/javascripts/locale/en/app.js
index 0bb76c80b7a..d634af959e5 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;"},"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
+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;"},"%{commit_author_link} committed %{commit_timeago}":[""],"About auto deploy":[""],"Active":[""],"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?":[""],"Attach a file by drag &amp; drop or %{upload_link}":[""],"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":[""],"Browse files":[""],"ByAuthor|by":[""],"CI configuration":[""],"Cancel":[""],"ChangeTypeActionLabel|Pick into branch":[""],"ChangeTypeActionLabel|Revert in branch":[""],"ChangeTypeAction|Cherry-pick":[""],"Changelog":[""],"Charts":[""],"Cherry-pick this commit":[""],"Cherry-pick this merge request":[""],"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 message":[""],"CommitBoxTitle|Commit":[""],"CommitMessage|Add %{file_name}":[""],"Commits":[""],"Commits|History":[""],"Committed by":[""],"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":[""],"Create new...":[""],"CreateNewFork|Fork":[""],"CreateTag|Tag":[""],"Cron Timezone":[""],"Cron syntax":[""],"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":[""],"Define a custom pattern with cron syntax":[""],"Delete":[""],"Deploy":["",""],"Description":[""],"Directory name":[""],"Don't show again":[""],"Download":[""],"Download tar":[""],"Download tar.bz2":[""],"Download tar.gz":[""],"Download zip":[""],"DownloadArtifacts|Download":[""],"DownloadCommit|Email Patches":[""],"DownloadCommit|Plain Diff":[""],"DownloadSource|Download":[""],"Edit":[""],"Edit Pipeline Schedule %{id}":[""],"Every day (at 4:00am)":[""],"Every month (on the 1st at 4:00am)":[""],"Every week (Sundays at 4:00am)":[""],"Failed to change the owner":[""],"Failed to remove the pipeline schedule":[""],"Files":[""],"Find by path":[""],"Find file":[""],"FirstPushedBy|First":[""],"FirstPushedBy|pushed by":[""],"Fork":["",""],"ForkedFromProjectPath|Forked from":[""],"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":[""],"Learn more in the":[""],"Learn more in the|pipeline schedules documentation":[""],"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 schedule":[""],"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":[""],"OfSearchInADropdown|Filter":[""],"OpenedNDaysAgo|Opened":[""],"Options":[""],"Owner":[""],"Pipeline":[""],"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":[""],"PipelineSheduleIntervalPattern|Custom":[""],"Pipeline|with stage":[""],"Pipeline|with stages":[""],"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":[""],"Revert this commit":[""],"Revert this merge request":[""],"Save pipeline schedule":[""],"Schedule a new pipeline":[""],"Scheduling Pipelines":[""],"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":[""],"Start a %{new_merge_request} with these changes":[""],"Start a <strong>new merge request</strong> with these changes":[""],"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 pipelines schedule runs pipelines in the future, repeatedly, for specific branches or tags. Those scheduled pipelines will inherit limited project access based on their associated user.":[""],"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":[""],"day":["",""],"new merge request":[""],"notification emails":[""],"parent":["",""]}}}; \ 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 6977625f4d8..eafcd15acf9 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-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
+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-15 21:59-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","POT-Creation-Date":"2017-06-15 21:59-0500","lang":"es","domain":"app","plural_forms":"nplurals=2; plural=n != 1;"},"%{commit_author_link} committed %{commit_timeago}":["%{commit_author_link} cambió %{commit_timeago}"],"About auto deploy":["Acerca del auto despliegue"],"Active":["Activo"],"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 solo lectura"],"Are you sure you want to delete this pipeline schedule?":["¿Estás seguro que deseas eliminar esta programación del pipeline?"],"Attach a file by drag &amp; drop or %{upload_link}":["Adjunte un archivo arrastrando &amp; soltando o %{upload_link}"],"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"],"Browse files":["Examinar los archivos"],"ByAuthor|by":["por"],"CI configuration":["Configuración de CI"],"Cancel":["Cancelar"],"ChangeTypeActionLabel|Pick into branch":["Escoger en la rama"],"ChangeTypeActionLabel|Revert in branch":["Revertir en la rama"],"ChangeTypeAction|Cherry-pick":["Cherry-pick"],"ChangeTypeAction|Revert":["Revertir"],"Changelog":["Changelog"],"Charts":["Gráficos"],"Cherry-pick this commit":["Escoger este cambio"],"Cherry-pick this merge request":["Escoger esta solicitud de fusión"],"CiStatusLabel|canceled":["cancelado"],"CiStatusLabel|created":["creado"],"CiStatusLabel|failed":["fallido"],"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"],"Commit message":["Mensaje del cambio"],"CommitBoxTitle|Commit":["Cambio"],"CommitMessage|Add %{file_name}":["Agregar %{file_name}"],"Commits":["Cambios"],"Commits|History":["Historial"],"Committed by":["Enviado por"],"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"],"Create new...":["Crear nuevo..."],"CreateNewFork|Fork":["Bifurcar"],"CreateTag|Tag":["Etiqueta"],"Cron Timezone":["Zona horaria del Cron"],"Cron syntax":["Sintaxis de Cron"],"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"],"Define a custom pattern with cron syntax":["Definir un patrón personalizado con la sintaxis de cron"],"Delete":["Eliminar"],"Deploy":["Despliegue","Despliegues"],"Description":["Descripción"],"Directory name":["Nombre del directorio"],"Don't show again":["No mostrar de nuevo"],"Download":["Descargar"],"Download tar":["Descargar tar"],"Download tar.bz2":["Descargar tar.bz2"],"Download tar.gz":["Descargar tar.gz"],"Download zip":["Descargar zip"],"DownloadArtifacts|Download":["Descargar"],"DownloadCommit|Email Patches":["Parches por correo electrónico"],"DownloadCommit|Plain Diff":["Diferencias en texto plano"],"DownloadSource|Download":["Descargar"],"Edit":["Editar"],"Edit Pipeline Schedule %{id}":["Editar Programación del Pipeline %{id}"],"Every day (at 4:00am)":["Todos los días (a las 4:00 am)"],"Every month (on the 1st at 4:00am)":["Todos los meses (el día 1 a las 4:00 am)"],"Every week (Sundays at 4:00am)":["Todas las semanas (domingos a las 4:00 am)"],"Failed to change the owner":["Error al cambiar el propietario"],"Failed to remove the pipeline schedule":["Error al eliminar la programación del pipeline"],"Files":["Archivos"],"Find by path":["Buscar por ruta"],"Find file":["Buscar archivo"],"FirstPushedBy|First":["Primer"],"FirstPushedBy|pushed by":["enviado por"],"Fork":["Bifurcación","Bifurcaciones"],"ForkedFromProjectPath|Forked from":["Bifurcado de"],"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"],"Interval Pattern":["Patrón de intervalo"],"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 Pipeline":["Último Pipeline"],"Last Update":["Última actualización"],"Last commit":["Último cambio"],"Learn more in the":["Más información en la"],"Learn more in the|pipeline schedules documentation":["documentación sobre la programación de pipelines"],"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 Pipeline Schedule":["Nueva Programación del Pipeline"],"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 schedule":["Nueva programación"],"New snippet":["Nuevo fragmento de código"],"New tag":["Nueva etiqueta"],"No repository":["No hay repositorio"],"No schedules":["No hay programaciones"],"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"],"OfSearchInADropdown|Filter":["Filtrar"],"OpenedNDaysAgo|Opened":["Abierto"],"Options":["Opciones"],"Owner":["Propietario"],"Pipeline":["Pipeline"],"Pipeline Health":["Estado del Pipeline"],"Pipeline Schedule":["Programación del Pipeline"],"Pipeline Schedules":["Programaciones de los Pipelines"],"PipelineSchedules|Activated":["Activado"],"PipelineSchedules|Active":["Activos"],"PipelineSchedules|All":["Todos"],"PipelineSchedules|Inactive":["Inactivos"],"PipelineSchedules|Next Run":["Próxima Ejecución"],"PipelineSchedules|None":["Ninguno"],"PipelineSchedules|Provide a short description for this pipeline":["Proporcione una breve descripción para este pipeline"],"PipelineSchedules|Take ownership":["Tomar posesión"],"PipelineSchedules|Target":["Destino"],"PipelineSheduleIntervalPattern|Custom":["Personalizado"],"Pipeline|with stage":["con etapa"],"Pipeline|with stages":["con etapas"],"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":["Léeme"],"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"],"Revert this commit":["Revertir este cambio"],"Revert this merge request":["Revertir esta solicitud de fusión"],"Save pipeline schedule":["Guardar programación del pipeline"],"Schedule a new pipeline":["Programar un nuevo pipeline"],"Scheduling Pipelines":["Programación de Pipelines"],"Search branches and tags":["Buscar ramas y etiquetas"],"Select Archive Format":["Seleccionar formato de archivo"],"Select a timezone":["Selecciona una zona horaria"],"Select target branch":["Selecciona una rama de destino"],"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"],"Start a %{new_merge_request} with these changes":["Iniciar una %{new_merge_request} con estos cambios"],"Switch branch/tag":["Cambiar rama/etiqueta"],"Tag":["Etiqueta","Etiquetas"],"Tags":["Etiquetas"],"Target Branch":["Rama de destino"],"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 pipelines schedule runs pipelines in the future, repeatedly, for specific branches or tags. Those scheduled pipelines will inherit limited project access based on their associated user.":["La programación de pipelines ejecuta pipelines en el futuro, repetidamente, para ramas o etiquetas específicas. Los pipelines programados heredarán acceso limitado al proyecto basado en su usuario asociado."],"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 un mes"],"Timeago|a week ago":["hace una semana"],"Timeago|a while":["hace un momento"],"Timeago|a year ago":["hace un 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":["Solo puedes agregar archivos cuando estás 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 por cualquier actividad"],"You will receive notifications only for comments in which you were @mentioned":["Recibirás notificaciones solo 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"],"day":["día","días"],"new merge request":["nueva solicitud de fusión"],"notification emails":["correos electrónicos de notificación"],"parent":["padre","padres"]}}}; \ 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 d1335cfbc0f..9c28e4e4627 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;"},"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
+var locales = locales || {}; locales['zh_CN'] = {"domain":"app","locale_data":{"app":{"":{"Project-Id-Version":"gitlab 1.0.0","Report-Msgid-Bugs-To":"","POT-Creation-Date":"2017-06-15 21:59-0500","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","PO-Revision-Date":"2017-06-19 09:57-0400","Last-Translator":"Huang Tao <htve@outlook.com>","Language-Team":"Chinese (China) (https://translate.zanata.org/project/view/GitLab)","Language":"zh-CN","X-Generator":"Zanata 3.9.6","Plural-Forms":"nplurals=1; plural=0","lang":"zh_CN","domain":"app","plural_forms":"nplurals=1; plural=0"},"%{commit_author_link} committed %{commit_timeago}":["由 %{commit_author_link} 提交于 %{commit_timeago}"],"About auto deploy":["关于自动部署"],"Active":["启用"],"Activity":["活动"],"Add Changelog":["添加更新日志"],"Add Contribution guide":["添加贡献指南"],"Add License":["添加许可证"],"Add an SSH key to your profile to pull or push via SSH.":["新建一个用于推送或拉取的 SSH 秘钥到账号中。"],"Add new directory":["添加目录"],"Archived project! Repository is read-only":["项目已归档!存储库为只读状态"],"Are you sure you want to delete this pipeline schedule?":["确定要删除此流水线计划吗?"],"Attach a file by drag &amp; drop or %{upload_link}":["拖放文件到此处或者 %{upload_link}"],"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}":["已创建分支 <strong>%{branch_name}</strong> 。如需设置自动部署, 请选择合适的 GitLab CI Yaml 模板并提交更改。%{link_to_autodeploy_doc}"],"Branches":["分支"],"Browse files":["浏览文件"],"ByAuthor|by":["作者:"],"CI configuration":["CI 配置"],"Cancel":["取消"],"ChangeTypeActionLabel|Pick into branch":["选择分支"],"ChangeTypeActionLabel|Revert in branch":["还原分支"],"ChangeTypeAction|Cherry-pick":["优选"],"ChangeTypeAction|Revert":["还原"],"Changelog":["更新日志"],"Charts":["统计图"],"Cherry-pick this commit":["优选此提交"],"Cherry-pick this merge request":["优选此合并请求"],"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 message":["提交信息"],"CommitBoxTitle|Commit":["提交"],"CommitMessage|Add %{file_name}":["添加 %{file_name}"],"Commits":["提交"],"Commits|History":["历史"],"Committed by":["提交者:"],"Compare":["比较"],"Contribution guide":["贡献指南"],"Contributors":["贡献者"],"Copy URL to clipboard":["复制 URL 到剪贴板"],"Copy commit SHA to clipboard":["复制提交 SHA 的值到剪贴板"],"Create New Directory":["创建新目录"],"Create directory":["创建目录"],"Create empty bare repository":["创建空的存储库"],"Create merge request":["创建合并请求"],"Create new...":["创建..."],"CreateNewFork|Fork":["派生"],"CreateTag|Tag":["标签"],"Cron Timezone":["Cron 时区"],"Cron syntax":["Cron 语法"],"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}.":["自定义通知级别继承自参与级别。使用自定义通知级别,您会收到参与级别及选定事件的通知。想了解更多信息,请查看 %{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":["测试"],"Define a custom pattern with cron syntax":["使用 Cron 语法定义自定义模式"],"Delete":["删除"],"Deploy":["部署"],"Description":["描述"],"Directory name":["目录名称"],"Don't show again":["不再显示"],"Download":["下载"],"Download tar":["下载 tar"],"Download tar.bz2":["下载 tar.bz2"],"Download tar.gz":["下载 tar.gz"],"Download zip":["下载 zip"],"DownloadArtifacts|Download":["下载"],"DownloadCommit|Email Patches":["电子邮件补丁"],"DownloadCommit|Plain Diff":["差异文件"],"DownloadSource|Download":["下载"],"Edit":["编辑"],"Edit Pipeline Schedule %{id}":["编辑 %{id} 流水线计划"],"Every day (at 4:00am)":["每日执行(凌晨 4 点)"],"Every month (on the 1st at 4:00am)":["每月执行(每月 1 日凌晨 4 点)"],"Every week (Sundays at 4:00am)":["每周执行(周日凌晨 4 点)"],"Failed to change the owner":["无法变更所有者"],"Failed to remove the pipeline schedule":["无法删除流水线计划"],"Files":["文件"],"Find by path":["按路径查找"],"Find file":["查找文件"],"FirstPushedBy|First":["首次推送"],"FirstPushedBy|pushed by":["推送者:"],"Fork":["派生"],"ForkedFromProjectPath|Forked from":["派生自"],"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":["最后提交"],"Learn more in the":["了解更多"],"Learn more in the|pipeline schedules documentation":["流水线计划文档"],"Leave group":["退出群组"],"Leave project":["退出项目"],"Limited to showing %d event at most":["最多显示 %d 个事件"],"Median":["中位数"],"MissingSSHKeyWarningLink|add an SSH key":["新建 SSH 公钥"],"New Issue":["新建议题"],"New Pipeline Schedule":["创建流水线计划"],"New branch":["新建分支"],"New directory":["新建目录"],"New file":["新建文件"],"New issue":["新建议题"],"New merge request":["新建合并请求"],"New schedule":["新建计划"],"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":["关注"],"OfSearchInADropdown|Filter":["筛选"],"OpenedNDaysAgo|Opened":["开始于"],"Options":["操作"],"Owner":["所有者"],"Pipeline":["流水线"],"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":["目标"],"PipelineSheduleIntervalPattern|Custom":["自定义"],"Pipeline|with stage":["于阶段"],"Pipeline|with stages":["于阶段"],"Project '%{project_name}' queued for deletion.":["项目 '%{project_name}' 已进入删除队列。"],"Project '%{project_name}' was successfully created.":["项目 '%{project_name}' 已创建成功。"],"Project '%{project_name}' was successfully updated.":["项目 '%{project_name}' 已更新完成。"],"Project '%{project_name}' will be deleted.":["项目 '%{project_name}' 将被删除。"],"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":["申请权限"],"Revert this commit":["还原此提交"],"Revert this merge request":["还原此合并请求"],"Save pipeline schedule":["保存流水线计划"],"Schedule a new pipeline":["新建流水线计划"],"Scheduling Pipelines":["流水线计划"],"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}":["为账号创建一个用于推送或拉取的 %{protocol} 密码。"],"Set up CI":["设置 CI"],"Set up Koding":["设置 Koding"],"Set up auto deploy":["设置自动部署"],"SetPasswordToCloneLink|set a password":["设置密码"],"Showing %d event":["显示 %d 个事件"],"Source code":["源代码"],"StarProject|Star":["星标"],"Start a %{new_merge_request} with these changes":["由此更改 %{new_merge_request}"],"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 pipelines schedule runs pipelines in the future, repeatedly, for specific branches or tags. Those scheduled pipelines will inherit limited project access based on their associated user.":["流水线计划会周期性重复运行指定分支或标签的流水线。这些流水线将根据其关联用户继承有限的项目访问权限。"],"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":[" %s 天前"],"Timeago|%s days remaining":["剩余 %s 天"],"Timeago|%s hours remaining":["剩余 %s 小时"],"Timeago|%s minutes ago":[" %s 分钟前"],"Timeago|%s minutes remaining":["剩余 %s 分钟"],"Timeago|%s months ago":[" %s 个月前"],"Timeago|%s months remaining":["剩余 %s 月"],"Timeago|%s seconds remaining":["剩余 %s 秒"],"Timeago|%s weeks ago":[" %s 星期前"],"Timeago|%s weeks remaining":["剩余 %s 星期"],"Timeago|%s years ago":[" %s 年前"],"Timeago|%s years remaining":["剩余 %s 年"],"Timeago|1 day remaining":["剩余 1 天"],"Timeago|1 hour remaining":["剩余 1 小时"],"Timeago|1 minute remaining":["剩余 1 分钟"],"Timeago|1 month remaining":["剩余 1 个月"],"Timeago|1 week remaining":["剩余 1 星期"],"Timeago|1 year remaining":["剩余 1 年"],"Timeago|Past due":["逾期"],"Timeago|a day ago":[" 1 天前"],"Timeago|a month ago":[" 1 个月前"],"Timeago|a week ago":[" 1 星期前"],"Timeago|a while":["刚刚"],"Timeago|a year ago":[" 1 年前"],"Timeago|about %s hours ago":["约 %s 小时前"],"Timeago|about a minute ago":["约 1 分钟前"],"Timeago|about an hour ago":["约 1 小时前"],"Timeago|in %s days":[" %s 天后"],"Timeago|in %s hours":[" %s 小时后"],"Timeago|in %s minutes":[" %s 分钟后"],"Timeago|in %s months":[" %s 个月后"],"Timeago|in %s seconds":[" %s 秒后"],"Timeago|in %s weeks":[" %s 星期后"],"Timeago|in %s years":[" %s 年后"],"Timeago|in 1 day":[" 1 天后"],"Timeago|in 1 hour":[" 1 小时后"],"Timeago|in 1 minute":[" 1 分钟后"],"Timeago|in 1 month":[" 1 月后"],"Timeago|in 1 week":[" 1 星期后"],"Timeago|in 1 year":[" 1 年后"],"Timeago|less than a minute ago":["不到 1 分钟前"],"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?":["即将要删除 %{project_name_with_namespace}。\\n已删除的项目无法恢复!\\n确定继续吗?"],"You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?":["即将删除与源项目 %{forked_from_project} 的派生关系。确定继续吗?"],"You are going to transfer %{project_name_with_namespace} to another owner. Are you ABSOLUTELY sure?":["即将 %{project_name_with_namespace} 转移给另一个所有者。确定继续吗?"],"You can only add files when you are on a branch":["只能在分支上添加文件"],"You have reached your project limit":["您已达到项目数量限制"],"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":["在账号中 %{set_password_link} 之前将无法通过 %{protocol} 拉取或推送代码。"],"You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile":["在账号中 %{add_ssh_key_link} 之前将无法通过 SSH 拉取或推送代码。"],"Your name":["您的名字"],"day":["天"],"new merge request":["新建合并请求"],"notification emails":["通知邮件"],"parent":["父级"]}}}; \ No newline at end of file
diff --git a/app/assets/javascripts/merge_request_tabs.js b/app/assets/javascripts/merge_request_tabs.js
index 894ed81b044..7bb2236017e 100644
--- a/app/assets/javascripts/merge_request_tabs.js
+++ b/app/assets/javascripts/merge_request_tabs.js
@@ -233,11 +233,18 @@ import BlobForkSuggestion from './blob/blob_fork_suggestion';
}
mountPipelinesView() {
- this.commitPipelinesTable = new gl.CommitPipelinesTable().$mount();
+ const pipelineTableViewEl = document.querySelector('#commit-pipeline-table-view');
+ const CommitPipelinesTable = gl.CommitPipelinesTable;
+ this.commitPipelinesTable = new CommitPipelinesTable({
+ propsData: {
+ endpoint: pipelineTableViewEl.dataset.endpoint,
+ helpPagePath: pipelineTableViewEl.dataset.helpPagePath,
+ },
+ }).$mount();
+
// $mount(el) replaces the el with the new rendered component. We need it in order to mount
// it everytime this tab is clicked - https://vuejs.org/v2/api/#vm-mount
- document.querySelector('#commit-pipeline-table-view')
- .appendChild(this.commitPipelinesTable.$el);
+ pipelineTableViewEl.appendChild(this.commitPipelinesTable.$el);
}
loadDiff(source) {
diff --git a/app/assets/javascripts/milestone.js b/app/assets/javascripts/milestone.js
index 07ede5ee913..3e07ec4d0aa 100644
--- a/app/assets/javascripts/milestone.js
+++ b/app/assets/javascripts/milestone.js
@@ -4,87 +4,7 @@
(function() {
this.Milestone = (function() {
- Milestone.updateIssue = function(li, issue_url, data) {
- return $.ajax({
- type: "PUT",
- url: issue_url,
- data: data,
- success: function(_data) {
- return Milestone.successCallback(_data, li);
- },
- error: function(data) {
- return new Flash("Issue update failed", 'alert');
- },
- dataType: "json"
- });
- };
-
- Milestone.sortIssues = function(url, data) {
- return $.ajax({
- type: "PUT",
- url,
- data: data,
- success: function(_data) {
- return Milestone.successCallback(_data);
- },
- error: function() {
- return new Flash("Issues update failed", 'alert');
- },
- dataType: "json"
- });
- };
-
- Milestone.sortMergeRequests = function(url, data) {
- return $.ajax({
- type: "PUT",
- url,
- data: data,
- success: function(_data) {
- return Milestone.successCallback(_data);
- },
- error: function(data) {
- return new Flash("Issue update failed", 'alert');
- },
- dataType: "json"
- });
- };
-
- Milestone.updateMergeRequest = function(li, merge_request_url, data) {
- return $.ajax({
- type: "PUT",
- url: merge_request_url,
- data: data,
- success: function(_data) {
- return Milestone.successCallback(_data, li);
- },
- error: function(data) {
- return new Flash("Issue update failed", 'alert');
- },
- dataType: "json"
- });
- };
-
- Milestone.successCallback = function(data, element) {
- const $avatarContainer = $(element).find('.assignee-icon');
- $avatarContainer.empty();
-
- if (data.assignees && data.assignees.length > 0) {
- const $avatars = data.assignees.map((assignee) => {
- const img_tag = $('<img/>');
- img_tag.attr('src', assignee.avatar_url);
- img_tag.addClass('avatar s16');
- return img_tag;
- });
-
- $avatarContainer.append($avatars);
- }
- };
-
function Milestone() {
- this.issuesSortEndpoint = $('#tab-issues').data('sort-endpoint');
- this.mergeRequestsSortEndpoint = $('#tab-merge-requests').data('sort-endpoint');
-
- this.bindIssuesSorting();
this.bindTabsSwitching();
// Load merge request tab if it is active
@@ -94,22 +14,6 @@
this.loadInitialTab();
}
- Milestone.prototype.bindIssuesSorting = function() {
- if (!this.issuesSortEndpoint) return;
-
- $('#issues-list-unassigned, #issues-list-ongoing, #issues-list-closed').each(function (i, el) {
- this.createSortable(el, {
- group: 'issue-list',
- listEls: $('.issues-sortable-list'),
- fieldName: 'issue',
- sortCallback: (data) => {
- Milestone.sortIssues(this.issuesSortEndpoint, data);
- },
- updateCallback: Milestone.updateIssue,
- });
- }.bind(this));
- };
-
Milestone.prototype.bindTabsSwitching = function() {
return $('a[data-toggle="tab"]').on('show.bs.tab', (e) => {
const $target = $(e.target);
@@ -119,69 +23,6 @@
});
};
- Milestone.prototype.bindMergeRequestSorting = function() {
- if (!this.mergeRequestsSortEndpoint) return;
-
- $("#merge_requests-list-unassigned, #merge_requests-list-ongoing, #merge_requests-list-closed").each(function (i, el) {
- this.createSortable(el, {
- group: 'merge-request-list',
- listEls: $(".merge_requests-sortable-list:not(#merge_requests-list-merged)"),
- fieldName: 'merge_request',
- sortCallback: (data) => {
- Milestone.sortMergeRequests(this.mergeRequestsSortEndpoint, data);
- },
- updateCallback: Milestone.updateMergeRequest,
- });
- }.bind(this));
- };
-
- Milestone.prototype.createSortable = function(el, opts) {
- return Sortable.create(el, {
- group: opts.group,
- filter: '.is-disabled',
- forceFallback: true,
- onStart: function(e) {
- opts.listEls.css('min-height', e.item.offsetHeight);
- },
- onEnd: function () {
- opts.listEls.css("min-height", "0px");
- },
- onUpdate: function(e) {
- var ids = this.toArray(),
- data;
-
- if (ids.length) {
- data = ids.map(function(id) {
- return 'sortable_' + opts.fieldName + '[]=' + id;
- }).join('&');
-
- opts.sortCallback(data);
- }
- },
- onAdd: function (e) {
- var data, issuableId, issuableUrl, newState;
- newState = e.to.dataset.state;
- issuableUrl = e.item.dataset.url;
- data = (function() {
- switch (newState) {
- case 'ongoing':
- return `${opts.fieldName}[assignee_ids][]=${gon.current_user_id}`;
- case 'unassigned':
- return `${opts.fieldName}[assignee_ids][]=0`;
- case 'closed':
- return opts.fieldName + '[state_event]=close';
- }
- })();
- if (e.from.dataset.state === 'closed') {
- data += '&' + opts.fieldName + '[state_event]=reopen';
- }
-
- opts.updateCallback(e.item, issuableUrl, data);
- this.options.onUpdate.call(this, e);
- }
- });
- };
-
Milestone.prototype.loadInitialTab = function() {
const $target = $(`.js-milestone-tabs a[href="${location.hash}"]`);
@@ -203,10 +44,6 @@
.done((data) => {
$(tabElId).html(data.html);
$target.addClass('is-loaded');
-
- if (tabElId === '#tab-merge-requests') {
- this.bindMergeRequestSorting();
- }
});
}
};
diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js
index d56cf959486..624dd336786 100644
--- a/app/assets/javascripts/notes.js
+++ b/app/assets/javascripts/notes.js
@@ -32,7 +32,7 @@ const normalizeNewlines = function(str) {
(function() {
this.Notes = (function() {
const MAX_VISIBLE_COMMIT_LIST_COUNT = 3;
- const REGEX_SLASH_COMMANDS = /^\/\w+.*$/gm;
+ const REGEX_QUICK_ACTIONS = /^\/\w+.*$/gm;
Notes.interval = null;
@@ -187,7 +187,7 @@ const normalizeNewlines = function(str) {
if ($textarea.val() !== '') {
return;
}
- myLastNote = $(`li.note[data-author-id='${gon.current_user_id}'][data-editable]:last`, $textarea.closest('.note, #notes'));
+ myLastNote = $(`li.note[data-author-id='${gon.current_user_id}'][data-editable]:last`, $textarea.closest('.note, .notes_holder, #notes'));
if (myLastNote.length) {
myLastNoteEditBtn = myLastNote.find('.js-note-edit');
return myLastNoteEditBtn.trigger('click', [true, myLastNote]);
@@ -284,7 +284,7 @@ const normalizeNewlines = function(str) {
return this.initRefresh();
};
- Notes.prototype.handleSlashCommands = function(noteEntity) {
+ Notes.prototype.handleQuickActions = function(noteEntity) {
var votesBlock;
if (noteEntity.commands_changes) {
if ('merge' in noteEntity.commands_changes) {
@@ -322,7 +322,9 @@ const normalizeNewlines = function(str) {
Notes.updateNoteTargetSelector = function($note) {
const hash = gl.utils.getLocationHash();
- $note.toggleClass('target', hash && $note.filter(`#${hash}`).length > 0);
+ // Needs to be an explicit true/false for the jQuery `toggleClass(force)`
+ const addTargetClass = Boolean(hash && $note.filter(`#${hash}`).length > 0);
+ $note.toggleClass('target', addTargetClass);
};
/*
@@ -1220,27 +1222,27 @@ const normalizeNewlines = function(str) {
};
/**
- * Identify if comment has any slash commands
+ * Identify if comment has any quick actions
*/
- Notes.prototype.hasSlashCommands = function(formContent) {
- return REGEX_SLASH_COMMANDS.test(formContent);
+ Notes.prototype.hasQuickActions = function(formContent) {
+ return REGEX_QUICK_ACTIONS.test(formContent);
};
/**
- * Remove slash commands and leave comment with pure message
+ * Remove quick actions and leave comment with pure message
*/
- Notes.prototype.stripSlashCommands = function(formContent) {
- return formContent.replace(REGEX_SLASH_COMMANDS, '').trim();
+ Notes.prototype.stripQuickActions = function(formContent) {
+ return formContent.replace(REGEX_QUICK_ACTIONS, '').trim();
};
/**
- * Gets appropriate description from slash commands found in provided `formContent`
+ * Gets appropriate description from quick actions found in provided `formContent`
*/
- Notes.prototype.getSlashCommandDescription = function (formContent, availableSlashCommands = []) {
+ Notes.prototype.getQuickActionDescription = function (formContent, availableQuickActions = []) {
let tempFormContent;
- // Identify executed slash commands from `formContent`
- const executedCommands = availableSlashCommands.filter((command, index) => {
+ // Identify executed quick actions from `formContent`
+ const executedCommands = availableQuickActions.filter((command, index) => {
const commandRegex = new RegExp(`/${command.name}`);
return commandRegex.test(formContent);
});
@@ -1298,7 +1300,7 @@ const normalizeNewlines = function(str) {
};
/**
- * Create Placeholder System Note DOM element populated with slash command description
+ * Create Placeholder System Note DOM element populated with quick action description
*/
Notes.prototype.createPlaceholderSystemNote = function ({ formContent, uniqueId }) {
const $tempNote = $(
@@ -1347,7 +1349,7 @@ const normalizeNewlines = function(str) {
const { formData, formContent, formAction } = this.getFormData($form);
let noteUniqueId;
let systemNoteUniqueId;
- let hasSlashCommands = false;
+ let hasQuickActions = false;
let $notesContainer;
let tempFormContent;
@@ -1366,9 +1368,9 @@ const normalizeNewlines = function(str) {
}
tempFormContent = formContent;
- if (this.hasSlashCommands(formContent)) {
- tempFormContent = this.stripSlashCommands(formContent);
- hasSlashCommands = true;
+ if (this.hasQuickActions(formContent)) {
+ tempFormContent = this.stripQuickActions(formContent);
+ hasQuickActions = true;
}
// Show placeholder note
@@ -1385,10 +1387,10 @@ const normalizeNewlines = function(str) {
}
// Show placeholder system note
- if (hasSlashCommands) {
+ if (hasQuickActions) {
systemNoteUniqueId = _.uniqueId('tempSystemNote_');
$notesContainer.append(this.createPlaceholderSystemNote({
- formContent: this.getSlashCommandDescription(formContent, AjaxCache.get(gl.GfmAutoComplete.dataSources.commands)),
+ formContent: this.getQuickActionDescription(formContent, AjaxCache.get(gl.GfmAutoComplete.dataSources.commands)),
uniqueId: systemNoteUniqueId,
}));
}
@@ -1410,7 +1412,7 @@ const normalizeNewlines = function(str) {
$notesContainer.find(`#${noteUniqueId}`).remove();
// Reset cached commands list when command is applied
- if (hasSlashCommands) {
+ if (hasQuickActions) {
$form.find('textarea.js-note-text').trigger('clear-commands-cache.atwho');
}
@@ -1444,7 +1446,7 @@ const normalizeNewlines = function(str) {
}
if (note.commands_changes) {
- this.handleSlashCommands(note);
+ this.handleQuickActions(note);
}
$form.trigger('ajax:success', [note]);
@@ -1452,7 +1454,7 @@ const normalizeNewlines = function(str) {
// Submission failed, remove placeholder note and show Flash error message
$notesContainer.find(`#${noteUniqueId}`).remove();
- if (hasSlashCommands) {
+ if (hasQuickActions) {
$notesContainer.find(`#${systemNoteUniqueId}`).remove();
}
diff --git a/app/assets/javascripts/pipeline_schedules/components/interval_pattern_input.js b/app/assets/javascripts/pipeline_schedules/components/interval_pattern_input.js
index 4d623763ca7..901adbe9fce 100644
--- a/app/assets/javascripts/pipeline_schedules/components/interval_pattern_input.js
+++ b/app/assets/javascripts/pipeline_schedules/components/interval_pattern_input.js
@@ -1,4 +1,7 @@
import Vue from 'vue';
+import Translate from '../../vue_shared/translate';
+
+Vue.use(Translate);
const inputNameAttribute = 'schedule[cron]';
@@ -72,11 +75,11 @@ export default {
/>
<label for="custom">
- Custom
+ {{ s__('PipelineSheduleIntervalPattern|Custom') }}
</label>
<span class="cron-syntax-link-wrap">
- (<a :href="cronSyntaxUrl" target="_blank">Cron syntax</a>)
+ (<a :href="cronSyntaxUrl" target="_blank">{{ __('Cron syntax') }}</a>)
</span>
</div>
@@ -92,7 +95,7 @@ export default {
/>
<label class="label-light" for="every-day">
- Every day (at 4:00am)
+ {{ __('Every day (at 4:00am)') }}
</label>
</div>
@@ -108,7 +111,7 @@ export default {
/>
<label class="label-light" for="every-week">
- Every week (Sundays at 4:00am)
+ {{ __('Every week (Sundays at 4:00am)') }}
</label>
</div>
@@ -124,7 +127,7 @@ export default {
/>
<label class="label-light" for="every-month">
- Every month (on the 1st at 4:00am)
+ {{ __('Every month (on the 1st at 4:00am)') }}
</label>
</div>
@@ -133,7 +136,7 @@ export default {
id="schedule_cron"
class="form-control inline cron-interval-input"
type="text"
- placeholder="Define a custom pattern with cron syntax"
+ :placeholder="__('Define a custom pattern with cron syntax')"
required="true"
v-model="cronInterval"
:name="inputNameAttribute"
diff --git a/app/assets/javascripts/pipeline_schedules/components/pipeline_schedules_callout.js b/app/assets/javascripts/pipeline_schedules/components/pipeline_schedules_callout.js
index 5109b110b31..c827b7402dc 100644
--- a/app/assets/javascripts/pipeline_schedules/components/pipeline_schedules_callout.js
+++ b/app/assets/javascripts/pipeline_schedules/components/pipeline_schedules_callout.js
@@ -1,6 +1,10 @@
+import Vue from 'vue';
import Cookies from 'js-cookie';
+import Translate from '../../vue_shared/translate';
import illustrationSvg from '../icons/intro_illustration.svg';
+Vue.use(Translate);
+
const cookieKey = 'pipeline_schedules_callout_dismissed';
export default {
@@ -29,20 +33,18 @@ export default {
</button>
<div class="svg-container" v-html="illustrationSvg"></div>
<div class="user-callout-copy">
- <h4>Scheduling Pipelines</h4>
+ <h4>{{ __('Scheduling Pipelines') }}</h4>
<p>
- The pipelines schedule runs pipelines in the future, repeatedly, for specific branches or tags.
- Those scheduled pipelines will inherit limited project access based on their associated user.
+ {{ __('The pipelines schedule runs pipelines in the future, repeatedly, for specific branches or tags. Those scheduled pipelines will inherit limited project access based on their associated user.') }}
</p>
- <p> Learn more in the
+ <p> {{ __('Learn more in the') }}
<a
:href="docsUrl"
target="_blank"
- rel="nofollow">pipeline schedules documentation</a>. <!-- oneline to prevent extra space before period -->
+ rel="nofollow">{{ s__('Learn more in the|pipeline schedules documentation') }}</a>. <!-- oneline to prevent extra space before period -->
</p>
</div>
</div>
</div>
`,
};
-
diff --git a/app/assets/javascripts/pipelines/components/async_button.vue b/app/assets/javascripts/pipelines/components/async_button.vue
index 37a6f02d8fd..abcd0c4ecea 100644
--- a/app/assets/javascripts/pipelines/components/async_button.vue
+++ b/app/assets/javascripts/pipelines/components/async_button.vue
@@ -1,9 +1,9 @@
<script>
/* eslint-disable no-new, no-alert */
-/* global Flash */
-import '~/flash';
+
import eventHub from '../event_hub';
import loadingIcon from '../../vue_shared/components/loading_icon.vue';
+import tooltipMixin from '../../vue_shared/mixins/tooltip';
export default {
props: {
@@ -11,53 +11,42 @@ export default {
type: String,
required: true,
},
-
- service: {
- type: Object,
- required: true,
- },
-
title: {
type: String,
required: true,
},
-
icon: {
type: String,
required: true,
},
-
cssClass: {
type: String,
required: true,
},
-
confirmActionMessage: {
type: String,
required: false,
},
},
-
components: {
loadingIcon,
},
-
+ mixins: [
+ tooltipMixin,
+ ],
data() {
return {
isLoading: false,
};
},
-
computed: {
iconClass() {
return `fa fa-${this.icon}`;
},
-
buttonClass() {
- return `btn has-tooltip ${this.cssClass}`;
+ return `btn ${this.cssClass}`;
},
},
-
methods: {
onClick() {
if (this.confirmActionMessage && confirm(this.confirmActionMessage)) {
@@ -66,21 +55,11 @@ export default {
this.makeRequest();
}
},
-
makeRequest() {
this.isLoading = true;
- $(this.$el).tooltip('destroy');
-
- this.service.postAction(this.endpoint)
- .then(() => {
- this.isLoading = false;
- eventHub.$emit('refreshPipelines');
- })
- .catch(() => {
- this.isLoading = false;
- new Flash('An error occured while making the request.');
- });
+ $(this.$refs.tooltip).tooltip('destroy');
+ eventHub.$emit('postAction', this.endpoint);
},
},
};
@@ -95,10 +74,12 @@ export default {
:aria-label="title"
data-container="body"
data-placement="top"
+ ref="tooltip"
:disabled="isLoading">
<i
:class="iconClass"
- aria-hidden="true" />
+ aria-hidden="true">
+ </i>
<loading-icon v-if="isLoading" />
</button>
</template>
diff --git a/app/assets/javascripts/pipelines/components/pipelines.vue b/app/assets/javascripts/pipelines/components/pipelines.vue
index fed42d23112..01ae07aad65 100644
--- a/app/assets/javascripts/pipelines/components/pipelines.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines.vue
@@ -1,15 +1,9 @@
<script>
- import Visibility from 'visibilityjs';
import PipelinesService from '../services/pipelines_service';
- import eventHub from '../event_hub';
- import pipelinesTableComponent from '../../vue_shared/components/pipelines_table.vue';
+ import pipelinesMixin from '../mixins/pipelines';
import tablePagination from '../../vue_shared/components/table_pagination.vue';
- import emptyState from './empty_state.vue';
- import errorState from './error_state.vue';
import navigationTabs from './navigation_tabs.vue';
import navigationControls from './nav_controls.vue';
- import loadingIcon from '../../vue_shared/components/loading_icon.vue';
- import Poll from '../../lib/utils/poll';
export default {
props: {
@@ -20,13 +14,12 @@
},
components: {
tablePagination,
- pipelinesTableComponent,
- emptyState,
- errorState,
navigationTabs,
navigationControls,
- loadingIcon,
},
+ mixins: [
+ pipelinesMixin,
+ ],
data() {
const pipelinesData = document.querySelector('#pipelines-list-vue').dataset;
@@ -47,11 +40,6 @@
state: this.store.state,
apiScope: 'all',
pagenum: 1,
- isLoading: false,
- hasError: false,
- isMakingRequest: false,
- updateGraphDropdown: false,
- hasMadeRequest: false,
};
},
computed: {
@@ -62,9 +50,6 @@
const scope = gl.utils.getParameterByName('scope');
return scope === null ? 'all' : scope;
},
- shouldRenderErrorState() {
- return this.hasError && !this.isLoading;
- },
/**
* The empty state should only be rendered when the request is made to fetch all pipelines
@@ -106,7 +91,6 @@
this.state.pipelines.length &&
this.state.pageInfo.total > this.state.pageInfo.perPage;
},
-
hasCiEnabled() {
return this.hasCi !== undefined;
},
@@ -129,37 +113,7 @@
},
created() {
this.service = new PipelinesService(this.endpoint);
-
- const poll = new Poll({
- resource: this.service,
- method: 'getPipelines',
- data: { page: this.pageParameter, scope: this.scopeParameter },
- successCallback: this.successCallback,
- errorCallback: this.errorCallback,
- notificationCallback: this.setIsMakingRequest,
- });
-
- if (!Visibility.hidden()) {
- this.isLoading = true;
- poll.makeRequest();
- } else {
- // If tab is not visible we need to make the first request so we don't show the empty
- // state without knowing if there are any pipelines
- this.fetchPipelines();
- }
-
- Visibility.change(() => {
- if (!Visibility.hidden()) {
- poll.restart();
- } else {
- poll.stop();
- }
- });
-
- eventHub.$on('refreshPipelines', this.fetchPipelines);
- },
- beforeDestroy() {
- eventHub.$off('refreshPipelines');
+ this.requestData = { page: this.pageParameter, scope: this.scopeParameter };
},
methods: {
/**
@@ -174,15 +128,6 @@
return param;
},
- fetchPipelines() {
- if (!this.isMakingRequest) {
- this.isLoading = true;
-
- this.service.getPipelines({ scope: this.scopeParameter, page: this.pageParameter })
- .then(response => this.successCallback(response))
- .catch(() => this.errorCallback());
- }
- },
successCallback(resp) {
const response = {
headers: resp.headers,
@@ -190,33 +135,14 @@
};
this.store.storeCount(response.body.count);
- this.store.storePipelines(response.body.pipelines);
this.store.storePagination(response.headers);
-
- this.isLoading = false;
- this.updateGraphDropdown = true;
- this.hasMadeRequest = true;
- },
-
- errorCallback() {
- this.hasError = true;
- this.isLoading = false;
- this.updateGraphDropdown = false;
- },
-
- setIsMakingRequest(isMakingRequest) {
- this.isMakingRequest = isMakingRequest;
-
- if (isMakingRequest) {
- this.updateGraphDropdown = false;
- }
+ this.setCommonData(response.body.pipelines);
},
},
};
</script>
<template>
<div :class="cssClass">
-
<div
class="top-area scrolling-tabs-container inner-page-scroll-tabs"
v-if="!isLoading && !shouldRenderEmptyState">
@@ -274,7 +200,6 @@
<pipelines-table-component
:pipelines="state.pipelines"
- :service="service"
:update-graph-dropdown="updateGraphDropdown"
/>
</div>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_actions.vue b/app/assets/javascripts/pipelines/components/pipelines_actions.vue
index 97b4de26214..a6fc4f04237 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_actions.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_actions.vue
@@ -11,10 +11,6 @@
type: Array,
required: true,
},
- service: {
- type: Object,
- required: true,
- },
},
components: {
loadingIcon,
@@ -31,17 +27,9 @@
$(this.$refs.tooltip).tooltip('destroy');
- this.service.postAction(endpoint)
- .then(() => {
- this.isLoading = false;
- eventHub.$emit('refreshPipelines');
- })
- .catch(() => {
- this.isLoading = false;
- // eslint-disable-next-line no-new
- new Flash('An error occured while making the request.');
- });
+ eventHub.$emit('postAction', endpoint);
},
+
isActionDisabled(action) {
if (action.playable === undefined) {
return false;
diff --git a/app/assets/javascripts/vue_shared/components/pipelines_table.vue b/app/assets/javascripts/pipelines/components/pipelines_table.vue
index 884f1ce9689..5088d92209f 100644
--- a/app/assets/javascripts/vue_shared/components/pipelines_table.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_table.vue
@@ -12,10 +12,6 @@
type: Array,
required: true,
},
- service: {
- type: Object,
- required: true,
- },
updateGraphDropdown: {
type: Boolean,
required: false,
@@ -57,7 +53,6 @@
v-for="model in pipelines"
:key="model.id"
:pipeline="model"
- :service="service"
:update-graph-dropdown="updateGraphDropdown"
/>
</div>
diff --git a/app/assets/javascripts/vue_shared/components/pipelines_table_row.vue b/app/assets/javascripts/pipelines/components/pipelines_table_row.vue
index 4d5ebe2e9ed..c3f1c426d8a 100644
--- a/app/assets/javascripts/vue_shared/components/pipelines_table_row.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_table_row.vue
@@ -1,13 +1,13 @@
<script>
/* eslint-disable no-param-reassign */
-import asyncButtonComponent from '../../pipelines/components/async_button.vue';
-import pipelinesActionsComponent from '../../pipelines/components/pipelines_actions.vue';
-import pipelinesArtifactsComponent from '../../pipelines/components/pipelines_artifacts.vue';
-import ciBadge from './ci_badge_link.vue';
-import pipelineStage from '../../pipelines/components/stage.vue';
-import pipelineUrl from '../../pipelines/components/pipeline_url.vue';
-import pipelinesTimeago from '../../pipelines/components/time_ago.vue';
-import commitComponent from './commit.vue';
+import asyncButtonComponent from './async_button.vue';
+import pipelinesActionsComponent from './pipelines_actions.vue';
+import pipelinesArtifactsComponent from './pipelines_artifacts.vue';
+import ciBadge from '../../vue_shared/components/ci_badge_link.vue';
+import pipelineStage from './stage.vue';
+import pipelineUrl from './pipeline_url.vue';
+import pipelinesTimeago from './time_ago.vue';
+import commitComponent from '../../vue_shared/components/commit.vue';
/**
* Pipeline table row.
@@ -20,10 +20,6 @@ export default {
type: Object,
required: true,
},
- service: {
- type: Object,
- required: true,
- },
updateGraphDropdown: {
type: Boolean,
required: false,
@@ -271,7 +267,6 @@ export default {
<pipelines-actions-component
v-if="pipeline.details.manual_actions.length"
:actions="pipeline.details.manual_actions"
- :service="service"
/>
<pipelines-artifacts-component
@@ -282,7 +277,6 @@ export default {
<async-button-component
v-if="pipeline.flags.retryable"
- :service="service"
:endpoint="pipeline.retry_path"
css-class="js-pipelines-retry-button btn-default btn-retry"
title="Retry"
@@ -291,7 +285,6 @@ export default {
<async-button-component
v-if="pipeline.flags.cancelable"
- :service="service"
:endpoint="pipeline.cancel_path"
css-class="js-pipelines-cancel-button btn-remove"
title="Cancel"
diff --git a/app/assets/javascripts/pipelines/mixins/pipelines.js b/app/assets/javascripts/pipelines/mixins/pipelines.js
new file mode 100644
index 00000000000..9adc15e6266
--- /dev/null
+++ b/app/assets/javascripts/pipelines/mixins/pipelines.js
@@ -0,0 +1,103 @@
+/* global Flash */
+import '~/flash';
+import Visibility from 'visibilityjs';
+import Poll from '../../lib/utils/poll';
+import emptyState from '../components/empty_state.vue';
+import errorState from '../components/error_state.vue';
+import loadingIcon from '../../vue_shared/components/loading_icon.vue';
+import pipelinesTableComponent from '../components/pipelines_table.vue';
+import eventHub from '../event_hub';
+
+export default {
+ components: {
+ pipelinesTableComponent,
+ errorState,
+ emptyState,
+ loadingIcon,
+ },
+ computed: {
+ shouldRenderErrorState() {
+ return this.hasError && !this.isLoading;
+ },
+ },
+ data() {
+ return {
+ isLoading: false,
+ hasError: false,
+ isMakingRequest: false,
+ updateGraphDropdown: false,
+ hasMadeRequest: false,
+ };
+ },
+ beforeMount() {
+ this.poll = new Poll({
+ resource: this.service,
+ method: 'getPipelines',
+ data: this.requestData ? this.requestData : undefined,
+ successCallback: this.successCallback,
+ errorCallback: this.errorCallback,
+ notificationCallback: this.setIsMakingRequest,
+ });
+
+ if (!Visibility.hidden()) {
+ this.isLoading = true;
+ this.poll.makeRequest();
+ } else {
+ // If tab is not visible we need to make the first request so we don't show the empty
+ // state without knowing if there are any pipelines
+ this.fetchPipelines();
+ }
+
+ Visibility.change(() => {
+ if (!Visibility.hidden()) {
+ this.poll.restart();
+ } else {
+ this.poll.stop();
+ }
+ });
+
+ eventHub.$on('refreshPipelines', this.fetchPipelines);
+ eventHub.$on('postAction', this.postAction);
+ },
+ beforeDestroy() {
+ eventHub.$off('refreshPipelines');
+ eventHub.$on('postAction', this.postAction);
+ },
+ destroyed() {
+ this.poll.stop();
+ },
+ methods: {
+ fetchPipelines() {
+ if (!this.isMakingRequest) {
+ this.isLoading = true;
+
+ this.service.getPipelines(this.requestData)
+ .then(response => this.successCallback(response))
+ .catch(() => this.errorCallback());
+ }
+ },
+ setCommonData(pipelines) {
+ this.store.storePipelines(pipelines);
+ this.isLoading = false;
+ this.updateGraphDropdown = true;
+ this.hasMadeRequest = true;
+ },
+ errorCallback() {
+ this.hasError = true;
+ this.isLoading = false;
+ this.updateGraphDropdown = false;
+ },
+ setIsMakingRequest(isMakingRequest) {
+ this.isMakingRequest = isMakingRequest;
+
+ if (isMakingRequest) {
+ this.updateGraphDropdown = false;
+ }
+ },
+ postAction(endpoint) {
+ this.service.postAction(endpoint)
+ .then(() => eventHub.$emit('refreshPipelines'))
+ .catch(() => new Flash('An error occured while making the request.'));
+ },
+ },
+};
diff --git a/app/assets/javascripts/preview_markdown.js b/app/assets/javascripts/preview_markdown.js
index 4a3df2fd465..141333b2b4d 100644
--- a/app/assets/javascripts/preview_markdown.js
+++ b/app/assets/javascripts/preview_markdown.js
@@ -3,7 +3,7 @@
// MarkdownPreview
//
// Handles toggling the "Write" and "Preview" tab clicks, rendering the preview
-// (including the explanation of slash commands), and showing a warning when
+// (including the explanation of quick actions), and showing a warning when
// more than `x` users are referenced.
//
(function () {
diff --git a/app/assets/javascripts/right_sidebar.js b/app/assets/javascripts/right_sidebar.js
index b71c3097706..da7c0c5a36c 100644
--- a/app/assets/javascripts/right_sidebar.js
+++ b/app/assets/javascripts/right_sidebar.js
@@ -7,6 +7,13 @@ import Cookies from 'js-cookie';
function Sidebar(currentUser) {
this.toggleTodo = this.toggleTodo.bind(this);
this.sidebar = $('aside');
+
+ this.$sidebarInner = this.sidebar.find('.issuable-sidebar');
+ this.$navGitlab = $('.navbar-gitlab');
+ this.$layoutNav = $('.layout-nav');
+ this.$subScroll = $('.sub-nav-scroll');
+ this.$rightSidebar = $('.js-right-sidebar');
+
this.removeListeners();
this.addEventListeners();
}
@@ -21,14 +28,15 @@ import Cookies from 'js-cookie';
Sidebar.prototype.addEventListeners = function() {
const $document = $(document);
- const throttledSetSidebarHeight = _.throttle(this.setSidebarHeight, 10);
+ const throttledSetSidebarHeight = _.throttle(this.setSidebarHeight.bind(this), 20);
+ const debouncedSetSidebarHeight = _.debounce(this.setSidebarHeight.bind(this), 200);
this.sidebar.on('click', '.sidebar-collapsed-icon', this, this.sidebarCollapseClicked);
$('.dropdown').on('hidden.gl.dropdown', this, this.onSidebarDropdownHidden);
$('.dropdown').on('loading.gl.dropdown', this.sidebarDropdownLoading);
$('.dropdown').on('loaded.gl.dropdown', this.sidebarDropdownLoaded);
$(window).on('resize', () => throttledSetSidebarHeight());
- $document.on('scroll', () => throttledSetSidebarHeight());
+ $document.on('scroll', () => debouncedSetSidebarHeight());
$document.on('click', '.js-sidebar-toggle', function(e, triggered) {
var $allGutterToggleIcons, $this, $thisIcon;
e.preventDefault();
@@ -207,13 +215,14 @@ import Cookies from 'js-cookie';
};
Sidebar.prototype.setSidebarHeight = function() {
- const $navHeight = $('.navbar-gitlab').outerHeight() + $('.layout-nav').outerHeight() + $('.sub-nav-scroll').outerHeight();
- const $rightSidebar = $('.js-right-sidebar');
+ const $navHeight = this.$navGitlab.outerHeight() + this.$layoutNav.outerHeight() + (this.$subScroll ? this.$subScroll.outerHeight() : 0);
const diff = $navHeight - $(window).scrollTop();
if (diff > 0) {
- $rightSidebar.outerHeight($(window).height() - diff);
+ this.$rightSidebar.outerHeight($(window).height() - diff);
+ this.$sidebarInner.height('100%');
} else {
- $rightSidebar.outerHeight('100%');
+ this.$rightSidebar.outerHeight('100%');
+ this.$sidebarInner.height('');
}
};
diff --git a/app/assets/javascripts/settings_panels.js b/app/assets/javascripts/settings_panels.js
index e67f449e1a2..59ff2a86293 100644
--- a/app/assets/javascripts/settings_panels.js
+++ b/app/assets/javascripts/settings_panels.js
@@ -1,11 +1,28 @@
+function expandSectionParent($section, $content) {
+ $section.addClass('expanded');
+ $content.off('animationend.expandSectionParent');
+}
+
function expandSection($section) {
$section.find('.js-settings-toggle').text('Close');
- $section.find('.settings-content').addClass('expanded').off('scroll').scrollTop(0);
+
+ const $content = $section.find('.settings-content');
+ $content.addClass('expanded').off('scroll.expandSection').scrollTop(0);
+
+ if ($content.hasClass('no-animate')) {
+ expandSectionParent($section, $content);
+ } else {
+ $content.on('animationend.expandSectionParent', () => expandSectionParent($section, $content));
+ }
}
function closeSection($section) {
$section.find('.js-settings-toggle').text('Expand');
- $section.find('.settings-content').removeClass('expanded').on('scroll', () => expandSection($section));
+
+ const $content = $section.find('.settings-content');
+ $content.removeClass('expanded').on('scroll.expandSection', () => expandSection($section));
+
+ $section.removeClass('expanded');
}
function toggleSection($section) {
@@ -21,7 +38,7 @@ function toggleSection($section) {
export default function initSettingsPanels() {
$('.settings').each((i, elm) => {
const $section = $(elm);
- $section.on('click', '.js-settings-toggle', () => toggleSection($section));
- $section.find('.settings-content:not(.expanded)').on('scroll', () => expandSection($section));
+ $section.on('click.toggleSection', '.js-settings-toggle', () => toggleSection($section));
+ $section.find('.settings-content:not(.expanded)').on('scroll.expandSection', () => expandSection($section));
});
}
diff --git a/app/assets/javascripts/sidebar/components/time_tracking/help_state.js b/app/assets/javascripts/sidebar/components/time_tracking/help_state.js
index b2a77462fe0..142ad437509 100644
--- a/app/assets/javascripts/sidebar/components/time_tracking/help_state.js
+++ b/app/assets/javascripts/sidebar/components/time_tracking/help_state.js
@@ -15,10 +15,10 @@ export default {
<div class="time-tracking-help-state">
<div class="time-tracking-info">
<h4>
- Track time with slash commands
+ Track time with quick actions
</h4>
<p>
- Slash commands can be used in the issues description and comment boxes.
+ Quick actions can be used in the issues description and comment boxes.
</p>
<p>
<code>
diff --git a/app/assets/javascripts/sidebar/components/time_tracking/sidebar_time_tracking.js b/app/assets/javascripts/sidebar/components/time_tracking/sidebar_time_tracking.js
index 244b67b3ad9..650e935b116 100644
--- a/app/assets/javascripts/sidebar/components/time_tracking/sidebar_time_tracking.js
+++ b/app/assets/javascripts/sidebar/components/time_tracking/sidebar_time_tracking.js
@@ -16,10 +16,10 @@ export default {
'issuable-time-tracker': timeTracker,
},
methods: {
- listenForSlashCommands() {
- $(document).on('ajax:success', '.gfm-form', this.slashCommandListened);
+ listenForQuickActions() {
+ $(document).on('ajax:success', '.gfm-form', this.quickActionListened);
},
- slashCommandListened(e, data) {
+ quickActionListened(e, data) {
const subscribedCommands = ['spend_time', 'time_estimate'];
let changedCommands;
if (data !== undefined) {
@@ -35,7 +35,7 @@ export default {
},
},
mounted() {
- this.listenForSlashCommands();
+ this.listenForQuickActions();
},
template: `
<div class="block">
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_memory_usage.js b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_memory_usage.js
index 8155218681c..76cb71b6c12 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_memory_usage.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_memory_usage.js
@@ -1,5 +1,5 @@
-import statusCodes from '~/lib/utils/http_status';
-import { bytesToMiB } from '~/lib/utils/number_utils';
+import statusCodes from '../../lib/utils/http_status';
+import { bytesToMiB } from '../../lib/utils/number_utils';
import MemoryGraph from '../../vue_shared/components/memory_graph';
import MRWidgetService from '../services/mr_widget_service';