summaryrefslogtreecommitdiff
path: root/app/assets
diff options
context:
space:
mode:
authorFatih Acet <acetfatih@gmail.com>2016-09-19 23:41:36 +0300
committerFatih Acet <acetfatih@gmail.com>2016-09-19 23:41:36 +0300
commite49c6f8666f0e4a575bc9e2955c06eb59e213fd1 (patch)
tree0e72bfd8613087f0baa2ac8814de083e891115c5 /app/assets
parent3f3bdeced1e2e1f35b9f8e37a45f46233ee5cb58 (diff)
downloadgitlab-ce-e49c6f8666f0e4a575bc9e2955c06eb59e213fd1.tar.gz
Finalise cycle analytics frontend.
Diffstat (limited to 'app/assets')
-rw-r--r--app/assets/javascripts/cycle-analytics.js.es695
-rw-r--r--app/assets/javascripts/dispatcher.js4
-rw-r--r--app/assets/stylesheets/pages/cycle_analytics.scss96
3 files changed, 110 insertions, 85 deletions
diff --git a/app/assets/javascripts/cycle-analytics.js.es6 b/app/assets/javascripts/cycle-analytics.js.es6
index 727ae12b4fc..acae5439fa2 100644
--- a/app/assets/javascripts/cycle-analytics.js.es6
+++ b/app/assets/javascripts/cycle-analytics.js.es6
@@ -1,69 +1,92 @@
((global) => {
+ const COOKIE_NAME = 'cycle_analytics_help_dismissed';
+
gl.CycleAnalytics = class CycleAnalytics {
constructor() {
+ const that = this;
+
+ this.isHelpDismissed = $.cookie(COOKIE_NAME);
this.vue = new Vue({
el: '#cycle-analytics',
name: 'CycleAnalytics',
created: this.fetchData(),
- data: this.getData({ isLoading: true })
+ data: this.decorateData({ isLoading: true }),
+ methods: {
+ dismissLanding() {
+ that.dismissLanding();
+ }
+ }
});
}
- fetchData() {
- $.get('cycle_analytics.json')
- .done((data) => {
- this.vue.$data = this.getData(data);
- this.initDropdown();
- })
- .error((data) => {
- this.handleError(data);
- })
- .always(() => {
- this.vue.isLoading = false;
- })
+ fetchData(options) {
+ options = options || { startDate: 30 };
+
+ $.ajax({
+ url: $('#cycle-analytics').data('request-path'),
+ method: 'GET',
+ dataType: 'json',
+ contentType: 'application/json',
+ data: { start_date: options.startDate }
+ }).done((data) => {
+ this.vue.$data = this.decorateData(data);
+ this.initDropdown();
+ })
+ .error((data) => {
+ this.handleError(data);
+ })
+ .always(() => {
+ this.vue.isLoading = false;
+ })
}
- getData(data) {
- return {
- notAvailable: data.notAvailable || false,
- isLoading: data.isLoading || false,
- analytics: {
- summary: [
- { desc: 'New Issues', value: data.issues || '-' },
- { desc: 'Commits', value: data.commits || '-' },
- { desc: 'Deploys', value: data.deploys || '-' }
- ],
- data: [
- { title: 'Issue', desc: 'Time before an issue get scheduled', value: data.issue || '-' },
- { title: 'Plan', desc: 'Time before an issue starts implementation', value: data.plan || '-' },
- { title: 'Code', desc: 'Time until first merge request', value: data.code || '-' },
- { title: 'Test', desc: 'CI test time of the default branch', value: data.test || '-' },
- { title: 'Review', desc: 'Time between MR creation and merge/close', value: data.review || '-' },
- { title: 'Deploy', desc: 'Time for a new commit to land in one of the environments', value: data.deploy || '-' }
- ]
- }
- }
+ decorateData(data) {
+ data.summary = data.summary || [];
+ data.stats = data.stats || [];
+ data.isHelpDismissed = this.isHelpDismissed;
+ data.isLoading = data.isLoading || false;
+
+ data.summary.forEach((item) => {
+ item.value = item.value || '-';
+ });
+
+ data.stats.forEach((item) => {
+ item.value = item.value || '-';
+ })
+
+ return data;
}
handleError(data) {
- // TODO: Make sure that this is the proper error handling
- new Flash('There was an error while fetching cycyle analytics data.', 'alert');
+ this.vue.$data = {
+ hasError: true,
+ isHelpDismissed: this.isHelpDismissed
+ };
+
+ new Flash('There was an error while fetching cycle analytics data.', 'alert');
+ }
+
+ dismissLanding() {
+ this.vue.isHelpDismissed = true;
+ $.cookie(COOKIE_NAME, true);
}
initDropdown() {
const $dropdown = $('.js-ca-dropdown');
const $label = $dropdown.find('.dropdown-label');
- $dropdown.find('li a').on('click', (e) => {
+ $dropdown.find('li a').off('click').on('click', (e) => {
e.preventDefault();
const $target = $(e.currentTarget);
const value = $target.data('value');
$label.text($target.text().trim());
this.vue.isLoading = true;
+ this.fetchData({ startDate: value });
})
}
+
}
})(window.gl || (window.gl = {}));
diff --git a/app/assets/javascripts/dispatcher.js b/app/assets/javascripts/dispatcher.js
index 46734761e86..6e620e9976c 100644
--- a/app/assets/javascripts/dispatcher.js
+++ b/app/assets/javascripts/dispatcher.js
@@ -92,7 +92,7 @@
new MergedButtons();
break;
case "projects:merge_requests:conflicts":
- window.mcui = new MergeConflictResolver()
+ new MergeConflictResolver()
case 'projects:merge_requests:index':
shortcut_handler = new ShortcutsNavigation();
Issuable.init();
@@ -187,7 +187,7 @@
new gl.ProtectedBranchEditList();
break;
case 'projects:cycle_analytics:show':
- window.ca = new gl.CycleAnalytics();
+ new gl.CycleAnalytics();
break;
}
switch (path.first()) {
diff --git a/app/assets/stylesheets/pages/cycle_analytics.scss b/app/assets/stylesheets/pages/cycle_analytics.scss
index 16a9b0eebfc..4bbd942112a 100644
--- a/app/assets/stylesheets/pages/cycle_analytics.scss
+++ b/app/assets/stylesheets/pages/cycle_analytics.scss
@@ -1,5 +1,7 @@
#cycle-analytics {
- margin-top: 24px;
+ margin: 24px auto 0;
+ width: 800px;
+ position: relative;
.panel {
@@ -22,6 +24,10 @@
.text {
color: $layout-link-gray;
}
+
+ &:last-child {
+ text-align: right;
+ }
}
.dropdown {
@@ -39,9 +45,13 @@
.content-list {
li {
padding: 18px $gl-padding $gl-padding;
+
+ .container-fluid {
+ padding: 0;
+ }
}
- .col-md-10 {
+ .title-col {
span {
&:first-child {
line-height: 19px;
@@ -54,62 +64,54 @@
}
}
- .col-md-2 span {
- line-height: 42px;
- }
- }
-
- .inner-content {
- width: 450px;
- text-align: center;
- margin: 0 auto;
- padding: 62px 0;
+ .value-col {
+ text-align: right;
- .btn-block {
- max-width: 130px;
- margin: 0 auto;
+ span {
+ line-height: 42px;
+ }
}
+ }
- h4 {
- color: $gl-text-color;
- font-size: 17px;
- }
+ .landing {
+ margin-bottom: $gl-padding;
+ overflow: hidden;
- p {
- color: #8C8C8C;
- margin-bottom: $gl-padding;
+ .dismiss-icon {
+ position: absolute;
+ right: $gl-padding;
+ cursor: pointer;
}
- }
- &.waiting {
- .panel .header {
- width: 35px;
- height: 35px;
- margin-bottom: 3px;
+ svg {
+ margin: 0 20px;
+ float: left;
+ width: 136px;
+ height: 136px;
}
- span {
- background-color: #F8F8F8;
- color: #F8F8F8 !important;
- display: inline-block;
- line-height: 13px !important;
- }
+ .inner-content {
+ width: 480px;
+ float: left;
- .dropdown {
- opacity: .33;
- }
+ h4 {
+ color: $gl-text-color;
+ font-size: 17px;
+ }
- .col-md-2 span {
- position: relative;
- top: 11px;
+ p {
+ color: #8C8C8C;
+ margin-bottom: $gl-padding;
+ }
}
+ }
- .fa-spinner {
- font-size: 32px;
- position: absolute;
- left: 50%;
- top: 50%;
- margin: -16px 0 0 -16px;
- }
+ .fa-spinner {
+ font-size: 28px;
+ position: relative;
+ margin-left: -20px;
+ left: 50%;
+ margin-top: 36px;
}
+
}