diff --git a/app/institutions/dashboard/-components/chart-kpi-wrapper/chart-kpi/component.ts b/app/institutions/dashboard/-components/chart-kpi-wrapper/chart-kpi/component.ts index 711a744af1..252b2978d9 100644 --- a/app/institutions/dashboard/-components/chart-kpi-wrapper/chart-kpi/component.ts +++ b/app/institutions/dashboard/-components/chart-kpi-wrapper/chart-kpi/component.ts @@ -31,7 +31,7 @@ export default class ChartKpi extends Component { * @returns a ChartOptions model which is custom to COS */ get chartOptions(): ChartOptions { - return { + const options = { aspectRatio: 1, legend: { display: false, @@ -42,9 +42,14 @@ export default class ChartKpi extends Component { }], yAxes: [{ display: false, + ticks: { min: 0 }, }], }, }; + if (this.args.data.chartType === 'bar') { + options.scales.yAxes[0].display = true; + } + return options; } /** @@ -80,21 +85,22 @@ export default class ChartKpi extends Component { get chartData(): ChartData { const backgroundColors = [] as string[]; const data = [] as number[]; - const labels = [] as string[]; + const labels = [] as string[]; + const { taskInstance, chartData } = this.args.data; - this.args.data.chartData.map((chartData: ChartDataModel, $index: number) => { - backgroundColors.push(this.getColor($index)); + const rawData = taskInstance?.value || chartData || []; - data.push(chartData.total); - labels.push(chartData.label); + rawData.forEach((rawChartData: ChartDataModel, $index: number) => { + backgroundColors.push(this.getColor($index)); + data.push(rawChartData.total); + labels.push(rawChartData.label); this.expandedData.push({ - name: chartData.label, - total: chartData.total, + name: rawChartData.label, + total: rawChartData.total, color: this.getColor($index), }); }); - return { labels, datasets: [{ diff --git a/app/institutions/dashboard/-components/chart-kpi-wrapper/chart-kpi/styles.scss b/app/institutions/dashboard/-components/chart-kpi-wrapper/chart-kpi/styles.scss index 75fe4f855d..6dad4139b1 100644 --- a/app/institutions/dashboard/-components/chart-kpi-wrapper/chart-kpi/styles.scss +++ b/app/institutions/dashboard/-components/chart-kpi-wrapper/chart-kpi/styles.scss @@ -6,7 +6,7 @@ display: flex; flex-direction: column; justify-content: center; - align-items: flex-start; + text-align: center; width: 290px; min-height: 290px; height: fit-content; diff --git a/app/institutions/dashboard/-components/chart-kpi-wrapper/chart-kpi/template.hbs b/app/institutions/dashboard/-components/chart-kpi-wrapper/chart-kpi/template.hbs index c62c58f81f..d55b0fd48e 100644 --- a/app/institutions/dashboard/-components/chart-kpi-wrapper/chart-kpi/template.hbs +++ b/app/institutions/dashboard/-components/chart-kpi-wrapper/chart-kpi/template.hbs @@ -2,68 +2,74 @@ local-class='chart-container {{if (is-mobile) 'mobile'}}' ...attributes > -
-
- -
-
-
- {{#let (unique-id 'expanded-data') as |expandedDataId|}} -
-
{{@data.title}}
-
- -
-
-
+ {{else if @data.taskInstance.isError}} + {{t 'institutions.dashboard.kpi-chart.error'}} + {{else}} +
+
-
    - {{#each this.expandedData as |data index |}} -
  • +
+
+
+ {{#let (unique-id 'expanded-data') as |expandedDataId|}} +
+
{{@data.title}}
+
+ +
+
+
+
    + {{#each this.expandedData as |data index |}} +
  • - {{data.total}} -
- - {{/each}} - -
- {{/let}} -
+
+
+
+ {{data.name}} +
+
+ {{data.total}} +
+ + {{/each}} + +
+ {{/let}} + + {{/if}} \ No newline at end of file diff --git a/app/institutions/dashboard/-components/chart-kpi-wrapper/component-test.ts b/app/institutions/dashboard/-components/chart-kpi-wrapper/component-test.ts index 5603074b0f..c12c97d485 100644 --- a/app/institutions/dashboard/-components/chart-kpi-wrapper/component-test.ts +++ b/app/institutions/dashboard/-components/chart-kpi-wrapper/component-test.ts @@ -19,7 +19,7 @@ module('Integration | institutions | dashboard | -components | kpi-chart-wrapper publicProjectCount: 20, publicRegistrationCount: 100, embargoedRegistrationCount: 200, - preprintCount: 1000, + publishedPreprintCount: 1000, storageByteCount: 2000, }, departmentMetrics: [ @@ -32,6 +32,9 @@ module('Integration | institutions | dashboard | -components | kpi-chart-wrapper numberOfUsers: 37, }, ], + institution: { + iris: ['bleh'], + }, }); this.set('model', model); @@ -225,22 +228,21 @@ module('Integration | institutions | dashboard | -components | kpi-chart-wrapper // And the expanded data position 0 name is verified assert.dom(`${parentDom} [data-test-expanded-name="0"]`) - .hasText('Math'); + .exists(); // And the expanded data position 0 total is verified assert.dom(`${parentDom} [data-test-expanded-total="0"]`) - .hasText('25'); + .hasText('3'); // And the expanded data position 1 name is verified assert.dom(`${parentDom} [data-test-expanded-name="1"]`) - .hasText('Science'); + .exists(); // And the expanded data position 1 total is verified assert.dom(`${parentDom} [data-test-expanded-total="1"]`) - .hasText('37'); + .hasText('2'); - // Finally there are only 2 expanded data points - assert.dom(`${parentDom} [data-test-expanded-name="2"]`) + assert.dom(`${parentDom} [data-test-expanded-total="2"]`) .doesNotExist(); }); @@ -261,19 +263,19 @@ module('Integration | institutions | dashboard | -components | kpi-chart-wrapper // And the expanded data position 0 name is verified assert.dom(`${parentDom} [data-test-expanded-name="0"]`) - .hasText('Math'); + .exists(); // And the expanded data position 0 total is verified assert.dom(`${parentDom} [data-test-expanded-total="0"]`) - .hasText('25'); + .hasText('3'); // And the expanded data position 1 name is verified assert.dom(`${parentDom} [data-test-expanded-name="1"]`) - .hasText('Science'); + .exists(); // And the expanded data position 1 total is verified assert.dom(`${parentDom} [data-test-expanded-total="1"]`) - .hasText('37'); + .hasText('2'); // Finally there are only 2 expanded data points assert.dom(`${parentDom} [data-test-expanded-name="2"]`) @@ -297,56 +299,19 @@ module('Integration | institutions | dashboard | -components | kpi-chart-wrapper // And the expanded data position 0 name is verified assert.dom(`${parentDom} [data-test-expanded-name="0"]`) - .hasText('Math'); - - // And the expanded data position 0 total is verified - assert.dom(`${parentDom} [data-test-expanded-total="0"]`) - .hasText('25'); - - // And the expanded data position 1 name is verified - assert.dom(`${parentDom} [data-test-expanded-name="1"]`) - .hasText('Science'); - - // And the expanded data position 1 total is verified - assert.dom(`${parentDom} [data-test-expanded-total="1"]`) - .hasText('37'); - - // Finally there are only 2 expanded data points - assert.dom(`${parentDom} [data-test-expanded-name="2"]`) - .doesNotExist(); - }); - - test('it calculates the Public vs Private Data Storage data correctly', async function(assert) { - // Given the component is rendered - await render(hbs` - -`); - const parentDom = '[data-test-kpi-chart="7"]'; - - // When I click the expanded icon - await click(`${parentDom} [data-test-expand-additional-data]`); - - // And the title is verified - assert.dom(`${parentDom} [data-test-chart-title]`) - .hasText('Public vs Private Data Storage'); - - // And the expanded data position 0 name is verified - assert.dom(`${parentDom} [data-test-expanded-name="0"]`) - .hasText('Public Data Storage'); + .exists(); // And the expanded data position 0 total is verified assert.dom(`${parentDom} [data-test-expanded-total="0"]`) - .hasText('2000'); + .hasText('3'); // And the expanded data position 1 name is verified assert.dom(`${parentDom} [data-test-expanded-name="1"]`) - .hasText('Private Data Storage'); + .exists(); // And the expanded data position 1 total is verified assert.dom(`${parentDom} [data-test-expanded-total="1"]`) - .hasText('2100'); + .hasText('2'); // Finally there are only 2 expanded data points assert.dom(`${parentDom} [data-test-expanded-name="2"]`) diff --git a/app/institutions/dashboard/-components/chart-kpi-wrapper/component.ts b/app/institutions/dashboard/-components/chart-kpi-wrapper/component.ts index 34cd03de93..4bc74e2cdb 100644 --- a/app/institutions/dashboard/-components/chart-kpi-wrapper/component.ts +++ b/app/institutions/dashboard/-components/chart-kpi-wrapper/component.ts @@ -1,12 +1,16 @@ +import Store from '@ember-data/store'; +import { inject as service } from '@ember/service'; import { waitFor } from '@ember/test-waiters'; import Component from '@glimmer/component'; import { tracked } from '@glimmer/tracking'; -import { task } from 'ember-concurrency'; +import { task, TaskInstance } from 'ember-concurrency'; import { taskFor } from 'ember-concurrency-ts'; import Intl from 'ember-intl/services/intl'; -import { inject as service } from '@ember/service'; + import InstitutionDepartmentModel from 'ember-osf-web/models/institution-department'; import InstitutionSummaryMetricModel from 'ember-osf-web/models/institution-summary-metric'; +import SearchResultModel from 'ember-osf-web/models/search-result'; + /* import InstitutionSummaryMetricModel from 'ember-osf-web/models/institution-summary-metric'; */ @@ -22,12 +26,16 @@ interface TotalCountChartWrapperArgs { export interface KpiChartModel { title: string; - chartData: ChartDataModel[]; chartType: string; + // Either chartData or taskInstance should be defined + chartData?: ChartDataModel[]; + taskInstance?: TaskInstance; } export default class ChartKpiWrapperComponent extends Component { @service intl!: Intl; + @service store!: Store; + @tracked model = this.args.model; @tracked kpiCharts = [] as KpiChartModel[]; @tracked isLoading = true; @@ -50,6 +58,11 @@ export default class ChartKpiWrapperComponent extends Component { const metrics = await this.model; + const getLicenseTask = taskFor(this.getShareData).perform('rights'); + const getAddonsTask = taskFor(this.getShareData).perform('hasOsfAddon'); + const getRegionTask = taskFor(this.getShareData) + .perform('storageRegion'); + this.kpiCharts.push( { title: this.intl.t('institutions.dashboard.kpi-chart.users-by-department'), @@ -73,23 +86,18 @@ export default class ChartKpiWrapperComponent extends Component { - licenseData.push( - { - label: metric.name, - total: metric.numberOfUsers, - } as ChartDataModel, - ); - }); - return licenseData; - } - - /** - * calculateAddons - * - * @description Abstracted method to build the ChartData model for add-ons - * @param addonMetrics The add-on metrics object + * @returns ChartDataModel[] The labels and totals for each section * - * @returns The add-ons ChartData model */ - private calculateAddons(addonMetrics: InstitutionDepartmentModel[]): ChartDataModel[] { - const addonData = [] as ChartDataModel[]; - - addonMetrics.forEach((metric: InstitutionDepartmentModel ) => { - addonData.push( - { - label: metric.name, - total: metric.numberOfUsers, - } as ChartDataModel, - ); - }); - return addonData; - } - - /** - * calculateStorageRegions - * - * @description Abstracted method to build the Storage Regions ChartData - * @param storageRegionsMetrics The storage regions metrics object - * - * @returns The storage regions ChartData model - */ - private calculateStorageRegions(storageRegionsMetrics: InstitutionDepartmentModel[]): ChartDataModel[] { - const storageRegionsData = [] as ChartDataModel[]; - - storageRegionsMetrics.forEach((metric: InstitutionDepartmentModel ) => { - storageRegionsData.push( - { - label: metric.name, - total: metric.numberOfUsers, - } as ChartDataModel, - ); + @task + @waitFor + private async getShareData( + propertyPath: string, + ): Promise { + const valueSearch = await this.store.queryRecord('index-value-search', { + cardSearchFilter: { + affiliation: this.args.model.institution.iris.join(','), + }, + 'page[size]': 10, + valueSearchPropertyPath: propertyPath, }); - return storageRegionsData; - } + const resultPage = valueSearch.searchResultPage.toArray(); - /** - * calculateDataStorage - * - * @description Abstracted method to calculate the private and public data storage - * @param summaryMetrics The institutional summary metrics object - * - * @returns The total of private and public data storage - */ - private calculateDataStorage(summaryMetrics: InstitutionSummaryMetricModel): ChartDataModel[] { - return [ - { - label: this.intl.t('institutions.dashboard.kpi-chart.public-vs-private-data-storage.public'), - total: summaryMetrics.storageByteCount, - } as ChartDataModel, - { - label: this.intl.t('institutions.dashboard.kpi-chart.public-vs-private-data-storage.private'), - total: summaryMetrics.storageByteCount + 100, - } as ChartDataModel, - ]; + return resultPage.map((result: SearchResultModel) => ({ + total: result.cardSearchResultCount, + label: result.indexCard.get('label'), + })); } } - - diff --git a/mirage/factories/institution-summary-metric.ts b/mirage/factories/institution-summary-metric.ts index e99994d552..123c422d7d 100644 --- a/mirage/factories/institution-summary-metric.ts +++ b/mirage/factories/institution-summary-metric.ts @@ -19,7 +19,7 @@ export default Factory.extend({ embargoedRegistrationCount() { return faker.random.number({ min: 0, max: 25}); }, - preprintCount() { + publishedPreprintCount() { return faker.random.number({ min: 15, max: 175}); }, storageByteCount() { diff --git a/translations/en-us.yml b/translations/en-us.yml index 742cf13288..71cfbb0949 100644 --- a/translations/en-us.yml +++ b/translations/en-us.yml @@ -859,6 +859,7 @@ institutions: title: 'Public vs Private Data Storage' public: 'Public Data Storage' private: 'Private Data Storage' + error: 'Error loading data' object-list: filter-button-label: 'Filter' filter-heading: 'Filter by:' diff --git a/types/ember-cli-chart.d.ts b/types/ember-cli-chart.d.ts index 93d77cdeae..6d027a67b1 100644 --- a/types/ember-cli-chart.d.ts +++ b/types/ember-cli-chart.d.ts @@ -20,14 +20,18 @@ declare module 'ember-cli-chart' { xAxes?: [ { display?: boolean + ticks?: { + min?: number + } } - ], yAxes?: [ { display?: boolean + ticks?: { + min?: number + } } - ] } }