BigW Consortium Gitlab

Commit 7ef21460 by Filipa Lacerda

Transform vue_pipelines index into a non-dependent table component.

parent 7ad626e3
/* eslint-disable no-new */ /* eslint-disable no-new */
/* global Vue, VueResource */ /* global Vue, CommitsPipelineStore, PipelinesService, Flash */
//= require vue //= require vue
//= require_tree .
//= require vue
//= require vue-resource //= require vue-resource
//= require ./pipelines_store
//= require ./pipelines_service
//= require vue_shared/components/commit
//= require vue_shared/vue_resource_interceptor //= require vue_shared/vue_resource_interceptor
//= require vue_shared/components/pipelines_table //= require vue_shared/components/pipelines_table
...@@ -21,18 +20,23 @@ ...@@ -21,18 +20,23 @@
* Necessary SVG in the table are provided as props. This should be refactored * Necessary SVG in the table are provided as props. This should be refactored
* as soon as we have Webpack and can load them directly into JS files. * as soon as we have Webpack and can load them directly into JS files.
*/ */
(() => { $(() => {
window.gl = window.gl || {}; window.gl = window.gl || {};
gl.Commits = gl.Commits || {}; gl.commits = gl.commits || {};
gl.commits.pipelines = gl.commits.pipelines || {};
if (gl.Commits.PipelinesTableView) { if (gl.commits.PipelinesTableView) {
gl.Commits.PipelinesTableView.$destroy(true); gl.commits.PipelinesTableView.$destroy(true);
} }
gl.Commits.PipelinesTableView = new Vue({ gl.commits.pipelines.PipelinesTableView = new Vue({
el: document.querySelector('#commit-pipeline-table-view'), el: document.querySelector('#commit-pipeline-table-view'),
components: {
'pipelines-table-component': gl.pipelines.PipelinesTableComponent,
},
/** /**
* Accesses the DOM to provide the needed data. * Accesses the DOM to provide the needed data.
* Returns the necessary props to render `pipelines-table-component` component. * Returns the necessary props to render `pipelines-table-component` component.
...@@ -41,21 +45,70 @@ ...@@ -41,21 +45,70 @@
*/ */
data() { data() {
const pipelinesTableData = document.querySelector('#commit-pipeline-table-view').dataset; const pipelinesTableData = document.querySelector('#commit-pipeline-table-view').dataset;
const svgsData = document.querySelector('.pipeline-svgs').dataset;
const store = gl.commits.pipelines.PipelinesStore.create();
// Transform svgs DOMStringMap to a plain Object.
const svgsObject = Object.keys(svgsData).reduce((acc, element) => {
acc[element] = svgsData[element];
return acc;
}, {});
return { return {
scope: pipelinesTableData.pipelinesData, endpoint: pipelinesTableData.pipelinesData,
store: new CommitsPipelineStore(), svgs: svgsObject,
service: new PipelinesService(), store,
svgs: pipelinesTableData, state: store.state,
isLoading: false,
}; };
}, },
components: { /**
'pipelines-table-component': gl.pipelines.PipelinesTableComponent, * When the component is created the service to fetch the data will be
* initialized with the correct endpoint.
*
* 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.
*
*/
created() {
gl.pipelines.pipelinesService = new PipelinesService(this.endpoint);
this.isLoading = true;
return gl.pipelines.pipelinesService.all()
.then(response => response.json())
.then((json) => {
this.store.store(json);
this.isLoading = false;
}).catch(() => {
this.isLoading = false;
new Flash('An error occurred while fetching the pipelines.', 'alert');
});
}, },
template: ` template: `
<pipelines-table-component :scope='scope' :store='store' :svgs='svgs'></pipelines-table-component> <div>
<div class="pipelines realtime-loading" v-if='isLoading'>
<i class="fa fa-spinner fa-spin"></i>
</div>
<div class="blank-state blank-state-no-icon"
v-if="!isLoading && state.pipelines.length === 0">
<h2 class="blank-state-title js-blank-state-title">
You don't have any pipelines.
</h2>
Put get started with pipelines button here!!!
</div>
<div class="table-holder" v-if='!isLoading && state.pipelines.length > 0'>
<pipelines-table-component
:pipelines='state.pipelines'
:svgs='svgs'>
</pipelines-table-component>
</div>
</div>
`, `,
}); });
}); });
...@@ -5,12 +5,8 @@ ...@@ -5,12 +5,8 @@
* Pipelines service. * Pipelines service.
* *
* Used to fetch the data used to render the pipelines table. * Used to fetch the data used to render the pipelines table.
* Used Vue.Resource * Uses Vue.Resource
*/ */
window.gl = window.gl || {};
gl.pipelines = gl.pipelines || {};
class PipelinesService { class PipelinesService {
constructor(root) { constructor(root) {
Vue.http.options.root = root; Vue.http.options.root = root;
...@@ -36,42 +32,3 @@ class PipelinesService { ...@@ -36,42 +32,3 @@ class PipelinesService {
return this.pipelines.get(); return this.pipelines.get();
} }
} }
gl.pipelines.PipelinesService = PipelinesService;
// const pageValues = (headers) => {
// const normalized = gl.utils.normalizeHeaders(headers);
//
// const paginationInfo = {
// perPage: +normalized['X-PER-PAGE'],
// page: +normalized['X-PAGE'],
// total: +normalized['X-TOTAL'],
// totalPages: +normalized['X-TOTAL-PAGES'],
// nextPage: +normalized['X-NEXT-PAGE'],
// previousPage: +normalized['X-PREV-PAGE'],
// };
//
// return paginationInfo;
// };
// gl.PipelineStore = class {
// fetchDataLoop(Vue, pageNum, url, apiScope) {
// const goFetch = () =>
// this.$http.get(`${url}?scope=${apiScope}&page=${pageNum}`)
// .then((response) => {
// const pageInfo = pageValues(response.headers);
// this.pageInfo = Object.assign({}, this.pageInfo, pageInfo);
//
// const res = JSON.parse(response.body);
// this.count = Object.assign({}, this.count, res.count);
// this.pipelines = Object.assign([], this.pipelines, res);
//
// this.pageRequest = false;
// }, () => {
// this.pageRequest = false;
// return new Flash('Something went wrong on our end.');
// });
//
// goFetch();
// }
// };
...@@ -6,12 +6,14 @@ ...@@ -6,12 +6,14 @@
* Pipelines' Store for commits view. * Pipelines' Store for commits view.
* *
* Used to store the Pipelines rendered in the commit view in the pipelines table. * Used to store the Pipelines rendered in the commit view in the pipelines table.
*
* TODO: take care of timeago instances in here
*/ */
(() => { (() => {
const CommitPipelineStore = { window.gl = window.gl || {};
gl.commits = gl.commits || {};
gl.commits.pipelines = gl.commits.pipelines || {};
gl.commits.pipelines.PipelinesStore = {
state: {}, state: {},
create() { create() {
...@@ -20,11 +22,9 @@ ...@@ -20,11 +22,9 @@
return this; return this;
}, },
storePipelines(pipelines = []) { store(pipelines = []) {
this.state.pipelines = pipelines; this.state.pipelines = pipelines;
return pipelines; return pipelines;
}, },
}; };
return CommitPipelineStore;
})(); })();
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
type: Object, type: Object,
required: true, required: true,
}, },
//FIXME: DOMStringMap is non standard, let's use a plain object.
svgs: { svgs: {
type: DOMStringMap, type: DOMStringMap,
required: true, required: true,
......
/* eslint-disable no-param-reassign, no-new */ /* eslint-disable no-param-reassign */
/* global Vue */ /* global Vue */
/* global PipelinesService */
/* global Flash */
//= require vue_pipelines_index/status.js.es6 //=require ./pipelines_table_row
//= require vue_pipelines_index/pipeline_url.js.es6
//= require vue_pipelines_index/stage.js.es6 /**
//= require vue_pipelines_index/pipeline_actions.js.es6 * Pipelines Table Component
//= require vue_pipelines_index/time_ago.js.es6 *
//= require vue_pipelines_index/pipelines.js.es6 * Given an array of pipelines, renders a table.
*
*/
(() => { (() => {
window.gl = window.gl || {}; window.gl = window.gl || {};
...@@ -17,31 +17,10 @@ ...@@ -17,31 +17,10 @@
gl.pipelines.PipelinesTableComponent = Vue.component('pipelines-table-component', { gl.pipelines.PipelinesTableComponent = Vue.component('pipelines-table-component', {
props: { props: {
pipelines: {
/** type: Array,
* Object used to store the Pipelines to render.
* It's passed as a prop to allow different stores to use this Component.
* Different API calls can result in different responses, using a custom
* store allows us to use the same pipeline component.
*
* Note: All provided stores need to have a `storePipelines` method.
* Find a better way to do this.
*/
store: {
type: Object,
required: true,
default: () => ({}),
},
/**
* Will be used to fetch the needed data.
* This component is used in different and therefore different API calls
* to different endpoints will be made. To guarantee this is a reusable
* component, the endpoint must be provided.
*/
endpoint: {
type: String,
required: true, required: true,
default: [],
}, },
/** /**
...@@ -55,172 +34,10 @@ ...@@ -55,172 +34,10 @@
}, },
components: { components: {
'commit-component': gl.CommitComponent, 'pipelines-table-row-component': gl.pipelines.PipelinesTableRowComponent,
runningPipeline: gl.VueRunningPipeline,
pipelineActions: gl.VuePipelineActions,
'vue-stage': gl.VueStage,
pipelineUrl: gl.VuePipelineUrl,
pipelineHead: gl.VuePipelineHead,
statusScope: gl.VueStatusScope,
},
data() {
return {
state: this.store.state,
isLoading: false,
};
},
computed: {
/**
* If provided, returns the commit tag.
*
* @returns {Object|Undefined}
*/
commitAuthor() {
if (this.pipeline &&
this.pipeline.commit &&
this.pipeline.commit.author) {
return this.pipeline.commit.author;
}
return undefined;
},
/**
* If provided, returns the commit tag.
*
* @returns {String|Undefined}
*/
commitTag() {
if (this.model.last_deployment &&
this.model.last_deployment.tag) {
return this.model.last_deployment.tag;
}
return undefined;
}, },
/**
* If provided, returns the commit ref.
*
* @returns {Object|Undefined}
*/
commitRef() {
if (this.pipeline.ref) {
return Object.keys(this.pipeline.ref).reduce((accumulator, prop) => {
if (prop === 'url') {
accumulator.path = this.pipeline.ref[prop];
} else {
accumulator[prop] = this.pipeline.ref[prop];
}
return accumulator;
}, {});
}
return undefined;
},
/**
* If provided, returns the commit url.
*
* @returns {String|Undefined}
*/
commitUrl() {
if (this.pipeline.commit &&
this.pipeline.commit.commit_path) {
return this.pipeline.commit.commit_path;
}
return undefined;
},
/**
* If provided, returns the commit short sha.
*
* @returns {String|Undefined}
*/
commitShortSha() {
if (this.pipeline.commit &&
this.pipeline.commit.short_id) {
return this.pipeline.commit.short_id;
}
return undefined;
},
/**
* If provided, returns the commit title.
*
* @returns {String|Undefined}
*/
commitTitle() {
if (this.pipeline.commit &&
this.pipeline.commit.title) {
return this.pipeline.commit.title;
}
return undefined;
},
/**
* Figure this out!
*/
author(pipeline) {
if (!pipeline.commit) return { avatar_url: '', web_url: '', username: '' };
if (pipeline.commit.author) return pipeline.commit.author;
return {
avatar_url: pipeline.commit.author_gravatar_url,
web_url: `mailto:${pipeline.commit.author_email}`,
username: pipeline.commit.author_name,
};
},
/**
* Figure this out
*/
match(string) {
return string.replace(/_([a-z])/g, (m, w) => w.toUpperCase());
},
},
/**
* When the component is created the service to fetch the data will be
* initialized with the correct endpoint.
*
* 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.
*
*/
created() {
gl.pipelines.pipelinesService = new PipelinesService(this.endpoint);
this.isLoading = true;
return gl.pipelines.pipelinesService.all()
.then(resp => resp.json())
.then((json) => {
this.store.storePipelines(json);
this.isLoading = false;
}).catch(() => {
this.isLoading = false;
new Flash('An error occurred while fetching the pipelines.', 'alert');
});
},
// this need to be reusable between the 3 tables :/
template: ` template: `
<div>
<div class="pipelines realtime-loading" v-if='isLoading'>
<i class="fa fa-spinner fa-spin"></i>
</div>
<div class="blank-state blank-state-no-icon"
v-if="!isLoading && state.pipelines.length === 0">
<h2 class="blank-state-title js-blank-state-title">
You don't have any pipelines.
</h2>
Put get started with pipelines button here!!!
</div>
<div class="table-holder" v-if='!isLoading state.pipelines.length > 0'>
<table class="table ci-table"> <table class="table ci-table">
<thead> <thead>
<tr> <tr>
...@@ -233,41 +50,15 @@ ...@@ -233,41 +50,15 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr class="commit" v-for='pipeline in state.pipelines'> <template v-for="model in pipelines"
<status-scope v-bind:model="model">
:pipeline='pipeline' <tr
:match='match' is="pipelines-table-row-component"
:svgs='svgs'> :pipeline="model"
</status-scope> :svgs="svgs"></tr>
</template>
<pipeline-url :pipeline='pipeline'></pipeline-url>
<td>
<commit-component
:tag="commitTag"
:commit-ref="commitRef"
:commit-url="commitUrl"
:short-sha="commitShortSha"
:title="commitTitle"
:author="commitAuthor"
:commit-icon-svg="commitIconSvg">
</commit-component>
</td>
<td class="stage-cell">
<div class="stage-container dropdown js-mini-pipeline-graph" v-for='stage in pipeline.details.stages'>
<vue-stage :stage='stage' :svgs='svgs' :match='match'></vue-stage>
</div>
</td>
<time-ago :pipeline='pipeline' :svgs='svgs'></time-ago>
<pipeline-actions :pipeline='pipeline' :svgs='svgs'></pipeline-actions>
</tr>
</tbody> </tbody>
</table> </table>
</div>
</div>
`, `,
}); });
})(); })();
/* eslint-disable no-param-reassign */
/* global Vue */
//= require vue_pipelines_index/status
//= require vue_pipelines_index/pipeline_url
//= require vue_pipelines_index/stage
//= require vue_shared/components/commit
//= require vue_pipelines_index/pipeline_actions
//= require vue_pipelines_index/time_ago
(() => {
window.gl = window.gl || {};
gl.pipelines = gl.pipelines || {};
gl.pipelines.PipelinesTableRowComponent = Vue.component('pipelines-table-row-component', {
props: {
pipeline: {
type: Object,
required: true,
default: () => ({}),
},
/**
* Remove this. Find a better way to do this. don't want to provide this 3 times.
*/
svgs: {
type: Object,
required: true,
default: () => ({}),
},
},
components: {
'commit-component': gl.CommitComponent,
runningPipeline: gl.VueRunningPipeline,
pipelineActions: gl.VuePipelineActions,
'vue-stage': gl.VueStage,
pipelineUrl: gl.VuePipelineUrl,
pipelineHead: gl.VuePipelineHead,
statusScope: gl.VueStatusScope,
},
computed: {
/**
* If provided, returns the commit tag.
* Needed to render the commit component column.
*
* @returns {Object|Undefined}
*/
commitAuthor() {
if (this.pipeline &&
this.pipeline.commit &&
this.pipeline.commit.author) {
return this.pipeline.commit.author;
}
return undefined;
},
/**
* If provided, returns the commit tag.
* Needed to render the commit component column.
*
* @returns {String|Undefined}
*/
commitTag() {
// if (this.model.last_deployment &&
// this.model.last_deployment.tag) {
// return this.model.last_deployment.tag;
// }
return undefined;
},
/**
* If provided, returns the commit ref.
* Needed to render the commit component column.
*
* @returns {Object|Undefined}
*/
commitRef() {
if (this.pipeline.ref) {
return Object.keys(this.pipeline.ref).reduce((accumulator, prop) => {
if (prop === 'url') {
accumulator.path = this.pipeline.ref[prop];
} else {
accumulator[prop] = this.pipeline.ref[prop];
}
return accumulator;
}, {});
}
return undefined;
},
/**
* If provided, returns the commit url.
* Needed to render the commit component column.
*
* @returns {String|Undefined}
*/
commitUrl() {
if (this.pipeline.commit &&
this.pipeline.commit.commit_path) {
return this.pipeline.commit.commit_path;
}
return undefined;
},
/**
* If provided, returns the commit short sha.
* Needed to render the commit component column.
*
* @returns {String|Undefined}
*/
commitShortSha() {
if (this.pipeline.commit &&
this.pipeline.commit.short_id) {
return this.pipeline.commit.short_id;
}
return undefined;
},
/**
* If provided, returns the commit title.
* Needed to render the commit component column.
*
* @returns {String|Undefined}
*/
commitTitle() {
if (this.pipeline.commit &&
this.pipeline.commit.title) {
return this.pipeline.commit.title;
}
return undefined;
},
/**
* Figure this out!
* Needed to render the commit component column.
*/
author(pipeline) {
if (!pipeline.commit) return { avatar_url: '', web_url: '', username: '' };
if (pipeline.commit.author) return pipeline.commit.author;
return {
avatar_url: pipeline.commit.author_gravatar_url,
web_url: `mailto:${pipeline.commit.author_email}`,
username: pipeline.commit.author_name,
};
},
},
methods: {
match(string) {
return string.replace(/_([a-z])/g, (m, w) => w.toUpperCase());
},
},
template: `
<tr class="commit">
<status-scope
:pipeline='pipeline'
:svgs='svgs'
:match="match">
</status-scope>
<pipeline-url :pipeline='pipeline'></pipeline-url>
<td>
<commit-component
:tag="commitTag"
:commit-ref="commitRef"
:commit-url="commitUrl"
:short-sha="commitShortSha"
:title="commitTitle"
:author="commitAuthor"
:commit-icon-svg="svgs.commitIconSvg">
</commit-component>
</td>
<td class="stage-cell">
<div class="stage-container dropdown js-mini-pipeline-graph" v-for='stage in pipeline.details.stages'>
<vue-stage :stage='stage' :svgs='svgs' :match='match'></vue-stage>
</div>
</td>
<time-ago :pipeline='pipeline' :svgs='svgs'></time-ago>
<pipeline-actions :pipeline='pipeline' :svgs='svgs'></pipeline-actions>
</tr>
`,
});
})();
...@@ -3,9 +3,6 @@ ...@@ -3,9 +3,6 @@
= render 'commit_box' = render 'commit_box'
= render 'ci_menu' = render 'ci_menu'
- content_for :page_specific_javascripts do
= page_specific_javascript_tag("commit/pipelines/pipelines_bundle.js")
#commit-pipeline-table-view{ data: { pipelines_data: pipelines_namespace_project_commit_path(@project.namespace, @project, @commit.id)}} #commit-pipeline-table-view{ data: { pipelines_data: pipelines_namespace_project_commit_path(@project.namespace, @project, @commit.id)}}
.pipeline-svgs{ data: { "commit_icon_svg" => custom_icon("icon_commit"), .pipeline-svgs{ data: { "commit_icon_svg" => custom_icon("icon_commit"),
"icon_status_canceled" => custom_icon("icon_status_canceled"), "icon_status_canceled" => custom_icon("icon_status_canceled"),
...@@ -28,3 +25,6 @@ ...@@ -28,3 +25,6 @@
"icon_timer" => custom_icon("icon_timer"), "icon_timer" => custom_icon("icon_timer"),
"icon_status_manual" => custom_icon("icon_status_manual"), "icon_status_manual" => custom_icon("icon_status_manual"),
} } } }
- content_for :page_specific_javascripts do
= page_specific_javascript_tag('commit/pipelines/pipelines_bundle.js')
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment