From 37cb4e9635617925917e47f4953379cef402a1e4 Mon Sep 17 00:00:00 2001 From: gbarc-dt <133209247+gbarc-dt@users.noreply.github.com> Date: Wed, 16 Oct 2024 12:26:05 +0200 Subject: [PATCH 1/2] [TBT-192] - plan usage changes(#2912) * minutes missing * tests --- app/components/plan-usage.js | 152 ++++++++++++-------- app/styles/app/layouts/billing.scss | 17 +++ app/templates/components/plan_usage.hbs | 107 +++++++------- tests/acceptance/profile/plan-usage-test.js | 6 +- 4 files changed, 156 insertions(+), 126 deletions(-) diff --git a/app/components/plan-usage.js b/app/components/plan-usage.js index 7ff2bcf338..fc538518c5 100644 --- a/app/components/plan-usage.js +++ b/app/components/plan-usage.js @@ -2,15 +2,17 @@ import Component from '@ember/component'; import { inject as service } from '@ember/service'; import { computed } from '@ember/object'; import { alias, reads, empty } from '@ember/object/computed'; +import { task } from 'ember-concurrency'; import moment from 'moment'; export default Component.extend({ features: service(), store: service(), + insights: service(), download: service(), showUserStatisticsModal: false, - repositoriesVisiblity: null, - repositoriesVisiblityOptions: ['All repositories', 'Private repositories', 'Public repositories'], + insightsCurrentRange: null, + insightsRangeOptions: ['Last Week', 'Last Month'], dateCenter: null, dateRange: null, showDatePicker: false, @@ -18,21 +20,35 @@ export default Component.extend({ subscription: reads('account.subscription'), v2subscription: reads('account.v2subscription'), isV2SubscriptionEmpty: empty('v2subscription'), + isOrganization: reads('owner.isOrganization'), init() { this._super(...arguments); - this.repositoriesVisiblity = 'All repositories'; this.dateCenter = new Date(); - let twoMonthsAgo = new Date(); - twoMonthsAgo.setTime(twoMonthsAgo.getTime() - 60 * 24 * 60 * 60 * 1000); + this.interval = 'week'; + this.insightsCurrentRange = this.insightsRangeOptions[0]; + let weekAgo = new Date(); + weekAgo.setTime(weekAgo.getTime() - 7 * 24 * 60 * 60 * 1000); this.dateRange = { - start: twoMonthsAgo, + start: weekAgo, end: new Date() }; this.owner.fetchExecutionsPerRepo.perform(moment(this.dateRange.start).format('YYYY-MM-DD'), moment(this.dateRange.end).format('YYYY-MM-DD')); this.owner.fetchExecutionsPerSender.perform(moment(this.dateRange.start).format('YYYY-MM-DD'), moment(this.dateRange.end).format('YYYY-MM-DD')); + this.requestRepositoryData.perform(); }, + requestRepositoryData: task(function* () { + return yield this.insights.getChartData.perform( + this.owner, + this.interval, + 'builds', + 'sum', + ['count_started'], + {calcAvg: true, private: true} + ); + }).drop(), + summarizedRepositories: computed('summarizedCalculations.repositories', function () { let repos = []; for (let repoId in this.summarizedCalculations.repositories) { @@ -43,7 +59,15 @@ export default Component.extend({ return repos; }), - summarizedMinutesByOs: reads('summarizedCalculations.minutesByOs'), + summarizedUsers: computed('summarizedOwnerCalculations.users', function () { + let users = []; + for (let userId in this.summarizedCalculations.users) { + const user = this.summarizedCalculations.users[userId]; + if (typeof user === 'object') + users.push(user); + } + return users; + }), totalBuildMinutes: computed('summarizedRepositories', function () { return this.summarizedRepositories.reduce((sum, repo) => sum + repo.buildMinutes, 0); @@ -52,51 +76,62 @@ export default Component.extend({ return this.summarizedRepositories.reduce((sum, repo) => sum + repo.buildCredits, 0); }), - summarizedCalculations: computed('owner.executionsPerRepo', 'repositoriesVisiblity', function () { + + summarizedCalculations: computed('owner.executionsPerRepo', function () { let repositories = []; - let minutesByOs = []; const executions = this.owner.get('executionsPerRepo'); - minutesByOs[getOsIconName('linux')] = 0; - minutesByOs[getOsIconName('osx')] = 0; - minutesByOs[getOsIconName('windows')] = 0; - minutesByOs[getOsIconName('freebsd')] = 0; - if (executions) { executions.forEach(async (execution) => { const repo = execution.repository; - if (this.repositoriesVisiblity === 'All repositories' || - (this.repositoriesVisiblity === 'Private repositories' && repo.private === true) || - (this.repositoriesVisiblity === 'Public repositories' && repo.private === false)) { - const minutes = execution.minutes_consumed; - const credits = execution.credits_consumed; - const osIcon = getOsIconName(execution.os); - if (minutesByOs[osIcon]) { - minutesByOs[osIcon] += minutes; - } else { - minutesByOs[osIcon] = minutes; - } - if (repositories[`'${execution.repository_id}'`]) { - repositories[`'${execution.repository_id}'`].buildMinutes += minutes; - repositories[`'${execution.repository_id}'`].buildCredits += credits; - } else { - repositories[`'${execution.repository_id}'`] = { - name: repo.name, - provider: repo.vcs_type.replace('Repository', '').toLowerCase(), - urlOwnerName: repo.owner_name, - formattedSlug: repo.slug.replace('/', ' / '), - urlName: repo.slug.split('/').lastObject, - buildMinutes: minutes, - buildCredits: credits - }; - } + const minutes = execution.minutes_consumed; + const credits = execution.credits_consumed; + if (repositories[`'${execution.repository_id}'`]) { + repositories[`'${execution.repository_id}'`].buildMinutes += minutes; + repositories[`'${execution.repository_id}'`].buildCredits += credits; + } else { + repositories[`'${execution.repository_id}'`] = { + name: repo.name, + provider: repo.vcs_type.replace('Repository', '').toLowerCase(), + urlOwnerName: repo.owner_name, + formattedSlug: repo.slug.replace('/', ' / '), + urlName: repo.slug.split('/').lastObject, + buildMinutes: minutes, + buildCredits: credits + }; } }); } return { repositories: repositories, - minutesByOs: minutesByOs + }; + }), + + summarizedOwnerCalculations: computed('owner.executionsPerSender', function () { + let users = []; + const executions = this.owner.get('executionsPerSender'); + + if (executions) { + executions.forEach(async (execution) => { + const sender = execution.sender; + const minutes = execution.minutes_consumed; + const credits = execution.credits_consumed; + if (users[`'${execution.sender_id}'`]) { + users[`'${execution.sender_id}'`].buildMinutes += minutes; + users[`'${execution.sender_id}'`].buildCredits += credits; + } else { + users[`'${execution.sender_id}'`] = { + login: sender.login, + name: sender.name, + buildMinutes: minutes, + buildCredits: credits + }; + } + }); + } + return { + users: users, }; }), @@ -187,30 +222,23 @@ export default Component.extend({ this.download.asCSV(fileName, header, data); }, - datePicker() { - this.set('showDatePicker', !this.showDatePicker); - if (!this.showDatePicker) { - this.owner.fetchExecutionsPerRepo.perform(moment(this.dateRange.start).format('YYYY-MM-DD'), - moment(this.dateRange.end || this.dateRange.start).format('YYYY-MM-DD')); - this.owner.fetchExecutionsPerSender.perform(moment(this.dateRange.start).format('YYYY-MM-DD'), - moment(this.dateRange.end || this.dateRange.start).format('YYYY-MM-DD')); - } + async changeInsightsRange(opt) { + this.set('insightsCurrentRange', opt); + this.set('interval', opt == this.insightsRangeOptions[0] ? 'week' : 'month'); + + let range = new Date(); + const distance = opt == this.insightsRangeOptions[0] ? 7 : 30; + range.setTime(range.getTime() - distance * 24 * 60 * 60 * 1000); + this.dateRange = { + start: range, + end: new Date() + }; + this.owner.fetchExecutionsPerRepo.perform(moment(this.dateRange.start).format('YYYY-MM-DD'), moment(this.dateRange.end).format('YYYY-MM-DD')); + this.owner.fetchExecutionsPerSender.perform(moment(this.dateRange.start).format('YYYY-MM-DD'), moment(this.dateRange.end).format('YYYY-MM-DD')); + this.requestRepositoryData.perform(); } + } }); const calculateMinutes = (start, finish) => (start && finish ? Math.ceil((Date.parse(finish) - Date.parse(start)) / 1000 / 60) : 0); - -const getOsIconName = (os) => { - if (os === 'linux') { - return 'icon-linux'; - } else if (os === 'freebsd') { - return 'icon-freebsd'; - } else if (os === 'osx') { - return 'icon-mac'; - } else if (os === 'windows') { - return 'icon-windows'; - } else { - return 'help'; - } -}; diff --git a/app/styles/app/layouts/billing.scss b/app/styles/app/layouts/billing.scss index 746bc3e655..4c1860fe0a 100644 --- a/app/styles/app/layouts/billing.scss +++ b/app/styles/app/layouts/billing.scss @@ -964,6 +964,13 @@ float: left; } + .total-usage { + margin-top: 1em; + margin-bottom: 1em; + float: left; + width: 100%; + } + .repositories-visiblity { clear: both; width: 150px; @@ -1060,6 +1067,12 @@ } } + .download-csv-container { + margin-bottom: 20px; + width: 100%; + float: left; + } + .download-csv { text-decoration: none; border-bottom: 1px solid $asphalt-grey; @@ -1068,6 +1081,10 @@ cursor: pointer; } + .credits-row { + width: 30%; + } + .repository-build-times { font-size: $font-size-s; width: 100%; diff --git a/app/templates/components/plan_usage.hbs b/app/templates/components/plan_usage.hbs index 1d860e4f81..1e23d40b0b 100644 --- a/app/templates/components/plan_usage.hbs +++ b/app/templates/components/plan_usage.hbs @@ -2,11 +2,7 @@

Plan information

- {{#if this.subscription.isManual}} - Manual plan - {{else}} - {{this.subscription.plan.name}} - {{/if}} + {{this.subscription.plan.name}}

Plan Activation date: {{#if this.subscription.createdAt}} @@ -34,74 +30,40 @@

Usage statistics

- - {{#if this.showDatePicker}} - - - - - {{/if}} -
- - {{#if this.v2subscription.plan.isNotStandardOrProTier}} - - {{/if}} -
- {{repositoriesVisiblity}} + {{insightsRange}}
- {{this.repositoriesVisiblity}} total build time: -
- {{#each-in this.summarizedMinutesByOs as |osicon minutes|}} -
- - -
- {{format-number minutes}} min -
-
- {{/each-in}} + +
All repositories total build time: {{this.totalBuildMinutes}} minutes
+ +
+ + {{#if this.v2subscription.plan.isNotStandardOrProTier}} + + {{/if}}
+ - - + @@ -115,21 +77,48 @@ {{repository.formattedSlug}} - + + {{/each}} + + + + + +
RepositoryTotal build minutesTotal creditsTotal credits
- {{format-number repository.buildMinutes}} + + {{format-number repository.buildCredits}}
Total{{format-number this.totalBuildCredits}}
+ + {{#if this.isOrganization }} + + + + + + + + + {{#each this.summarizedUsers as |user|}} + + {{/each}} - - +
UserTotal credits
- {{format-number repository.buildCredits}} + + {{user.login}} + + + {{format-number user.buildCredits}}
Total{{format-number this.totalBuildMinutes}}{{format-number this.totalBuildCredits}}{{format-number this.totalBuildCredits}}
+ {{/if}}
Date: Mon, 21 Oct 2024 12:40:21 +0200 Subject: [PATCH 2/2] csv part removed from usage (#2915) --- app/templates/components/plan_usage.hbs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/templates/components/plan_usage.hbs b/app/templates/components/plan_usage.hbs index 1e23d40b0b..06ee34f2db 100644 --- a/app/templates/components/plan_usage.hbs +++ b/app/templates/components/plan_usage.hbs @@ -52,12 +52,14 @@
All repositories total build time: {{this.totalBuildMinutes}} minutes
+