From e8eac643b3da60f2694b8e2341bb84fc64e1116b Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Mon, 13 Mar 2017 17:37:18 +0000 Subject: [PATCH 01/12] Adds empty state for pipelines table --- .../vue_pipelines_index/pipelines.js | 45 +++++++++++++++++-- .../javascripts/vue_pipelines_index/store.js | 1 + .../empty_states/icons/_pipelines_empty.svg | 1 + .../empty_states/icons/_pipelines_failed.svg | 1 + 4 files changed, 44 insertions(+), 4 deletions(-) create mode 100644 app/views/shared/empty_states/icons/_pipelines_empty.svg create mode 100644 app/views/shared/empty_states/icons/_pipelines_failed.svg diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.js b/app/assets/javascripts/vue_pipelines_index/pipelines.js index 601ef41e917..d835a537979 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipelines.js +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.js @@ -1,5 +1,7 @@ /* global Vue, gl */ /* eslint-disable no-param-reassign */ +import pipelinesEmptyStateSVG from 'empty_states/icons/_pipelines_empty.svg'; +import pipelinesErrorStateSVG from 'empty_states/icons/_pipelines_failed.svg'; window.Vue = require('vue'); require('../vue_shared/components/table_pagination'); @@ -25,6 +27,9 @@ const CommitPipelinesStoreWithTimeAgo = require('../commit/pipelines/pipelines_s pagenum: 1, count: {}, pageRequest: false, + hasError: false, + pipelinesEmptyStateSVG, + pipelinesErrorStateSVG, }; }, props: ['scope', 'store'], @@ -43,6 +48,16 @@ const CommitPipelinesStoreWithTimeAgo = require('../commit/pipelines/pipelines_s } }, + computed: { + shouldRenderErrorState() { + return this.hasError && !this.pageRequest; + }, + + shouldRenderEmptyState() { + return !this.hasError && !this.pageRequest && !this.pipelines.length; + }, + }, + methods: { /** * Will change the page number and update the URL. @@ -62,11 +77,33 @@ const CommitPipelinesStoreWithTimeAgo = require('../commit/pipelines/pipelines_s +
+ +
+
+ ${pipelinesEmptyStateSVG} +
+
+ +
+
+

Build with confidence

+

+ Continous Integration can help catch bugs by running your tests automatically, + while Continuous Deployment can help you deliver code to your product environment. + + + Get started with Pipelines + +

+
+
+
+
-

- No pipelines to show -

+ v-if="shouldRenderErrorState"> + ${pipelinesErrorStateSVG}
diff --git a/app/assets/javascripts/vue_pipelines_index/store.js b/app/assets/javascripts/vue_pipelines_index/store.js index 909007267b9..08327ae146f 100644 --- a/app/assets/javascripts/vue_pipelines_index/store.js +++ b/app/assets/javascripts/vue_pipelines_index/store.js @@ -24,6 +24,7 @@ this.pageRequest = false; }, () => { this.pageRequest = false; + this.hasError = true; return new Flash('An error occurred while fetching the pipelines, please reload the page again.'); }); } diff --git a/app/views/shared/empty_states/icons/_pipelines_empty.svg b/app/views/shared/empty_states/icons/_pipelines_empty.svg new file mode 100644 index 00000000000..8119d5bebe0 --- /dev/null +++ b/app/views/shared/empty_states/icons/_pipelines_empty.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/views/shared/empty_states/icons/_pipelines_failed.svg b/app/views/shared/empty_states/icons/_pipelines_failed.svg new file mode 100644 index 00000000000..7dbabf7e4ef --- /dev/null +++ b/app/views/shared/empty_states/icons/_pipelines_failed.svg @@ -0,0 +1 @@ + \ No newline at end of file From d51a5f0b4f0d6ff6fb634c8508f22a60296c7cdb Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Mon, 13 Mar 2017 17:39:57 +0000 Subject: [PATCH 02/12] Renders failed svg when an error occurred --- .../vue_pipelines_index/pipelines.js | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.js b/app/assets/javascripts/vue_pipelines_index/pipelines.js index d835a537979..512771b4e30 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipelines.js +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.js @@ -101,9 +101,20 @@ const CommitPipelinesStoreWithTimeAgo = require('../commit/pipelines/pipelines_s
-
- ${pipelinesErrorStateSVG} +
+ +
+
+ ${pipelinesErrorStateSVG} +
+
+ +
+
+

The API failed to fetch the pipelines.

+
+
@@ -115,9 +126,7 @@ const CommitPipelinesStoreWithTimeAgo = require('../commit/pipelines/pipelines_s :pagenum='pagenum' :change='change' :count='count.all' - :pageInfo='pageInfo' - > - + :pageInfo='pageInfo'/>
`, }); From d3732b5529249472ce0de4fbad36e3567f6cee54 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Tue, 14 Mar 2017 09:30:57 +0000 Subject: [PATCH 03/12] Moves tabs into Vue Component --- .../javascripts/vue_pipelines_index/index.js | 10 +- .../vue_pipelines_index/pipelines.js | 144 +++++++++++++++--- app/views/projects/pipelines/index.html.haml | 65 ++------ 3 files changed, 145 insertions(+), 74 deletions(-) diff --git a/app/assets/javascripts/vue_pipelines_index/index.js b/app/assets/javascripts/vue_pipelines_index/index.js index a90bd1518e9..6c1554b4c9d 100644 --- a/app/assets/javascripts/vue_pipelines_index/index.js +++ b/app/assets/javascripts/vue_pipelines_index/index.js @@ -7,13 +7,10 @@ require('../vue_shared/vue_resource_interceptor'); require('./pipelines'); $(() => new Vue({ - el: document.querySelector('.vue-pipelines-index'), + el: document.querySelector('#pipelines-list-vue'), data() { - const project = document.querySelector('.pipelines'); - return { - scope: project.dataset.url, store: new gl.PipelineStore(), }; }, @@ -21,9 +18,6 @@ $(() => new Vue({ 'vue-pipelines': gl.VuePipelines, }, template: ` - - + `, })); diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.js b/app/assets/javascripts/vue_pipelines_index/pipelines.js index 512771b4e30..e9b99fede10 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipelines.js +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.js @@ -18,10 +18,11 @@ const CommitPipelinesStoreWithTimeAgo = require('../commit/pipelines/pipelines_s }, data() { + const pipelinesData = document.querySelector('#pipelines-list-vue').dataset; + return { + ...pipelinesData, pipelines: [], - timeLoopInterval: '', - intervalId: '', apiScope: 'all', pageInfo: {}, pagenum: 1, @@ -39,7 +40,7 @@ const CommitPipelinesStoreWithTimeAgo = require('../commit/pipelines/pipelines_s if (pagenum) this.pagenum = pagenum; if (scope) this.apiScope = scope; - this.store.fetchDataLoop.call(this, Vue, this.pagenum, this.scope, this.apiScope); + this.store.fetchDataLoop.call(this, Vue, this.pagenum, this.endpoint, this.apiScope); }, beforeUpdate() { @@ -49,12 +50,56 @@ const CommitPipelinesStoreWithTimeAgo = require('../commit/pipelines/pipelines_s }, computed: { + canCreatePipelineParsed() { + return gl.utils.convertPermissionToBoolean(this.canCreatePipeline); + }, + + scope() { + return gl.utils.getParameterByName('scope'); + }, + shouldRenderErrorState() { return this.hasError && !this.pageRequest; }, + + /** + * The empty state should only be rendered when the request is made to fetch all pipelines + * and none is returned. + * + * @return {Boolean} + */ shouldRenderEmptyState() { - return !this.hasError && !this.pageRequest && !this.pipelines.length; + return !this.hasError && + !this.pageRequest && ( + !this.pipelines.length && (this.scope === 'all' || this.scope === null) + ); + }, + + shouldRenderTable() { + return !this.hasError && + !this.pageRequest && this.pipelines.length; + }, + + /** + * 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; + }, + + /** + * Pagination should only be rendered when there is more than one page. + * + * @return {Boolean} + */ + shouldRenderPagination() { + return !this.pageRequest && + this.pipelines.length && + this.pageInfo.total > this.pageInfo.perPage; }, }, @@ -72,14 +117,80 @@ const CommitPipelinesStoreWithTimeAgo = require('../commit/pipelines/pipelines_s }, }, template: ` -
-
- +
+
+ + + +
+ +
+
-
${pipelinesEmptyStateSVG} @@ -92,8 +203,7 @@ const CommitPipelinesStoreWithTimeAgo = require('../commit/pipelines/pipelines_s

Continous Integration can help catch bugs by running your tests automatically, while Continuous Deployment can help you deliver code to your product environment. - - + Get started with Pipelines

@@ -103,7 +213,6 @@ const CommitPipelinesStoreWithTimeAgo = require('../commit/pipelines/pipelines_s
-
${pipelinesErrorStateSVG} @@ -117,16 +226,17 @@ const CommitPipelinesStoreWithTimeAgo = require('../commit/pipelines/pipelines_s
-
+
+ v-if="shouldRenderPagination" + :pagenum="pagenum" + :change="change" + :count="count.all" + :pageInfo="pageInfo"/>
`, }); diff --git a/app/views/projects/pipelines/index.html.haml b/app/views/projects/pipelines/index.html.haml index 5d59ce06612..38cea4429ba 100644 --- a/app/views/projects/pipelines/index.html.haml +++ b/app/views/projects/pipelines/index.html.haml @@ -2,53 +2,20 @@ - page_title "Pipelines" = render "projects/pipelines/head" -%div{ class: container_class } - .top-area - %ul.nav-links - %li.js-pipelines-tab-all{ class: active_when(@scope.nil?) }> - = link_to project_pipelines_path(@project) do - All - %span.badge.js-totalbuilds-count - = number_with_delimiter(@pipelines_count) +- content_for :page_specific_javascripts do + = page_specific_javascript_bundle_tag("common_vue") + = page_specific_javascript_bundle_tag("vue_pipelines") - %li.js-pipelines-tab-pending{ class: active_when(@scope == 'pending') }> - = link_to project_pipelines_path(@project, scope: :pending) do - Pending - %span.badge - = number_with_delimiter(@pending_count) - - %li.js-pipelines-tab-running{ class: active_when(@scope == 'running') }> - = link_to project_pipelines_path(@project, scope: :running) do - Running - %span.badge.js-running-count - = number_with_delimiter(@running_count) - - %li.js-pipelines-tab-finished{ class: active_when(@scope == 'finished') }> - = link_to project_pipelines_path(@project, scope: :finished) do - Finished - %span.badge - = number_with_delimiter(@finished_count) - - %li.js-pipelines-tab-branches{ class: active_when(@scope == 'branches') }> - = link_to project_pipelines_path(@project, scope: :branches) do - Branches - - %li.js-pipelines-tab-tags{ class: active_when(@scope == 'tags') }> - = link_to project_pipelines_path(@project, scope: :tags) do - Tags - - .nav-controls - - if can? current_user, :create_pipeline, @project - = link_to new_namespace_project_pipeline_path(@project.namespace, @project), class: 'btn btn-create' do - Run pipeline - - - unless @repository.gitlab_ci_yml - = link_to 'Get started with Pipelines', help_page_path('ci/quick_start/README'), class: 'btn btn-info' - - = link_to ci_lint_path, class: 'btn btn-default' do - %span CI Lint - .content-list.pipelines{ data: { url: namespace_project_pipelines_path(@project.namespace, @project, format: :json) } } - .vue-pipelines-index - -= page_specific_javascript_bundle_tag('common_vue') -= page_specific_javascript_bundle_tag('vue_pipelines') +#pipelines-list-vue{ data: { endpoint: namespace_project_pipelines_path(@project.namespace, @project, format: :json), + "css-class" => container_class, + "help-page-path" => help_page_path('ci/quick_start/README'), + "new-pipeline-path" => new_namespace_project_pipeline_path(@project.namespace, @project), + "can-create-pipeline" => can?(current_user, :create_pipeline, @project).to_s, + "all-path" => project_pipelines_path(@project), + "pending-path" => project_pipelines_path(@project, scope: :pending), + "running-path" => project_pipelines_path(@project, scope: :running), + "finished-path" => project_pipelines_path(@project, scope: :finished), + "branches-path" => project_pipelines_path(@project, scope: :branches), + "tags-path" => project_pipelines_path(@project, scope: :tags), + "has-ci" => @repository.gitlab_ci_yml, + "ci-lint-path" => ci_lint_path } } From 6fb6632110ccec9c7ad64217647e17a29bdd66e3 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Wed, 15 Mar 2017 21:51:44 +0000 Subject: [PATCH 04/12] Adds counters to badges --- .../vue_pipelines_index/pipelines.js | 35 +++++++++++++++---- 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.js b/app/assets/javascripts/vue_pipelines_index/pipelines.js index e9b99fede10..ffcf3744233 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipelines.js +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.js @@ -26,7 +26,12 @@ const CommitPipelinesStoreWithTimeAgo = require('../commit/pipelines/pipelines_s apiScope: 'all', pageInfo: {}, pagenum: 1, - count: {}, + count: { + all: 0, + pending: 0, + running: 0, + finished: 0, + }, pageRequest: false, hasError: false, pipelinesEmptyStateSVG, @@ -127,6 +132,7 @@ const CommitPipelinesStoreWithTimeAgo = require('../commit/pipelines/pipelines_s All + {{count.all}}
  • Pending - + + + {{count.pending}} +
  • - Running - + + + Running + + + + {{count.running}} +
  • +
  • - Finished - + + + Finished + + + {{count.finished}} +
  • +
  • Branches
  • +
  • From 016602099b83dd23160748907d0dde08188c269f Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Fri, 17 Mar 2017 19:14:16 +0000 Subject: [PATCH 05/12] Update state. Divide into smaller components --- .../components/empty_state.js | 39 +++ .../components/error_state.js | 25 ++ .../components/nav_controls.js | 52 ++++ .../components/navigation_tabs.js | 66 +++++ .../javascripts/vue_pipelines_index/index.js | 6 +- .../vue_pipelines_index/pipelines.js | 246 +++++++----------- app/assets/stylesheets/pages/pipelines.scss | 1 + 7 files changed, 275 insertions(+), 160 deletions(-) create mode 100644 app/assets/javascripts/vue_pipelines_index/components/empty_state.js create mode 100644 app/assets/javascripts/vue_pipelines_index/components/error_state.js create mode 100644 app/assets/javascripts/vue_pipelines_index/components/nav_controls.js create mode 100644 app/assets/javascripts/vue_pipelines_index/components/navigation_tabs.js 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: ` +
    +
    +
    + ${pipelinesEmptyStateSVG} +
    +
    + +
    +
    +

    Build with confidence

    +

    + Continous Integration can help catch bugs by running your tests automatically, + while Continuous Deployment can help you deliver code to your product environment. + + Get started with Pipelines + +

    +
    +
    +
    + `, +}; 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: ` +
    +
    +
    + ${pipelinesErrorStateSVG} +
    +
    + +
    +
    +

    The API failed to fetch the pipelines.

    +
    +
    +
    + `, +}; 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: ` + + `, +}; 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: ` + + `, +}; 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: ` - + `, })); 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); + }, + + /** + * 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; }, shouldRenderTable() { return !this.hasError && - !this.pageRequest && this.pipelines.length; - }, - - /** - * 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; + !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: ` -
    -
    - - - +
    -
    -
    -
    -
    - ${pipelinesEmptyStateSVG} -
    -
    + -
    -
    -

    Build with confidence

    -

    - Continous Integration can help catch bugs by running your tests automatically, - while Continuous Deployment can help you deliver code to your product environment. - - Get started with Pipelines - -

    -
    -
    + + +
    +

    No pipelines to show.

    -
    -
    -
    - ${pipelinesErrorStateSVG} -
    -
    - -
    -
    -

    The API failed to fetch the pipelines.

    -
    -
    -
    - -
    - + +
    + :count="state.count.all" + :pageInfo="state.pageInfo"/>
    `, }; 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 { From 9d1ab1e9bd474e467c75cf7a1f7b728d6832075c Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Fri, 17 Mar 2017 23:07:37 +0000 Subject: [PATCH 06/12] Add error state to commits and merge requests pipelines table --- .../commit/pipelines/pipelines_table.js | 17 +++++++++++------ .../vue_pipelines_index/pipelines.js | 3 ++- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/app/assets/javascripts/commit/pipelines/pipelines_table.js b/app/assets/javascripts/commit/pipelines/pipelines_table.js index 832c4b1bd2a..29ee3e5e67b 100644 --- a/app/assets/javascripts/commit/pipelines/pipelines_table.js +++ b/app/assets/javascripts/commit/pipelines/pipelines_table.js @@ -5,6 +5,7 @@ import PipelinesTableComponent from '../../vue_shared/components/pipelines_table import PipelinesService from '../../vue_pipelines_index/services/pipelines_service'; import PipelineStore from '../../vue_pipelines_index/stores/pipelines_store'; import eventHub from '../../vue_pipelines_index/event_hub'; +import ErrorState from '../../vue_pipelines_index/components/error_state'; import '../../lib/utils/common_utils'; import '../../vue_shared/vue_resource_interceptor'; @@ -22,6 +23,7 @@ import '../../vue_shared/vue_resource_interceptor'; export default Vue.component('pipelines-table', { components: { 'pipelines-table-component': PipelinesTableComponent, + 'error-state': ErrorState, }, /** @@ -39,9 +41,16 @@ export default Vue.component('pipelines-table', { store, state: store.state, isLoading: false, + hasError: false, }; }, + computed: { + shouldRenderErrorState() { + return this.hasError && !this.pageRequest; + }, + }, + /** * When the component is about to be mounted, tell the service to fetch the data * @@ -80,6 +89,7 @@ export default Vue.component('pipelines-table', { this.isLoading = false; }) .catch(() => { + this.hasError = true; this.isLoading = false; new Flash('An error occurred while fetching the pipelines, please reload the page again.'); }); @@ -92,12 +102,7 @@ export default Vue.component('pipelines-table', {
    -
    -

    - No pipelines to show -

    -
    +
    diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.js b/app/assets/javascripts/vue_pipelines_index/pipelines.js index 64b8be78bc1..87242ff0369 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipelines.js +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.js @@ -163,6 +163,7 @@ export default { this.pageRequest = false; }) .catch(() => { + this.hasError = true; this.pageRequest = false; new Flash('An error occurred while fetching the pipelines, please reload the page again.'); }); @@ -196,7 +197,7 @@ export default {
    - + From 2c85a20482c2e33f307ad8faf60e41e199aa25b8 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Fri, 17 Mar 2017 23:15:28 +0000 Subject: [PATCH 07/12] Adds changelog --- changelogs/unreleased/27574-pipelines-empty-state.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 changelogs/unreleased/27574-pipelines-empty-state.yml diff --git a/changelogs/unreleased/27574-pipelines-empty-state.yml b/changelogs/unreleased/27574-pipelines-empty-state.yml new file mode 100644 index 00000000000..c26ea97205f --- /dev/null +++ b/changelogs/unreleased/27574-pipelines-empty-state.yml @@ -0,0 +1,4 @@ +--- +title: Adds empty and error state to pipelines +merge_request: +author: From 446b59dd4ee88f8ef86272c39408560a0107c48a Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Mon, 20 Mar 2017 15:36:02 +0000 Subject: [PATCH 08/12] Adds tests to new empty and error states --- .../commit/pipelines/pipelines_table.js | 9 ++ .../components/empty_state.js | 8 +- .../components/error_state.js | 18 +-- .../components/navigation_tabs.js | 4 +- .../vue_pipelines_index/pipelines.js | 80 +++++++------ .../projects/commit/_pipelines_list.haml | 1 + app/views/projects/pipelines/index.html.haml | 7 +- .../projects/pipelines/pipelines_spec.rb | 2 +- .../commit/pipelines/pipelines_spec.js | 4 +- spec/javascripts/fixtures/pipelines.html.haml | 14 +++ .../vue_pipelines_index/empty_state_spec.js | 38 ++++++ .../vue_pipelines_index/error_state_spec.js | 23 ++++ .../vue_pipelines_index/mock_data.js | 107 +++++++++++++++++ .../vue_pipelines_index/nav_controls_spec.js | 93 +++++++++++++++ .../vue_pipelines_index/pipelines_spec.js | 111 ++++++++++++++++++ 15 files changed, 465 insertions(+), 54 deletions(-) create mode 100644 spec/javascripts/fixtures/pipelines.html.haml create mode 100644 spec/javascripts/vue_pipelines_index/empty_state_spec.js create mode 100644 spec/javascripts/vue_pipelines_index/error_state_spec.js create mode 100644 spec/javascripts/vue_pipelines_index/mock_data.js create mode 100644 spec/javascripts/vue_pipelines_index/nav_controls_spec.js create mode 100644 spec/javascripts/vue_pipelines_index/pipelines_spec.js diff --git a/app/assets/javascripts/commit/pipelines/pipelines_table.js b/app/assets/javascripts/commit/pipelines/pipelines_table.js index 29ee3e5e67b..189dd2c7dce 100644 --- a/app/assets/javascripts/commit/pipelines/pipelines_table.js +++ b/app/assets/javascripts/commit/pipelines/pipelines_table.js @@ -5,6 +5,7 @@ import PipelinesTableComponent from '../../vue_shared/components/pipelines_table import PipelinesService from '../../vue_pipelines_index/services/pipelines_service'; import PipelineStore from '../../vue_pipelines_index/stores/pipelines_store'; import eventHub from '../../vue_pipelines_index/event_hub'; +import EmptyState from '../../vue_pipelines_index/components/empty_state'; import ErrorState from '../../vue_pipelines_index/components/error_state'; import '../../lib/utils/common_utils'; import '../../vue_shared/vue_resource_interceptor'; @@ -24,6 +25,7 @@ export default Vue.component('pipelines-table', { components: { 'pipelines-table-component': PipelinesTableComponent, 'error-state': ErrorState, + 'empty-state': EmptyState, }, /** @@ -38,6 +40,7 @@ export default Vue.component('pipelines-table', { return { endpoint: pipelinesTableData.endpoint, + helpPagePath: pipelinesTableData.helpPagePath, store, state: store.state, isLoading: false, @@ -49,6 +52,10 @@ export default Vue.component('pipelines-table', { shouldRenderErrorState() { return this.hasError && !this.pageRequest; }, + + shouldRenderEmptyState() { + return !this.state.pipelines.length && !this.pageRequest; + }, }, /** @@ -102,6 +109,8 @@ export default Vue.component('pipelines-table', {
  • + +
    +
    ${pipelinesEmptyStateSVG} @@ -28,10 +28,10 @@ export default {

    Continous Integration can help catch bugs by running your tests automatically, while Continuous Deployment can help you deliver code to your product environment. - - Get started with Pipelines -

    + + Get started with Pipelines +
    diff --git a/app/assets/javascripts/vue_pipelines_index/components/error_state.js b/app/assets/javascripts/vue_pipelines_index/components/error_state.js index 9071ecdea73..f197395a6db 100644 --- a/app/assets/javascripts/vue_pipelines_index/components/error_state.js +++ b/app/assets/javascripts/vue_pipelines_index/components/error_state.js @@ -8,18 +8,18 @@ export default { }, template: ` -
    -
    -
    - ${pipelinesErrorStateSVG} +
    +
    +
    + ${pipelinesErrorStateSVG} +
    -
    -
    -
    -

    The API failed to fetch the pipelines.

    +
    +
    +

    The API failed to fetch the pipelines.

    +
    -
    `, }; diff --git a/app/assets/javascripts/vue_pipelines_index/components/navigation_tabs.js b/app/assets/javascripts/vue_pipelines_index/components/navigation_tabs.js index a494d2459aa..b4480bd98c7 100644 --- a/app/assets/javascripts/vue_pipelines_index/components/navigation_tabs.js +++ b/app/assets/javascripts/vue_pipelines_index/components/navigation_tabs.js @@ -18,7 +18,9 @@ export default { template: `