Skip to content

Commit

Permalink
Merge branch 'release/20.5.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
fabmiz committed Jun 3, 2020
2 parents bbf339d + 9ce7e78 commit 84264e9
Show file tree
Hide file tree
Showing 38 changed files with 677 additions and 352 deletions.
17 changes: 16 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,20 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## [20.5.0] - 2020-06-03
## Changed
- Components
- `institutions`
- `dashboard/departments-panel`
- `dashboard/institutional-users-list`
- `dashboard/panel`
- `dashboard/projects-panel`
- Mirage
- Factories
- `institution-user`
- Serializers
- `institution-user`

## [20.4.0] - 2020-05-26
### Changed
- link to institutions
Expand Down Expand Up @@ -1592,7 +1606,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
### Added
- Quick Files

[Unreleased]: https://github.com/CenterForOpenScience/ember-osf-web/compare/20.4.0...develop
[Unreleased]: https://github.com/CenterForOpenScience/ember-osf-web/compare/20.5.0...develop
[20.4.0]: https://github.com/CenterForOpenScience/ember-osf-web/releases/tag/20.5.0
[20.4.0]: https://github.com/CenterForOpenScience/ember-osf-web/releases/tag/20.4.0
[20.3.1]: https://github.com/CenterForOpenScience/ember-osf-web/releases/tag/20.3.1
[20.3.0]: https://github.com/CenterForOpenScience/ember-osf-web/releases/tag/20.3.0
Expand Down
10 changes: 10 additions & 0 deletions app/adapters/institution-department.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import OsfAdapter from './osf-adapter';

export default class InstitutionDepartmentAdapter extends OsfAdapter {
}

declare module 'ember-data/types/registries/adapter' {
export default interface AdapterRegistry {
'institution-department': InstitutionDepartmentAdapter;
} // eslint-disable-line semi
}
10 changes: 10 additions & 0 deletions app/adapters/institution-summary-metric.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import OsfAdapter from './osf-adapter';

export default class InstitutionSummaryMetricAdapter extends OsfAdapter {
}

declare module 'ember-data/types/registries/adapter' {
export default interface AdapterRegistry {
'institution-summary-metric': InstitutionSummaryMetricAdapter;
} // eslint-disable-line semi
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import OsfAdapter from './osf-adapter';

export default class InstitutionalUserAdapter extends OsfAdapter {
export default class InstitutionUserAdapter extends OsfAdapter {
parentRelationship = 'institution';
}

declare module 'ember-data/types/registries/adapter' {
export default interface AdapterRegistry {
'institutional-user': InstitutionalUserAdapter;
'institution-user': InstitutionUserAdapter;
} // eslint-disable-line semi
}
Original file line number Diff line number Diff line change
@@ -1,65 +1,75 @@
import Component from '@ember/component';
import { computed } from '@ember/object';
import { alias } from '@ember/object/computed';
import { action, computed } from '@ember/object';
import { inject as service } from '@ember/service';
import { ChartData, ChartOptions, Shape } from 'ember-cli-chart';
import InstitutionModel, { Department } from 'ember-osf-web/models/institution';
import Intl from 'ember-intl/services/intl';
import { Department } from 'ember-osf-web/models/institution';
import InstitutionDepartmentsModel from 'ember-osf-web/models/institution-department';

export default class DepartmentsPanel extends Component {
institution!: InstitutionModel;
@alias('institution.statSummary.departments') departments!: any[];
chartHoverIndex: number = -1;
@service intl!: Intl;

chartOptions: ChartOptions = {
aspectRatio: 1,
legend: {
display: false,
},
onHover: (_: MouseEvent, shapes: Shape[]): void => {
if (shapes.length === 0 || this.chartHoverIndex === shapes[0]._index) {
return;
}
this.set('chartHoverIndex', shapes[0]._index);
},
};
topDepartments!: InstitutionDepartmentsModel[];
totalUsers!: number;

chartHoverIndex: number = 0;

get chartOptions(): ChartOptions {
return {
aspectRatio: 1,
legend: {
display: false,
},
onHover: this.onChartHover,
};
}

didReceiveAttrs() {
if (this.departments) {
const departmentNumbers = this.departments.map(x => x.numUsers);
this.set('chartHoverIndex', departmentNumbers.indexOf(Math.max(...departmentNumbers)));
@action
onChartHover(_: MouseEvent, shapes: Shape[]) {
if (shapes.length === 0 || this.chartHoverIndex === shapes[0]._index) {
return;
}
this.set('chartHoverIndex', shapes[0]._index);
}

@computed('chartHoverIndex', 'departments')
get chartData(): ChartData {
const departmentNames = this.departments.map(x => x.name);
const departmentNumbers = this.departments.map(x => x.numUsers);
@computed('topDepartments')
get displayDepartments() {
const departments = this.topDepartments.map(({ name, numberOfUsers }) => ({ name, numberOfUsers }));
const departmentNumbers = this.topDepartments.map(x => x.numberOfUsers);
const otherDepartmentNumber = this.totalUsers - departmentNumbers.reduce((a, b) => a + b);

return [...departments, { name: this.intl.t('general.other'), numberOfUsers: otherDepartmentNumber }];
}

const backgroundColors = [];
for (const index of departmentNumbers.keys()) {
if (index === this.chartHoverIndex) {
backgroundColors.push('#15a5eb');
} else {
backgroundColors.push('#a5b3bd');
@computed('chartHoverIndex', 'displayDepartments.[]')
get chartData(): ChartData {
const backgroundColors = this.displayDepartments.map((_, i) => {
if (i === this.chartHoverIndex) {
return '#15a5eb';
}
}
return '#a5b3bd';
});
const displayDepartmentNames = this.displayDepartments.map(({ name }) => name);
const displayDepartmentNumbers = this.displayDepartments.map(({ numberOfUsers }) => numberOfUsers);

return {
labels: departmentNames,
labels: displayDepartmentNames,
datasets: [{
data: departmentNumbers,
data: displayDepartmentNumbers,
backgroundColor: backgroundColors,
}],
};
}

@computed('chartHoverIndex', 'departments')
@computed('chartHoverIndex', 'displayDepartments.[]')
get activeDepartment(): Department {
return this.departments[this.chartHoverIndex];
return this.displayDepartments[this.chartHoverIndex];
}

@computed('activeDepartment', 'departments')
@computed('activeDepartment', 'displayDepartments')
get activeDepartmentPercentage(): string {
const count = this.departments.reduce((total, currentValue) => total + currentValue.numUsers, 0);
return ((this.activeDepartment.numUsers / count) * 100).toFixed(2);
const numUsersArray = this.displayDepartments.map(({ numberOfUsers }) => numberOfUsers);
const count = numUsersArray.reduce((a, b) => a + b);
return ((this.activeDepartment.numberOfUsers / count) * 100).toFixed(2);
}
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
{{#if this.institution.statSummary}}
{{#if this.topDepartments}}
<div
data-test-chart
local-class='ember-chart'
data-test-chart
local-class='ember-chart'
>
<EmberChart
@type='pie'
@data={{this.chartData}}
@options={{this.chartOptions}}
@type='pie'
@data={{this.chartData}}
@options={{this.chartOptions}}
/>
</div>
<div local-class='department'>
<h3>{{this.activeDepartment.name}}</h3>
<p>
<strong>{{this.activeDepartmentPercentage}}%:</strong> {{this.activeDepartment.numUsers}} {{t 'institutions.dashboard.users'}}
<strong>{{this.activeDepartmentPercentage}}%:</strong> {{this.activeDepartment.numberOfUsers}} {{t 'institutions.dashboard.users'}}
</p>
</div>
{{else}}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,31 +1,44 @@
import Component from '@ember/component';
import { action, computed } from '@ember/object';
import { alias } from '@ember/object/computed';
import { reads } from '@ember/object/computed';
import { inject as service } from '@ember/service';
import { TaskInstance, timeout } from 'ember-concurrency';
import { task } from 'ember-concurrency-decorators';
import Intl from 'ember-intl/services/intl';

import { InstitutionsDashboardModel } from 'ember-osf-web/institutions/dashboard/route';
import InstitutionModel from 'ember-osf-web/models/institution';
import InstitutionDepartmentsModel from 'ember-osf-web/models/institution-department';
import Analytics from 'ember-osf-web/services/analytics';

export default class InstitutionalUsersList extends Component {
@alias('model.taskInstance.value') institution?: InstitutionModel;
@service analytics!: Analytics;
@service intl!: Intl;

@reads('modelTaskInstance.value.institution')
institution?: InstitutionModel;

@reads('modelTaskInstance.value.departmentMetrics')
departmentMetrics?: InstitutionDepartmentsModel[];

// Private properties
modelTaskInstance!: TaskInstance<InstitutionsDashboardModel>;
department?: string;
sort = 'user_full_name';
sort = 'user_name';

reloadUserList?: () => void;

@computed('intl.locale')
get defaultDepartment() {
return this.intl.t('institutions.dashboard.select_default');
}

@computed('defaultDepartment', 'institution')
@computed('defaultDepartment', 'institution', 'departmentMetrics.[]')
get departments() {
let departments = [this.defaultDepartment];

if (this.institution && this.institution.statSummary) {
const institutionDepartments = this.institution.statSummary.departments.map((x: any) => x.name);
if (this.institution && this.departmentMetrics) {
const institutionDepartments = this.departmentMetrics.map((x: InstitutionDepartmentsModel) => x.name);
departments = departments.concat(institutionDepartments);
}

Expand All @@ -42,7 +55,7 @@ export default class InstitutionalUsersList extends Component {
}

@computed('department', 'isDefaultDepartment', 'sort')
get query() {
get queryUsers() {
const query = {} as Record<string, string>;
if (this.department && !this.isDefaultDepartment) {
query['filter[department]'] = this.department;
Expand All @@ -53,6 +66,20 @@ export default class InstitutionalUsersList extends Component {
return query;
}

@task({ restartable: true })
searchDepartment = task(function *(this: InstitutionalUsersList, name: string) {
yield timeout(500);
if (this.institution) {
const depts: InstitutionDepartmentsModel[] = yield this.institution.queryHasMany('departmentMetrics', {
filter: {
name,
},
});
return depts.map(dept => dept.name);
}
return [];
});

@action
onSelectChange(department: string) {
this.analytics.trackFromElement(this.element, {
Expand All @@ -61,6 +88,9 @@ export default class InstitutionalUsersList extends Component {
action: 'change',
});
this.set('department', department);
if (this.reloadUserList) {
this.reloadUserList();
}
}

@action
Expand Down
Loading

0 comments on commit 84264e9

Please sign in to comment.