Adds pagination to pipelines table in merge request page
This commit is contained in:
parent
fc892db6f0
commit
87444fb6ed
|
@ -2,9 +2,15 @@
|
||||||
import PipelinesService from '../../pipelines/services/pipelines_service';
|
import PipelinesService from '../../pipelines/services/pipelines_service';
|
||||||
import PipelineStore from '../../pipelines/stores/pipelines_store';
|
import PipelineStore from '../../pipelines/stores/pipelines_store';
|
||||||
import pipelinesMixin from '../../pipelines/mixins/pipelines';
|
import pipelinesMixin from '../../pipelines/mixins/pipelines';
|
||||||
|
import TablePagination from '../../vue_shared/components/table_pagination.vue';
|
||||||
|
import { getParameterByName } from '../../lib/utils/common_utils';
|
||||||
|
import CIPaginationMixin from '../../vue_shared/mixins/ci_pagination_api_mixin';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
mixins: [pipelinesMixin],
|
components: {
|
||||||
|
TablePagination,
|
||||||
|
},
|
||||||
|
mixins: [pipelinesMixin, CIPaginationMixin],
|
||||||
props: {
|
props: {
|
||||||
endpoint: {
|
endpoint: {
|
||||||
type: String,
|
type: String,
|
||||||
|
@ -35,6 +41,8 @@ export default {
|
||||||
return {
|
return {
|
||||||
store,
|
store,
|
||||||
state: store.state,
|
state: store.state,
|
||||||
|
page: getParameterByName('page') || '1',
|
||||||
|
requestData: {},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -48,11 +56,14 @@ export default {
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.service = new PipelinesService(this.endpoint);
|
this.service = new PipelinesService(this.endpoint);
|
||||||
|
this.requestData = { page: this.page };
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
successCallback(resp) {
|
successCallback(resp) {
|
||||||
// depending of the endpoint the response can either bring a `pipelines` key or not.
|
// depending of the endpoint the response can either bring a `pipelines` key or not.
|
||||||
const pipelines = resp.data.pipelines || resp.data;
|
const pipelines = resp.data.pipelines || resp.data;
|
||||||
|
|
||||||
|
this.store.storePagination(resp.headers);
|
||||||
this.setCommonData(pipelines);
|
this.setCommonData(pipelines);
|
||||||
|
|
||||||
const updatePipelinesEvent = new CustomEvent('update-pipelines-count', {
|
const updatePipelinesEvent = new CustomEvent('update-pipelines-count', {
|
||||||
|
@ -97,5 +108,11 @@ export default {
|
||||||
:view-type="viewType"
|
:view-type="viewType"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<table-pagination
|
||||||
|
v-if="shouldRenderPagination"
|
||||||
|
:change="onChangePage"
|
||||||
|
:page-info="state.pageInfo"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -155,14 +155,6 @@ export default {
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
shouldRenderPagination() {
|
|
||||||
return (
|
|
||||||
!this.isLoading &&
|
|
||||||
this.state.pipelines.length &&
|
|
||||||
this.state.pageInfo.total > this.state.pageInfo.perPage
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
emptyTabMessage() {
|
emptyTabMessage() {
|
||||||
const { scopes } = this.$options;
|
const { scopes } = this.$options;
|
||||||
const possibleScopes = [scopes.pending, scopes.running, scopes.finished];
|
const possibleScopes = [scopes.pending, scopes.running, scopes.finished];
|
||||||
|
@ -232,36 +224,6 @@ export default {
|
||||||
this.setCommonData(resp.data.pipelines);
|
this.setCommonData(resp.data.pipelines);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
/**
|
|
||||||
* 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)
|
|
||||||
.then(response => {
|
|
||||||
this.isLoading = false;
|
|
||||||
this.successCallback(response);
|
|
||||||
|
|
||||||
// restart polling
|
|
||||||
this.poll.restart({ data: this.requestData });
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
this.isLoading = false;
|
|
||||||
this.errorCallback();
|
|
||||||
|
|
||||||
// restart polling
|
|
||||||
this.poll.restart({ data: this.requestData });
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
handleResetRunnersCache(endpoint) {
|
handleResetRunnersCache(endpoint) {
|
||||||
this.isResetCacheButtonLoading = true;
|
this.isResetCacheButtonLoading = true;
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,15 @@ export default {
|
||||||
hasMadeRequest: false,
|
hasMadeRequest: false,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
shouldRenderPagination() {
|
||||||
|
return (
|
||||||
|
!this.isLoading &&
|
||||||
|
this.state.pipelines.length &&
|
||||||
|
this.state.pageInfo.total > this.state.pageInfo.perPage
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
beforeMount() {
|
beforeMount() {
|
||||||
this.poll = new Poll({
|
this.poll = new Poll({
|
||||||
resource: this.service,
|
resource: this.service,
|
||||||
|
@ -65,6 +74,35 @@ export default {
|
||||||
this.poll.stop();
|
this.poll.stop();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
/**
|
||||||
|
* 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)
|
||||||
|
.then(response => {
|
||||||
|
this.isLoading = false;
|
||||||
|
this.successCallback(response);
|
||||||
|
|
||||||
|
// restart polling
|
||||||
|
this.poll.restart({ data: this.requestData });
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
this.isLoading = false;
|
||||||
|
this.errorCallback();
|
||||||
|
|
||||||
|
// restart polling
|
||||||
|
this.poll.restart({ data: this.requestData });
|
||||||
|
});
|
||||||
|
},
|
||||||
updateTable() {
|
updateTable() {
|
||||||
// Cancel ongoing request
|
// Cancel ongoing request
|
||||||
if (this.isMakingRequest) {
|
if (this.isMakingRequest) {
|
||||||
|
|
|
@ -14,7 +14,14 @@ export default {
|
||||||
|
|
||||||
onChangePage(page) {
|
onChangePage(page) {
|
||||||
/* URLS parameters are strings, we need to parse to match types */
|
/* URLS parameters are strings, we need to parse to match types */
|
||||||
this.updateContent({ scope: this.scope, page: Number(page).toString() });
|
const params = {
|
||||||
|
page: Number(page).toString(),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (this.scope) {
|
||||||
|
params.scope = this.scope;
|
||||||
|
}
|
||||||
|
this.updateContent(params);
|
||||||
},
|
},
|
||||||
|
|
||||||
updateInternalState(parameters) {
|
updateInternalState(parameters) {
|
||||||
|
|
|
@ -43,7 +43,7 @@ class Projects::CommitController < Projects::ApplicationController
|
||||||
# rubocop: disable CodeReuse/ActiveRecord
|
# rubocop: disable CodeReuse/ActiveRecord
|
||||||
def pipelines
|
def pipelines
|
||||||
@pipelines = @commit.pipelines.order(id: :desc)
|
@pipelines = @commit.pipelines.order(id: :desc)
|
||||||
@pipelines = @pipelines.where(ref: params[:ref]) if params[:ref]
|
@pipelines = @pipelines.where(ref: params[:ref]).page(params[:page]).per(30) if params[:ref]
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html
|
format.html
|
||||||
|
@ -53,6 +53,7 @@ class Projects::CommitController < Projects::ApplicationController
|
||||||
render json: {
|
render json: {
|
||||||
pipelines: PipelineSerializer
|
pipelines: PipelineSerializer
|
||||||
.new(project: @project, current_user: @current_user)
|
.new(project: @project, current_user: @current_user)
|
||||||
|
.with_pagination(request, response)
|
||||||
.represent(@pipelines),
|
.represent(@pipelines),
|
||||||
count: {
|
count: {
|
||||||
all: @pipelines.count
|
all: @pipelines.count
|
||||||
|
|
|
@ -84,13 +84,14 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
|
||||||
end
|
end
|
||||||
|
|
||||||
def pipelines
|
def pipelines
|
||||||
@pipelines = @merge_request.all_pipelines
|
@pipelines = @merge_request.all_pipelines.page(params[:page]).per(30)
|
||||||
|
|
||||||
Gitlab::PollingInterval.set_header(response, interval: 10_000)
|
Gitlab::PollingInterval.set_header(response, interval: 10_000)
|
||||||
|
|
||||||
render json: {
|
render json: {
|
||||||
pipelines: PipelineSerializer
|
pipelines: PipelineSerializer
|
||||||
.new(project: @project, current_user: @current_user)
|
.new(project: @project, current_user: @current_user)
|
||||||
|
.with_pagination(request, response)
|
||||||
.represent(@pipelines),
|
.represent(@pipelines),
|
||||||
count: {
|
count: {
|
||||||
all: @pipelines.count
|
all: @pipelines.count
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
title: Adds pagination to pipelines table in merge request page
|
||||||
|
merge_request:
|
||||||
|
author:
|
||||||
|
type: performance
|
|
@ -356,6 +356,7 @@ describe Projects::CommitController do
|
||||||
expect(response).to be_ok
|
expect(response).to be_ok
|
||||||
expect(JSON.parse(response.body)['pipelines']).not_to be_empty
|
expect(JSON.parse(response.body)['pipelines']).not_to be_empty
|
||||||
expect(JSON.parse(response.body)['count']['all']).to eq 1
|
expect(JSON.parse(response.body)['count']['all']).to eq 1
|
||||||
|
expect(response).to include_pagination_headers
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -563,6 +563,7 @@ describe Projects::MergeRequestsController do
|
||||||
it 'responds with serialized pipelines' do
|
it 'responds with serialized pipelines' do
|
||||||
expect(json_response['pipelines']).not_to be_empty
|
expect(json_response['pipelines']).not_to be_empty
|
||||||
expect(json_response['count']['all']).to eq 1
|
expect(json_response['count']['all']).to eq 1
|
||||||
|
expect(response).to include_pagination_headers
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -72,6 +72,29 @@ describe('Pipelines table in Commits and Merge requests', function() {
|
||||||
done();
|
done();
|
||||||
}, 0);
|
}, 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('with pagination', () => {
|
||||||
|
it('should make an API request when using pagination', done => {
|
||||||
|
setTimeout(() => {
|
||||||
|
spyOn(vm, 'updateContent');
|
||||||
|
|
||||||
|
vm.store.state.pageInfo = {
|
||||||
|
page: 1,
|
||||||
|
total: 10,
|
||||||
|
perPage: 2,
|
||||||
|
nextPage: 2,
|
||||||
|
totalPages: 5,
|
||||||
|
};
|
||||||
|
|
||||||
|
vm.$nextTick(() => {
|
||||||
|
vm.$el.querySelector('.js-next-button a').click();
|
||||||
|
|
||||||
|
expect(vm.updateContent).toHaveBeenCalledWith({ page: '2' });
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('pipeline badge counts', () => {
|
describe('pipeline badge counts', () => {
|
||||||
|
|
Loading…
Reference in New Issue