Commit 01660209 authored by Filipa Lacerda's avatar Filipa Lacerda

Update state. Divide into smaller components

parent 059ad475
import pipelinesEmptyStateSVG from 'empty_states/icons/_pipelines_empty.svg';
export default {
props: {
helpPagePath: {
type: String,
required: true,
},
},
data() {
return {
pipelinesEmptyStateSVG,
};
},
template: `
<div class="row empty-state">
<div class="col-xs-12 pull-right">
<div class="svg-content">
${pipelinesEmptyStateSVG}
</div>
</div>
<div class="col-xs-12 center">
<div class="text-content">
<h4>Build with confidence</h4>
<p>
Continous Integration can help catch bugs by running your tests automatically,
while Continuous Deployment can help you deliver code to your product environment.
<a :href="helpPagePath" class="btn btn-info">
Get started with Pipelines
</a>
</p>
</div>
</div>
</div>
`,
};
import pipelinesErrorStateSVG from 'empty_states/icons/_pipelines_failed.svg';
export default {
data() {
return {
pipelinesErrorStateSVG,
};
},
template: `
<div class="row empty-state">
<div class="col-xs-12 pull-right">
<div class="svg-content">
${pipelinesErrorStateSVG}
</div>
</div>
<div class="col-xs-12 center">
<div class="text-content">
<h4>The API failed to fetch the pipelines.</h4>
</div>
</div>
</div>
`,
};
export default {
props: {
newPipelinePath: {
type: String,
required: true,
},
hasCIEnabled: {
type: Boolean,
required: true,
},
helpPagePath: {
type: String,
required: true,
},
ciLintPath: {
type: String,
required: true,
},
canCreatePipeline: {
type: Boolean,
required: true,
},
},
template: `
<div class="nav-controls">
<a
v-if="canCreatePipeline"
:href="newPipelinePath"
class="btn btn-create">
Run Pipeline
</a>
<a
v-if="!hasCIEnabled"
:href="helpPagePath"
class="btn btn-info">
Get started with Pipelines
</a>
<a
:href="ciLintPath"
class="btn btn-default">
CI Lint
</a>
</div>
`,
};
export default {
props: {
scope: {
type: String,
required: true,
},
count: {
type: Object,
required: true,
},
paths: {
type: Object,
required: true,
},
},
template: `
<ul class="nav-links">
<li :class="{ 'active': scope === 'all'}">
<a :href="paths.allPath">
All
<span class="badge js-totalbuilds-count">
{{count.all}}
</span>
</a>
</li>
<li class="js-pipelines-tab-pending"
:class="{ 'active': scope === 'pending'}">
<a :href="paths.pendingPath">
Pending
<span class="badge">
{{count.pending}}
</span>
</a>
</li>
<li class="js-pipelines-tab-running"
:class="{ 'active': scope === 'running'}">
<a :href="paths.runningPath">
Running
<span class="badge">
{{count.running}}
</span>
</a>
</li>
<li class="js-pipelines-tab-finished"
:class="{ 'active': scope === 'finished'}">
<a :href="paths.finishedPath">
Finished
<span class="badge">
{{count.finished}}
</span>
</a>
</li>
<li class="js-pipelines-tab-branches"
:class="{ 'active': scope === 'branches'}">
<a :href="paths.branchesPath">Branches</a>
</li>
<li class="js-pipelines-tab-tags"
:class="{ 'active': scope === 'tags'}">
<a :href="paths.tagsPath">Tags</a>
</li>
</ul>
`,
};
...@@ -9,20 +9,16 @@ $(() => new Vue({ ...@@ -9,20 +9,16 @@ $(() => new Vue({
el: document.querySelector('#pipelines-list-vue'), el: document.querySelector('#pipelines-list-vue'),
data() { data() {
const project = document.querySelector('.pipelines');
const store = new PipelinesStore(); const store = new PipelinesStore();
return { return {
store, store,
endpoint: project.dataset.url,
}; };
}, },
components: { components: {
'vue-pipelines': PipelinesComponent, 'vue-pipelines': PipelinesComponent,
}, },
template: ` template: `
<vue-pipelines <vue-pipelines :store="store" />
:endpoint="endpoint"
:store="store" />
`, `,
})); }));
...@@ -2,17 +2,19 @@ ...@@ -2,17 +2,19 @@
/* eslint-disable no-new */ /* eslint-disable no-new */
import Vue from 'vue'; import Vue from 'vue';
import '~/flash'; import '~/flash';
import pipelinesEmptyStateSVG from 'empty_states/icons/_pipelines_empty.svg';
import pipelinesErrorStateSVG from 'empty_states/icons/_pipelines_failed.svg';
import PipelinesService from './services/pipelines_service'; import PipelinesService from './services/pipelines_service';
import eventHub from './event_hub'; import eventHub from './event_hub';
import PipelinesTableComponent from '../vue_shared/components/pipelines_table'; import PipelinesTableComponent from '../vue_shared/components/pipelines_table';
import TablePaginationComponent from '../vue_shared/components/table_pagination'; import TablePaginationComponent from '../vue_shared/components/table_pagination';
import EmptyState from './components/empty_state';
import ErrorState from './components/error_state';
import NavigationTabs from './components/navigation_tabs';
import NavigationControls from './components/nav_controls';
export default { export default {
props: { props: {
endpoint: { store: {
type: String, type: Object,
required: true, required: true,
}, },
}, },
...@@ -20,6 +22,23 @@ export default { ...@@ -20,6 +22,23 @@ export default {
components: { components: {
'gl-pagination': TablePaginationComponent, 'gl-pagination': TablePaginationComponent,
'pipelines-table-component': PipelinesTableComponent, 'pipelines-table-component': PipelinesTableComponent,
'empty-state': EmptyState,
'error-state': ErrorState,
'navigation-tabs': NavigationTabs,
'navigation-controls': NavigationControls,
},
data() {
const pipelinesData = document.querySelector('#pipelines-list-vue').dataset;
return {
...pipelinesData,
state: this.store.state,
apiScope: 'all',
pagenum: 1,
pageRequest: false,
hasError: false,
};
}, },
computed: { computed: {
...@@ -28,7 +47,8 @@ export default { ...@@ -28,7 +47,8 @@ export default {
}, },
scope() { scope() {
return gl.utils.getParameterByName('scope'); const scope = gl.utils.getParameterByName('scope');
return scope === null ? 'all' : scope;
}, },
shouldRenderErrorState() { shouldRenderErrorState() {
...@@ -42,25 +62,28 @@ export default { ...@@ -42,25 +62,28 @@ export default {
* @return {Boolean} * @return {Boolean}
*/ */
shouldRenderEmptyState() { shouldRenderEmptyState() {
return !this.hasError && return !this.pageRequest &&
!this.pageRequest && ( !this.hasError &&
!this.pipelines.length && (this.scope === 'all' || this.scope === null) !this.state.pipelines.length &&
); (this.scope === 'all' || this.scope === null);
}, },
shouldRenderTable() { /**
return !this.hasError && * When a specific scope does not have pipelines we render a message.
!this.pageRequest && this.pipelines.length; *
* @return {Boolean}
*/
shouldRenderNoPipelinesMessage() {
return !this.pageRequest &&
!this.hasError &&
!this.state.pipelines.length &&
this.scope !== 'all' &&
this.scope !== null;
}, },
/** shouldRenderTable() {
* Header tabs should only be rendered when we receive an error or a successfull response with return !this.hasError &&
* pipelines. !this.pageRequest && this.state.pipelines.length;
*
* @return {Boolean}
*/
shouldRenderTabs() {
return !this.pageRequest && !this.hasError && this.pipelines.length;
}, },
/** /**
...@@ -70,24 +93,24 @@ export default { ...@@ -70,24 +93,24 @@ export default {
*/ */
shouldRenderPagination() { shouldRenderPagination() {
return !this.pageRequest && return !this.pageRequest &&
this.pipelines.length && this.state.pipelines.length &&
this.pageInfo.total > this.pageInfo.perPage; this.state.pageInfo.total > this.state.pageInfo.perPage;
}, },
},
data() { hasCIEnabled() {
const pipelinesData = document.querySelector('#pipelines-list-vue').dataset; return this.hasCi !== undefined;
},
return { paths() {
...pipelinesData, return {
state: this.store.state, allPath: this.allPath,
apiScope: 'all', pendingPath: this.pendingPath,
pagenum: 1, finishedPath: this.finishedPath,
pageRequest: false, runningPath: this.runningPath,
hasError: false, branchesPath: this.branchesPath,
pipelinesEmptyStateSVG, tagsPath: this.tagsPath,
pipelinesErrorStateSVG, };
}; },
}, },
created() { created() {
...@@ -147,144 +170,57 @@ export default { ...@@ -147,144 +170,57 @@ export default {
}, },
template: ` template: `
<div :class="cssClass"> <div
<div class="top-area" v-if="!shouldRenderEmptyState"> :class="cssClass"
<ul class="pipelines">
class="nav-links">
<div
<li :class="{ 'active': scope === null || scope === 'all'}"> class="top-area"
<a :href="allPath"> v-if="!pageRequest && !shouldRenderEmptyState">
All <navigation-tabs
</a> :scope="scope"
<span class="badge js-totalbuilds-count"> :count="state.count"
{{count.all}} :paths="paths" />
</span>
</li> <navigation-controls
<li :newPipelinePath="newPipelinePath"
class="js-pipelines-tab-pending" :hasCIEnabled="hasCIEnabled"
:class="{ 'active': scope === 'pending'}"> :helpPagePath="helpPagePath"
<a :href="pendingPath"> :ciLintPath="ciLintPath"
Pending :canCreatePipeline="canCreatePipelineParsed " />
</a>
<span class="badge">
{{count.pending}}
</span>
</li>
<li
class="js-pipelines-tab-running"
:class="{ 'active': scope === 'running'}">
<a :href="runningPath">
Running
</a>
<span class="badge">
{{count.running}}
</span>
</li>
<li
class="js-pipelines-tab-finished"
:class="{ 'active': scope === 'finished'}">
<a :href="finishedPath">
Finished
</a>
<span class="badge">
{{count.finished}}
</span>
</li>
<li
class="js-pipelines-tab-branches"
:class="{ 'active': scope === 'branches'}">
<a :href="branchesPath">Branches</a>
</li>
<li
class="js-pipelines-tab-tags"
:class="{ 'active': scope === 'tags'}">
<a :href="tagsPath">Tags</a>
</li>
</ul>
<div class="nav-controls">
<a
v-if="canCreatePipelineParsed"
:href="newPipelinePath"
class="btn btn-create">
Run Pipeline
</a>
<a
v-if="!hasCi"
:href="helpPagePath"
class="btn btn-info">
Get started with Pipelines
</a>
<a
:href="ciLintPath"
class="btn btn-default">
CI Lint
</a>
</div>
</div> </div>
<div class="pipelines realtime-loading" <div
class="realtime-loading"
v-if="pageRequest"> v-if="pageRequest">
<i class="fa fa-spinner fa-spin" aria-hidden="true"></i> <i class="fa fa-spinner fa-spin" aria-hidden="true"></i>
</div> </div>
<div v-if="shouldRenderEmptyState" <empty-state v-if="shouldRenderEmptyState" />
class="row empty-state">
<div class="col-xs-12 pull-right">
<div class="svg-content">
${pipelinesEmptyStateSVG}
</div>
</div>
<div class="col-xs-12 center">
<div class="text-content">
<h4>Build with confidence</h4>
<p>
Continous Integration can help catch bugs by running your tests automatically,
while Continuous Deployment can help you deliver code to your product environment.
<a :href="helpPagePath" class="btn btn-info">
Get started with Pipelines
</a>
</p>
</div>
</div>
</div>
<div v-if="shouldRenderErrorState" <error-state v-if="shouldRenderErrorState" />
class="row empty-state">
<div class="col-xs-12 pull-right"> <div
<div class="svg-content"> class="blank-state blank-state-no-icon"
${pipelinesErrorStateSVG} v-if="shouldRenderNoPipelinesMessage">
</div> <h2 class="blank-state-title js-blank-state-title">No pipelines to show.</h2>
</div>
<div class="col-xs-12 center">
<div class="text-content">
<h4>The API failed to fetch the pipelines.</h4>
</div>
</div>
</div> </div>
<div class="table-holder" <div
class="table-holder"
v-if="shouldRenderTable"> v-if="shouldRenderTable">
<pipelines-table-component :pipelines='pipelines'/>
<pipelines-table-component
:pipelines="state.pipelines"
:service="service"/>
</div> </div>
<gl-pagination <gl-pagination
v-if="shouldRenderPagination" v-if="shouldRenderPagination"
:pagenum="pagenum" :pagenum="pagenum"
:change="change" :change="change"
:count="count.all" :count="state.count.all"
:pageInfo="pageInfo"/> :pageInfo="state.pageInfo"/>
</div> </div>
`, `,
}; };
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
.realtime-loading { .realtime-loading {
font-size: 40px; font-size: 40px;
text-align: center; text-align: center;
margin: 0 auto;
} }
.stage { .stage {
......
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