summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFilipa Lacerda <filipa@gitlab.com>2016-11-23 14:44:05 +0000
committerFilipa Lacerda <filipa@gitlab.com>2016-11-30 17:06:46 +0000
commit43e5009a301d474225bf39e0efc5766b4b6be0c1 (patch)
tree1162ee20f1e3dc87a7036cd493b6695d5f437770
parent77337a82f0e2ee3d600d7ece248a110cbc3ef58d (diff)
downloadgitlab-ce-43e5009a301d474225bf39e0efc5766b4b6be0c1.tar.gz
Pipelines tabs
-rw-r--r--app/assets/javascripts/lib/utils/bootstrap_linked_tabs.js.es6110
-rw-r--r--app/controllers/projects/pipelines_controller.rb4
-rw-r--r--app/views/projects/pipelines/_with_tabs.html.haml23
-rw-r--r--config/routes/project.rb1
-rw-r--r--spec/features/projects/pipelines_spec.rb7
5 files changed, 140 insertions, 5 deletions
diff --git a/app/assets/javascripts/lib/utils/bootstrap_linked_tabs.js.es6 b/app/assets/javascripts/lib/utils/bootstrap_linked_tabs.js.es6
new file mode 100644
index 00000000000..28239cd66a9
--- /dev/null
+++ b/app/assets/javascripts/lib/utils/bootstrap_linked_tabs.js.es6
@@ -0,0 +1,110 @@
+
+/**
+ * Linked Tabs
+ *
+ * Handles persisting and restores the current tab selection and content.
+ * Reusable component for static content.
+ *
+ * ### Example Markup
+ *
+ * <ul class="nav-links tab-links">
+ * <li class="active">
+ * <a data-action="tab1" data-target="#tab1" data-toggle="tab" href="/path/tab1">
+ * Tab 1
+ * </a>
+ * </li>
+ * <li class="groups-tab">
+ * <a data-action="tab2" data-target="#tab2" data-toggle="tab" href="/path/tab2">
+ * Tab 2
+ * </a>
+ * </li>
+ *
+ *
+ * <div class="tab-content">
+ * <div class="tab-pane" id="tab1">
+ * Tab 1 Content
+ * </div>
+ * <div class="tab-pane" id="tab2">
+ * Tab 2 Content
+ * </div>
+ * </div>
+ *
+ *
+ * ### How to use
+ *
+ * new window.gl.LinkedTabs({
+ * action: "#{controller.action_name}",
+ * defaultAction: 'tab1',
+ * parentEl: '.tab-links'
+ * });
+ */
+
+(() => {
+ window.gl = window.gl || {};
+
+ window.gl.LinkedTabs = class LinkedTabs {
+ /**
+ * Binds the events and activates de default tab.
+ *
+ * @param {Object} options
+ */
+ constructor(options) {
+ this.options = options || {};
+
+ this.defaultAction = this.options.defaultAction;
+ this.action = this.options.action || this.defaultAction;
+
+ this.currentLocation = window.location;
+
+ if (this.action === 'show') {
+ this.action = this.defaultAction;
+ }
+
+ // since this is a custom event we need jQuery :(
+ $(document).on('shown.bs.tab', `${this.options.parentEl} a[data-toggle="tab"]`, evt => this.tabShown(evt));
+
+ this.activateTab(this.action);
+ }
+
+ /**
+ * Handles the `shown.bs.tab` event to set the currect url action.
+ *
+ * @param {type} evt
+ * @return {Function}
+ */
+ tabShown(evt) {
+ const source = evt.target.getAttribute('href');
+
+ return this.setCurrentAction(source);
+ }
+
+ /**
+ * Updates the URL with the path that matched the given action.
+ *
+ * @param {String} source
+ * @return {String}
+ */
+ setCurrentAction(source) {
+ const copySource = source;
+
+ copySource.replace(/\/+$/, '');
+
+ const newState = copySource + this.currentLocation.search + this.currentLocation.hash;
+
+ history.replaceState({
+ turbolinks: true,
+ url: newState,
+ }, document.title, newState);
+ return newState;
+ }
+
+ /**
+ * Given the current action activates the correct tab.
+ * http://getbootstrap.com/javascript/#tab-show
+ * Note: Will trigger `shown.bs.tab`
+ */
+ activateTab() {
+ return $(`.pipelines-tabs a[data-action='${this.action}']`).tab('show');
+ }
+ };
+})();
diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb
index 533af80aee0..de58f84f105 100644
--- a/app/controllers/projects/pipelines_controller.rb
+++ b/app/controllers/projects/pipelines_controller.rb
@@ -32,6 +32,10 @@ class Projects::PipelinesController < Projects::ApplicationController
def show
end
+ def builds
+ render 'show'
+ end
+
def retry
pipeline.retry_failed(current_user)
diff --git a/app/views/projects/pipelines/_with_tabs.html.haml b/app/views/projects/pipelines/_with_tabs.html.haml
index 718314701f9..49a26b3f374 100644
--- a/app/views/projects/pipelines/_with_tabs.html.haml
+++ b/app/views/projects/pipelines/_with_tabs.html.haml
@@ -1,14 +1,17 @@
.tabs-holder
- %ul.nav-links.no-top.no-bottom
- %li.active
- = link_to "Pipeline", "#js-tab-pipeline", data: { target: '#js-tab-pipeline', action: 'pipeline', toggle: 'tab' }, class: 'pipeline-tab'
+ %ul.pipelines-tabs.nav-links.no-top.no-bottom
%li
- = link_to "#js-tab-builds", data: { target: '#js-tab-builds', action: 'build', toggle: 'tab' }, class: 'builds-tab' do
+ = link_to namespace_project_pipeline_path(@project.namespace, @project, @pipeline), data: { target: 'div#js-tab-pipeline', action: 'pipelines', toggle: 'tab' } do
+ Pipeline
+ %li
+ = link_to builds_namespace_project_pipeline_path(@project.namespace, @project, @pipeline), data: {target: 'div#js-tab-builds', action: 'builds', toggle: 'tab' } do
Builds
%span.badge= pipeline.statuses.count
+
+
.tab-content
- #js-tab-pipeline.tab-pane.active
+ #js-tab-pipeline.tab-pane
.build-content.middle-block.pipeline-graph
.pipeline-visualization
%ul.stage-column-list
@@ -49,3 +52,13 @@
%th
- pipeline.statuses.relevant.stages.each do |stage|
= render 'projects/commit/ci_stage', stage: stage, statuses: pipeline.statuses.relevant.where(stage: stage)
+
+
+:javascript
+ var pipelines_tab;
+
+ pipelines_tab = new window.gl.LinkedTabs({
+ action: "#{controller.action_name}",
+ defaultAction: 'pipelines',
+ parentEl: '.pipelines-tabs'
+ });
diff --git a/config/routes/project.rb b/config/routes/project.rb
index 1336484a399..0754f0ec3b0 100644
--- a/config/routes/project.rb
+++ b/config/routes/project.rb
@@ -129,6 +129,7 @@ constraints(ProjectUrlConstrainer.new) do
member do
post :cancel
post :retry
+ get :builds
end
end
diff --git a/spec/features/projects/pipelines_spec.rb b/spec/features/projects/pipelines_spec.rb
index 10e5466fc85..03e89efb5d2 100644
--- a/spec/features/projects/pipelines_spec.rb
+++ b/spec/features/projects/pipelines_spec.rb
@@ -178,6 +178,13 @@ describe "Pipelines" do
expect(page).to have_link('Play')
end
+ context 'page tabs' do
+ it 'should have two tabs' do
+ expect(page).to have_link('Pipeline')
+ expect(page).to have_link('Builds')
+ end
+ end
+
context 'retrying builds' do
it { expect(page).not_to have_content('retried') }