Skip to content

Commit 84264e9

Browse files
committed
Merge branch 'release/20.5.0'
2 parents bbf339d + 9ce7e78 commit 84264e9

38 files changed

+677
-352
lines changed

CHANGELOG.md

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,20 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
55
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
66

7+
## [20.5.0] - 2020-06-03
8+
## Changed
9+
- Components
10+
- `institutions`
11+
- `dashboard/departments-panel`
12+
- `dashboard/institutional-users-list`
13+
- `dashboard/panel`
14+
- `dashboard/projects-panel`
15+
- Mirage
16+
- Factories
17+
- `institution-user`
18+
- Serializers
19+
- `institution-user`
20+
721
## [20.4.0] - 2020-05-26
822
### Changed
923
- link to institutions
@@ -1592,7 +1606,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
15921606
### Added
15931607
- Quick Files
15941608

1595-
[Unreleased]: https://github.com/CenterForOpenScience/ember-osf-web/compare/20.4.0...develop
1609+
[Unreleased]: https://github.com/CenterForOpenScience/ember-osf-web/compare/20.5.0...develop
1610+
[20.4.0]: https://github.com/CenterForOpenScience/ember-osf-web/releases/tag/20.5.0
15961611
[20.4.0]: https://github.com/CenterForOpenScience/ember-osf-web/releases/tag/20.4.0
15971612
[20.3.1]: https://github.com/CenterForOpenScience/ember-osf-web/releases/tag/20.3.1
15981613
[20.3.0]: https://github.com/CenterForOpenScience/ember-osf-web/releases/tag/20.3.0
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import OsfAdapter from './osf-adapter';
2+
3+
export default class InstitutionDepartmentAdapter extends OsfAdapter {
4+
}
5+
6+
declare module 'ember-data/types/registries/adapter' {
7+
export default interface AdapterRegistry {
8+
'institution-department': InstitutionDepartmentAdapter;
9+
} // eslint-disable-line semi
10+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import OsfAdapter from './osf-adapter';
2+
3+
export default class InstitutionSummaryMetricAdapter extends OsfAdapter {
4+
}
5+
6+
declare module 'ember-data/types/registries/adapter' {
7+
export default interface AdapterRegistry {
8+
'institution-summary-metric': InstitutionSummaryMetricAdapter;
9+
} // eslint-disable-line semi
10+
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import OsfAdapter from './osf-adapter';
22

3-
export default class InstitutionalUserAdapter extends OsfAdapter {
3+
export default class InstitutionUserAdapter extends OsfAdapter {
44
parentRelationship = 'institution';
55
}
66

77
declare module 'ember-data/types/registries/adapter' {
88
export default interface AdapterRegistry {
9-
'institutional-user': InstitutionalUserAdapter;
9+
'institution-user': InstitutionUserAdapter;
1010
} // eslint-disable-line semi
1111
}
Lines changed: 50 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,75 @@
11
import Component from '@ember/component';
2-
import { computed } from '@ember/object';
3-
import { alias } from '@ember/object/computed';
2+
import { action, computed } from '@ember/object';
3+
import { inject as service } from '@ember/service';
44
import { ChartData, ChartOptions, Shape } from 'ember-cli-chart';
5-
import InstitutionModel, { Department } from 'ember-osf-web/models/institution';
5+
import Intl from 'ember-intl/services/intl';
6+
import { Department } from 'ember-osf-web/models/institution';
7+
import InstitutionDepartmentsModel from 'ember-osf-web/models/institution-department';
68

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

12-
chartOptions: ChartOptions = {
13-
aspectRatio: 1,
14-
legend: {
15-
display: false,
16-
},
17-
onHover: (_: MouseEvent, shapes: Shape[]): void => {
18-
if (shapes.length === 0 || this.chartHoverIndex === shapes[0]._index) {
19-
return;
20-
}
21-
this.set('chartHoverIndex', shapes[0]._index);
22-
},
23-
};
12+
topDepartments!: InstitutionDepartmentsModel[];
13+
totalUsers!: number;
14+
15+
chartHoverIndex: number = 0;
16+
17+
get chartOptions(): ChartOptions {
18+
return {
19+
aspectRatio: 1,
20+
legend: {
21+
display: false,
22+
},
23+
onHover: this.onChartHover,
24+
};
25+
}
2426

25-
didReceiveAttrs() {
26-
if (this.departments) {
27-
const departmentNumbers = this.departments.map(x => x.numUsers);
28-
this.set('chartHoverIndex', departmentNumbers.indexOf(Math.max(...departmentNumbers)));
27+
@action
28+
onChartHover(_: MouseEvent, shapes: Shape[]) {
29+
if (shapes.length === 0 || this.chartHoverIndex === shapes[0]._index) {
30+
return;
2931
}
32+
this.set('chartHoverIndex', shapes[0]._index);
3033
}
3134

32-
@computed('chartHoverIndex', 'departments')
33-
get chartData(): ChartData {
34-
const departmentNames = this.departments.map(x => x.name);
35-
const departmentNumbers = this.departments.map(x => x.numUsers);
35+
@computed('topDepartments')
36+
get displayDepartments() {
37+
const departments = this.topDepartments.map(({ name, numberOfUsers }) => ({ name, numberOfUsers }));
38+
const departmentNumbers = this.topDepartments.map(x => x.numberOfUsers);
39+
const otherDepartmentNumber = this.totalUsers - departmentNumbers.reduce((a, b) => a + b);
40+
41+
return [...departments, { name: this.intl.t('general.other'), numberOfUsers: otherDepartmentNumber }];
42+
}
3643

37-
const backgroundColors = [];
38-
for (const index of departmentNumbers.keys()) {
39-
if (index === this.chartHoverIndex) {
40-
backgroundColors.push('#15a5eb');
41-
} else {
42-
backgroundColors.push('#a5b3bd');
44+
@computed('chartHoverIndex', 'displayDepartments.[]')
45+
get chartData(): ChartData {
46+
const backgroundColors = this.displayDepartments.map((_, i) => {
47+
if (i === this.chartHoverIndex) {
48+
return '#15a5eb';
4349
}
44-
}
50+
return '#a5b3bd';
51+
});
52+
const displayDepartmentNames = this.displayDepartments.map(({ name }) => name);
53+
const displayDepartmentNumbers = this.displayDepartments.map(({ numberOfUsers }) => numberOfUsers);
4554

4655
return {
47-
labels: departmentNames,
56+
labels: displayDepartmentNames,
4857
datasets: [{
49-
data: departmentNumbers,
58+
data: displayDepartmentNumbers,
5059
backgroundColor: backgroundColors,
5160
}],
5261
};
5362
}
5463

55-
@computed('chartHoverIndex', 'departments')
64+
@computed('chartHoverIndex', 'displayDepartments.[]')
5665
get activeDepartment(): Department {
57-
return this.departments[this.chartHoverIndex];
66+
return this.displayDepartments[this.chartHoverIndex];
5867
}
5968

60-
@computed('activeDepartment', 'departments')
69+
@computed('activeDepartment', 'displayDepartments')
6170
get activeDepartmentPercentage(): string {
62-
const count = this.departments.reduce((total, currentValue) => total + currentValue.numUsers, 0);
63-
return ((this.activeDepartment.numUsers / count) * 100).toFixed(2);
71+
const numUsersArray = this.displayDepartments.map(({ numberOfUsers }) => numberOfUsers);
72+
const count = numUsersArray.reduce((a, b) => a + b);
73+
return ((this.activeDepartment.numberOfUsers / count) * 100).toFixed(2);
6474
}
6575
}

app/institutions/dashboard/-components/departments-panel/template.hbs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
1-
{{#if this.institution.statSummary}}
1+
{{#if this.topDepartments}}
22
<div
3-
data-test-chart
4-
local-class='ember-chart'
3+
data-test-chart
4+
local-class='ember-chart'
55
>
66
<EmberChart
7-
@type='pie'
8-
@data={{this.chartData}}
9-
@options={{this.chartOptions}}
7+
@type='pie'
8+
@data={{this.chartData}}
9+
@options={{this.chartOptions}}
1010
/>
1111
</div>
1212
<div local-class='department'>
1313
<h3>{{this.activeDepartment.name}}</h3>
1414
<p>
15-
<strong>{{this.activeDepartmentPercentage}}%:</strong> {{this.activeDepartment.numUsers}} {{t 'institutions.dashboard.users'}}
15+
<strong>{{this.activeDepartmentPercentage}}%:</strong> {{this.activeDepartment.numberOfUsers}} {{t 'institutions.dashboard.users'}}
1616
</p>
1717
</div>
1818
{{else}}

app/institutions/dashboard/-components/institutional-users-list/component.ts

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,44 @@
11
import Component from '@ember/component';
22
import { action, computed } from '@ember/object';
3-
import { alias } from '@ember/object/computed';
3+
import { reads } from '@ember/object/computed';
44
import { inject as service } from '@ember/service';
5+
import { TaskInstance, timeout } from 'ember-concurrency';
6+
import { task } from 'ember-concurrency-decorators';
57
import Intl from 'ember-intl/services/intl';
8+
9+
import { InstitutionsDashboardModel } from 'ember-osf-web/institutions/dashboard/route';
610
import InstitutionModel from 'ember-osf-web/models/institution';
11+
import InstitutionDepartmentsModel from 'ember-osf-web/models/institution-department';
712
import Analytics from 'ember-osf-web/services/analytics';
813

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

18+
@reads('modelTaskInstance.value.institution')
19+
institution?: InstitutionModel;
20+
21+
@reads('modelTaskInstance.value.departmentMetrics')
22+
departmentMetrics?: InstitutionDepartmentsModel[];
23+
1424
// Private properties
25+
modelTaskInstance!: TaskInstance<InstitutionsDashboardModel>;
1526
department?: string;
16-
sort = 'user_full_name';
27+
sort = 'user_name';
28+
29+
reloadUserList?: () => void;
1730

1831
@computed('intl.locale')
1932
get defaultDepartment() {
2033
return this.intl.t('institutions.dashboard.select_default');
2134
}
2235

23-
@computed('defaultDepartment', 'institution')
36+
@computed('defaultDepartment', 'institution', 'departmentMetrics.[]')
2437
get departments() {
2538
let departments = [this.defaultDepartment];
2639

27-
if (this.institution && this.institution.statSummary) {
28-
const institutionDepartments = this.institution.statSummary.departments.map((x: any) => x.name);
40+
if (this.institution && this.departmentMetrics) {
41+
const institutionDepartments = this.departmentMetrics.map((x: InstitutionDepartmentsModel) => x.name);
2942
departments = departments.concat(institutionDepartments);
3043
}
3144

@@ -42,7 +55,7 @@ export default class InstitutionalUsersList extends Component {
4255
}
4356

4457
@computed('department', 'isDefaultDepartment', 'sort')
45-
get query() {
58+
get queryUsers() {
4659
const query = {} as Record<string, string>;
4760
if (this.department && !this.isDefaultDepartment) {
4861
query['filter[department]'] = this.department;
@@ -53,6 +66,20 @@ export default class InstitutionalUsersList extends Component {
5366
return query;
5467
}
5568

69+
@task({ restartable: true })
70+
searchDepartment = task(function *(this: InstitutionalUsersList, name: string) {
71+
yield timeout(500);
72+
if (this.institution) {
73+
const depts: InstitutionDepartmentsModel[] = yield this.institution.queryHasMany('departmentMetrics', {
74+
filter: {
75+
name,
76+
},
77+
});
78+
return depts.map(dept => dept.name);
79+
}
80+
return [];
81+
});
82+
5683
@action
5784
onSelectChange(department: string) {
5885
this.analytics.trackFromElement(this.element, {
@@ -61,6 +88,9 @@ export default class InstitutionalUsersList extends Component {
6188
action: 'change',
6289
});
6390
this.set('department', department);
91+
if (this.reloadUserList) {
92+
this.reloadUserList();
93+
}
6494
}
6595

6696
@action

0 commit comments

Comments
 (0)