summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorFilipa Lacerda <filipa@gitlab.com>2017-03-17 19:14:16 +0000
committerFilipa Lacerda <filipa@gitlab.com>2017-03-17 21:41:31 +0000
commit016602099b83dd23160748907d0dde08188c269f (patch)
tree57856b56f8a17a6b8a5b3533d98a6623b53606e6 /app
parent059ad4754c2370658a16eb2d26dd9bbeb1c35b5c (diff)
downloadgitlab-ce-016602099b83dd23160748907d0dde08188c269f.tar.gz
Update state. Divide into smaller components
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/vue_pipelines_index/components/empty_state.js39
-rw-r--r--app/assets/javascripts/vue_pipelines_index/components/error_state.js25
-rw-r--r--app/assets/javascripts/vue_pipelines_index/components/nav_controls.js52
-rw-r--r--app/assets/javascripts/vue_pipelines_index/components/navigation_tabs.js66
-rw-r--r--app/assets/javascripts/vue_pipelines_index/index.js6
-rw-r--r--app/assets/javascripts/vue_pipelines_index/pipelines.js250
-rw-r--r--app/assets/stylesheets/pages/pipelines.scss1
7 files changed, 277 insertions, 162 deletions
diff --git a/app/assets/javascripts/vue_pipelines_index/components/empty_state.js b/app/assets/javascripts/vue_pipelines_index/components/empty_state.js
new file mode 100644
index 00000000000..cfe23b65d55
--- /dev/null
+++ b/app/assets/javascripts/vue_pipelines_index/components/empty_state.js
@@ -0,0 +1,39 @@
+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>
+ `,
+};
diff --git a/app/assets/javascripts/vue_pipelines_index/components/error_state.js b/app/assets/javascripts/vue_pipelines_index/components/error_state.js
new file mode 100644
index 00000000000..9071ecdea73
--- /dev/null
+++ b/app/assets/javascripts/vue_pipelines_index/components/error_state.js
@@ -0,0 +1,25 @@
+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>
+ `,
+};
diff --git a/app/assets/javascripts/vue_pipelines_index/components/nav_controls.js b/app/assets/javascripts/vue_pipelines_index/components/nav_controls.js
new file mode 100644
index 00000000000..73eaaf6aa72
--- /dev/null
+++ b/app/assets/javascripts/vue_pipelines_index/components/nav_controls.js
@@ -0,0 +1,52 @@
+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>
+ `,
+};
diff --git a/app/assets/javascripts/vue_pipelines_index/components/navigation_tabs.js b/app/assets/javascripts/vue_pipelines_index/components/navigation_tabs.js
new file mode 100644
index 00000000000..a494d2459aa
--- /dev/null
+++ b/app/assets/javascripts/vue_pipelines_index/components/navigation_tabs.js
@@ -0,0 +1,66 @@
+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>
+ `,
+};
diff --git a/app/assets/javascripts/vue_pipelines_index/index.js b/app/assets/javascripts/vue_pipelines_index/index.js
index c35fc63e7b5..031b78b8410 100644
--- a/app/assets/javascripts/vue_pipelines_index/index.js
+++ b/app/assets/javascripts/vue_pipelines_index/index.js
@@ -9,20 +9,16 @@ $(() => new Vue({
el: document.querySelector('#pipelines-list-vue'),
data() {
- const project = document.querySelector('.pipelines');
const store = new PipelinesStore();
return {
store,
- endpoint: project.dataset.url,
};
},
components: {
'vue-pipelines': PipelinesComponent,
},
template: `
- <vue-pipelines
- :endpoint="endpoint"
- :store="store" />
+ <vue-pipelines :store="store" />
`,
}));
diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.js b/app/assets/javascripts/vue_pipelines_index/pipelines.js
index 4a729153bfa..64b8be78bc1 100644
--- a/app/assets/javascripts/vue_pipelines_index/pipelines.js
+++ b/app/assets/javascripts/vue_pipelines_index/pipelines.js
@@ -2,17 +2,19 @@
/* eslint-disable no-new */
import Vue from 'vue';
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 eventHub from './event_hub';
import PipelinesTableComponent from '../vue_shared/components/pipelines_table';
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 {
props: {
- endpoint: {
- type: String,
+ store: {
+ type: Object,
required: true,
},
},
@@ -20,6 +22,23 @@ export default {
components: {
'gl-pagination': TablePaginationComponent,
'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: {
@@ -28,7 +47,8 @@ export default {
},
scope() {
- return gl.utils.getParameterByName('scope');
+ const scope = gl.utils.getParameterByName('scope');
+ return scope === null ? 'all' : scope;
},
shouldRenderErrorState() {
@@ -42,25 +62,28 @@ export default {
* @return {Boolean}
*/
shouldRenderEmptyState() {
- return !this.hasError &&
- !this.pageRequest && (
- !this.pipelines.length && (this.scope === 'all' || this.scope === null)
- );
+ return !this.pageRequest &&
+ !this.hasError &&
+ !this.state.pipelines.length &&
+ (this.scope === 'all' || this.scope === null);
},
- shouldRenderTable() {
- return !this.hasError &&
- !this.pageRequest && this.pipelines.length;
+ /**
+ * When a specific scope does not have pipelines we render a message.
+ *
+ * @return {Boolean}
+ */
+ shouldRenderNoPipelinesMessage() {
+ return !this.pageRequest &&
+ !this.hasError &&
+ !this.state.pipelines.length &&
+ this.scope !== 'all' &&
+ this.scope !== null;
},
- /**
- * Header tabs should only be rendered when we receive an error or a successfull response with
- * pipelines.
- *
- * @return {Boolean}
- */
- shouldRenderTabs() {
- return !this.pageRequest && !this.hasError && this.pipelines.length;
+ shouldRenderTable() {
+ return !this.hasError &&
+ !this.pageRequest && this.state.pipelines.length;
},
/**
@@ -70,24 +93,24 @@ export default {
*/
shouldRenderPagination() {
return !this.pageRequest &&
- this.pipelines.length &&
- this.pageInfo.total > this.pageInfo.perPage;
+ this.state.pipelines.length &&
+ this.state.pageInfo.total > this.state.pageInfo.perPage;
},
- },
- data() {
- const pipelinesData = document.querySelector('#pipelines-list-vue').dataset;
+ hasCIEnabled() {
+ return this.hasCi !== undefined;
+ },
- return {
- ...pipelinesData,
- state: this.store.state,
- apiScope: 'all',
- pagenum: 1,
- pageRequest: false,
- hasError: false,
- pipelinesEmptyStateSVG,
- pipelinesErrorStateSVG,
- };
+ paths() {
+ return {
+ allPath: this.allPath,
+ pendingPath: this.pendingPath,
+ finishedPath: this.finishedPath,
+ runningPath: this.runningPath,
+ branchesPath: this.branchesPath,
+ tagsPath: this.tagsPath,
+ };
+ },
},
created() {
@@ -147,144 +170,57 @@ export default {
},
template: `
- <div :class="cssClass">
- <div class="top-area" v-if="!shouldRenderEmptyState">
- <ul
- class="nav-links">
-
- <li :class="{ 'active': scope === null || scope === 'all'}">
- <a :href="allPath">
- All
- </a>
- <span class="badge js-totalbuilds-count">
- {{count.all}}
- </span>
- </li>
- <li
- class="js-pipelines-tab-pending"
- :class="{ 'active': scope === 'pending'}">
- <a :href="pendingPath">
- Pending
- </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
+ :class="cssClass"
+ class="pipelines">
+
+ <div
+ class="top-area"
+ v-if="!pageRequest && !shouldRenderEmptyState">
+ <navigation-tabs
+ :scope="scope"
+ :count="state.count"
+ :paths="paths" />
+
+ <navigation-controls
+ :newPipelinePath="newPipelinePath"
+ :hasCIEnabled="hasCIEnabled"
+ :helpPagePath="helpPagePath"
+ :ciLintPath="ciLintPath"
+ :canCreatePipeline="canCreatePipelineParsed " />
</div>
- <div class="pipelines realtime-loading"
+ <div
+ class="realtime-loading"
v-if="pageRequest">
<i class="fa fa-spinner fa-spin" aria-hidden="true"></i>
</div>
- <div 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>
+ <empty-state v-if="shouldRenderEmptyState" />
- <div v-if="shouldRenderErrorState"
- 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>
+ <error-state v-if="shouldRenderErrorState" />
+
+ <div
+ class="blank-state blank-state-no-icon"
+ v-if="shouldRenderNoPipelinesMessage">
+ <h2 class="blank-state-title js-blank-state-title">No pipelines to show.</h2>
</div>
- <div class="table-holder"
+ <div
+ class="table-holder"
v-if="shouldRenderTable">
- <pipelines-table-component :pipelines='pipelines'/>
+
+ <pipelines-table-component
+ :pipelines="state.pipelines"
+ :service="service"/>
</div>
<gl-pagination
v-if="shouldRenderPagination"
:pagenum="pagenum"
:change="change"
- :count="count.all"
- :pageInfo="pageInfo"/>
+ :count="state.count.all"
+ :pageInfo="state.pageInfo"/>
</div>
`,
};
diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss
index 33b38ca6923..44ed6dcf33a 100644
--- a/app/assets/stylesheets/pages/pipelines.scss
+++ b/app/assets/stylesheets/pages/pipelines.scss
@@ -2,6 +2,7 @@
.realtime-loading {
font-size: 40px;
text-align: center;
+ margin: 0 auto;
}
.stage {