2017-09-10 17:25:29 +05:30
|
|
|
import Visibility from 'visibilityjs';
|
2022-11-25 23:54:43 +05:30
|
|
|
import { createAlert } from '~/flash';
|
2022-08-27 11:52:29 +05:30
|
|
|
import { helpPagePath } from '~/helpers/help_page_helper';
|
2021-03-11 19:13:27 +05:30
|
|
|
import { historyPushState, buildUrlWithCurrentLocation } from '~/lib/utils/common_utils';
|
2023-03-17 16:20:25 +05:30
|
|
|
import { HTTP_STATUS_UNAUTHORIZED } from '~/lib/utils/http_status';
|
2020-07-28 23:09:34 +05:30
|
|
|
import Poll from '~/lib/utils/poll';
|
2021-03-11 19:13:27 +05:30
|
|
|
import { __ } from '~/locale';
|
|
|
|
import { validateParams } from '~/pipelines/utils';
|
2021-12-11 22:18:48 +05:30
|
|
|
import { CANCEL_REQUEST, TOAST_MESSAGE } from '../constants';
|
2021-03-11 19:13:27 +05:30
|
|
|
import eventHub from '../event_hub';
|
2017-09-10 17:25:29 +05:30
|
|
|
|
|
|
|
export default {
|
|
|
|
data() {
|
|
|
|
return {
|
|
|
|
isLoading: false,
|
|
|
|
hasError: false,
|
|
|
|
isMakingRequest: false,
|
|
|
|
updateGraphDropdown: false,
|
|
|
|
hasMadeRequest: false,
|
|
|
|
};
|
|
|
|
},
|
2018-12-13 13:39:08 +05:30
|
|
|
computed: {
|
|
|
|
shouldRenderPagination() {
|
2019-07-07 11:18:12 +05:30
|
|
|
return !this.isLoading;
|
2018-12-13 13:39:08 +05:30
|
|
|
},
|
|
|
|
},
|
2017-09-10 17:25:29 +05:30
|
|
|
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('postAction', this.postAction);
|
2018-11-08 19:23:39 +05:30
|
|
|
eventHub.$on('retryPipeline', this.postAction);
|
2018-10-15 14:42:47 +05:30
|
|
|
eventHub.$on('clickedDropdown', this.updateTable);
|
2019-10-12 21:52:04 +05:30
|
|
|
eventHub.$on('updateTable', this.updateTable);
|
2019-12-04 20:38:33 +05:30
|
|
|
eventHub.$on('runMergeRequestPipeline', this.runMergeRequestPipeline);
|
2017-09-10 17:25:29 +05:30
|
|
|
},
|
|
|
|
beforeDestroy() {
|
2018-05-09 12:01:36 +05:30
|
|
|
eventHub.$off('postAction', this.postAction);
|
2018-11-08 19:23:39 +05:30
|
|
|
eventHub.$off('retryPipeline', this.postAction);
|
2018-10-15 14:42:47 +05:30
|
|
|
eventHub.$off('clickedDropdown', this.updateTable);
|
2019-10-12 21:52:04 +05:30
|
|
|
eventHub.$off('updateTable', this.updateTable);
|
2019-12-04 20:38:33 +05:30
|
|
|
eventHub.$off('runMergeRequestPipeline', this.runMergeRequestPipeline);
|
2017-09-10 17:25:29 +05:30
|
|
|
},
|
|
|
|
destroyed() {
|
|
|
|
this.poll.stop();
|
|
|
|
},
|
|
|
|
methods: {
|
2021-03-11 19:13:27 +05:30
|
|
|
updateInternalState(parameters) {
|
|
|
|
this.poll.stop();
|
|
|
|
|
|
|
|
const queryString = Object.keys(parameters)
|
|
|
|
.map((parameter) => {
|
|
|
|
const value = parameters[parameter];
|
|
|
|
// update internal state for UI
|
|
|
|
this[parameter] = value;
|
|
|
|
return `${parameter}=${encodeURIComponent(value)}`;
|
|
|
|
})
|
|
|
|
.join('&');
|
|
|
|
|
|
|
|
// update polling parameters
|
|
|
|
this.requestData = parameters;
|
|
|
|
|
|
|
|
historyPushState(buildUrlWithCurrentLocation(`?${queryString}`));
|
|
|
|
|
|
|
|
this.isLoading = true;
|
|
|
|
},
|
2018-12-13 13:39:08 +05:30
|
|
|
/**
|
|
|
|
* Handles URL and query parameter changes.
|
|
|
|
* When the user uses the pagination or the tabs,
|
|
|
|
* - update URL
|
|
|
|
* - Make API request to the server with new parameters
|
|
|
|
* - Update the polling function
|
|
|
|
* - Update the internal state
|
|
|
|
*/
|
|
|
|
updateContent(parameters) {
|
|
|
|
this.updateInternalState(parameters);
|
|
|
|
|
|
|
|
// fetch new data
|
|
|
|
return this.service
|
|
|
|
.getPipelines(this.requestData)
|
2021-03-08 18:12:59 +05:30
|
|
|
.then((response) => {
|
2018-12-13 13:39:08 +05:30
|
|
|
this.isLoading = false;
|
|
|
|
this.successCallback(response);
|
|
|
|
|
2019-07-07 11:18:12 +05:30
|
|
|
this.poll.enable({ data: this.requestData, response });
|
2018-12-13 13:39:08 +05:30
|
|
|
})
|
|
|
|
.catch(() => {
|
|
|
|
this.isLoading = false;
|
|
|
|
this.errorCallback();
|
|
|
|
|
|
|
|
// restart polling
|
|
|
|
this.poll.restart({ data: this.requestData });
|
|
|
|
});
|
|
|
|
},
|
2018-10-15 14:42:47 +05:30
|
|
|
updateTable() {
|
|
|
|
// Cancel ongoing request
|
|
|
|
if (this.isMakingRequest) {
|
|
|
|
this.service.cancelationSource.cancel(CANCEL_REQUEST);
|
|
|
|
}
|
|
|
|
// Stop polling
|
|
|
|
this.poll.stop();
|
2019-09-30 21:07:59 +05:30
|
|
|
// Restarting the poll also makes an initial request
|
2019-12-04 20:38:33 +05:30
|
|
|
return this.poll.restart();
|
2018-10-15 14:42:47 +05:30
|
|
|
},
|
2017-09-10 17:25:29 +05:30
|
|
|
fetchPipelines() {
|
|
|
|
if (!this.isMakingRequest) {
|
|
|
|
this.isLoading = true;
|
|
|
|
|
2018-10-15 14:42:47 +05:30
|
|
|
this.getPipelines();
|
2017-09-10 17:25:29 +05:30
|
|
|
}
|
|
|
|
},
|
2018-10-15 14:42:47 +05:30
|
|
|
getPipelines() {
|
2018-11-08 19:23:39 +05:30
|
|
|
return this.service
|
|
|
|
.getPipelines(this.requestData)
|
2021-03-08 18:12:59 +05:30
|
|
|
.then((response) => this.successCallback(response))
|
|
|
|
.catch((error) => this.errorCallback(error));
|
2018-10-15 14:42:47 +05:30
|
|
|
},
|
2017-09-10 17:25:29 +05:30
|
|
|
setCommonData(pipelines) {
|
|
|
|
this.store.storePipelines(pipelines);
|
|
|
|
this.isLoading = false;
|
|
|
|
this.updateGraphDropdown = true;
|
|
|
|
this.hasMadeRequest = true;
|
2018-10-15 14:42:47 +05:30
|
|
|
|
|
|
|
// In case the previous polling request returned an error, we need to reset it
|
|
|
|
if (this.hasError) {
|
|
|
|
this.hasError = false;
|
|
|
|
}
|
2017-09-10 17:25:29 +05:30
|
|
|
},
|
2018-10-15 14:42:47 +05:30
|
|
|
errorCallback(error) {
|
2018-03-27 19:54:05 +05:30
|
|
|
this.hasMadeRequest = true;
|
2018-10-15 14:42:47 +05:30
|
|
|
this.isLoading = false;
|
|
|
|
|
|
|
|
if (error && error.message && error.message !== CANCEL_REQUEST) {
|
|
|
|
this.hasError = true;
|
|
|
|
this.updateGraphDropdown = false;
|
|
|
|
}
|
2017-09-10 17:25:29 +05:30
|
|
|
},
|
|
|
|
setIsMakingRequest(isMakingRequest) {
|
|
|
|
this.isMakingRequest = isMakingRequest;
|
|
|
|
|
|
|
|
if (isMakingRequest) {
|
|
|
|
this.updateGraphDropdown = false;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
postAction(endpoint) {
|
2018-11-08 19:23:39 +05:30
|
|
|
this.service
|
|
|
|
.postAction(endpoint)
|
2019-09-30 21:07:59 +05:30
|
|
|
.then(() => this.updateTable())
|
2021-09-04 01:27:46 +05:30
|
|
|
.catch(() =>
|
2022-11-25 23:54:43 +05:30
|
|
|
createAlert({
|
2021-09-04 01:27:46 +05:30
|
|
|
message: __('An error occurred while making the request.'),
|
|
|
|
}),
|
|
|
|
);
|
2019-12-04 20:38:33 +05:30
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* When the user clicks on the run pipeline button
|
|
|
|
* we toggle the state of the button to be disabled
|
|
|
|
*
|
|
|
|
* Once the post request has finished, we fetch the
|
|
|
|
* pipelines again to show the most recent data
|
|
|
|
*
|
|
|
|
* Once the pipeline has been updated, we toggle back the
|
|
|
|
* loading state and re-enable the run pipeline button
|
|
|
|
*/
|
|
|
|
runMergeRequestPipeline(options) {
|
|
|
|
this.store.toggleIsRunningPipeline(true);
|
|
|
|
|
|
|
|
this.service
|
|
|
|
.runMRPipeline(options)
|
2021-12-11 22:18:48 +05:30
|
|
|
.then(() => {
|
|
|
|
this.$toast.show(TOAST_MESSAGE);
|
|
|
|
this.updateTable();
|
|
|
|
})
|
2022-04-04 11:22:00 +05:30
|
|
|
.catch((e) => {
|
2023-03-17 16:20:25 +05:30
|
|
|
const unauthorized = e.response.status === HTTP_STATUS_UNAUTHORIZED;
|
2022-04-04 11:22:00 +05:30
|
|
|
let errorMessage = __(
|
|
|
|
'An error occurred while trying to run a new pipeline for this merge request.',
|
|
|
|
);
|
|
|
|
|
2022-08-27 11:52:29 +05:30
|
|
|
if (unauthorized) {
|
2022-04-04 11:22:00 +05:30
|
|
|
errorMessage = __('You do not have permission to run a pipeline on this branch.');
|
|
|
|
}
|
|
|
|
|
2022-08-27 11:52:29 +05:30
|
|
|
createAlert({
|
2022-04-04 11:22:00 +05:30
|
|
|
message: errorMessage,
|
2022-08-27 11:52:29 +05:30
|
|
|
primaryButton: {
|
|
|
|
text: __('Learn more'),
|
|
|
|
link: helpPagePath('ci/pipelines/merge_request_pipelines.md'),
|
|
|
|
},
|
2021-09-04 01:27:46 +05:30
|
|
|
});
|
2019-12-04 20:38:33 +05:30
|
|
|
})
|
|
|
|
.finally(() => this.store.toggleIsRunningPipeline(false));
|
2017-09-10 17:25:29 +05:30
|
|
|
},
|
2021-03-11 19:13:27 +05:30
|
|
|
onChangePage(page) {
|
|
|
|
/* URLS parameters are strings, we need to parse to match types */
|
|
|
|
let params = {
|
|
|
|
page: Number(page).toString(),
|
|
|
|
};
|
|
|
|
|
|
|
|
if (this.scope) {
|
|
|
|
params.scope = this.scope;
|
|
|
|
}
|
|
|
|
|
|
|
|
params = this.onChangeWithFilter(params);
|
|
|
|
|
|
|
|
this.updateContent(params);
|
|
|
|
},
|
|
|
|
|
|
|
|
onChangeWithFilter(params) {
|
|
|
|
return { ...params, ...validateParams(this.requestData) };
|
|
|
|
},
|
2017-09-10 17:25:29 +05:30
|
|
|
},
|
|
|
|
};
|