Revision 59410
Added by Konstantinos Triantafyllou over 3 years ago
modules/uoa-usage-statistics/trunk/src/app/analytics/analytics.component.css | ||
---|---|---|
2 | 2 |
background-image: url("/assets/usage-statistics-assets/analytics/1.svg"); |
3 | 3 |
background-size: contain; |
4 | 4 |
background-repeat: no-repeat; |
5 |
background-position: bottom center;
|
|
6 |
min-height: 60vh;
|
|
5 |
background-position: center center;
|
|
6 |
min-height: calc(100vh - 100px);
|
|
7 | 7 |
} |
8 | 8 |
|
9 | 9 |
.countries input, .countries input:focus { |
modules/uoa-usage-statistics/trunk/src/app/analytics/analytics.component.html | ||
---|---|---|
1 | 1 |
<div *ngIf="countryFb" class="uk-section uk-section-small uk-container countries uk-text-center uk-text-bold"> |
2 |
<h2 class="uk-margin-medium-bottom portal-color uk-text-bold">Track Countries Usage Activity</h2> |
|
3 |
<div class="uk-container uk-container-small"> |
|
4 |
<div class="uk-flex uk-flex-middle uk-flex-center uk-align-center uk-margin-large-bottom"> |
|
5 |
<div class="uk-width-3-5"> |
|
6 |
<form [formGroup]="countryFb" (ngSubmit)="search()"> |
|
7 |
<input #input type="text" class="uk-animation-slide-right-medium uk-width-1-1" |
|
8 |
[class.uk-hidden]="!showSearch" |
|
9 |
placeholder="SEARCH FOR A COUNTRY" |
|
10 |
aria-label="Number" |
|
11 |
formControlName="country" |
|
12 |
[matAutocomplete]="auto"> |
|
13 |
<mat-autocomplete #auto="matAutocomplete" (optionSelected)="search()"> |
|
14 |
<mat-option *ngFor="let option of countries | async" [value]="option"> |
|
15 |
{{option}} |
|
16 |
</mat-option> |
|
17 |
</mat-autocomplete> |
|
18 |
</form> |
|
2 |
<h2 class="uk-margin-medium-bottom portal-color uk-text-bold">Track Countries Usage Activity</h2> |
|
3 |
<div class="uk-container uk-container-small"> |
|
4 |
<div class="uk-flex uk-flex-middle uk-flex-center uk-align-center uk-margin-large-bottom"> |
|
5 |
<div class="uk-width-3-5"> |
|
6 |
<form [formGroup]="countryFb" (ngSubmit)="search()"> |
|
7 |
<input #input type="text" class="uk-animation-slide-right-medium uk-width-1-1" |
|
8 |
[class.uk-hidden]="!showSearch || country" |
|
9 |
placeholder="SEARCH FOR A COUNTRY" |
|
10 |
aria-label="Number" |
|
11 |
formControlName="country" |
|
12 |
[matAutocomplete]="auto"> |
|
13 |
<mat-autocomplete #auto="matAutocomplete" (optionSelected)="search()"> |
|
14 |
<mat-option *ngFor="let option of countries | async" [value]="option"> |
|
15 |
{{option}} |
|
16 |
</mat-option> |
|
17 |
</mat-autocomplete> |
|
18 |
</form> |
|
19 |
<div class="uk-flex uk-flex-left"> |
|
20 |
<span *ngIf="country" class="uk-flex uk-flex-middle"> |
|
21 |
<span>{{country}}</span> |
|
22 |
<span class="uk-icon clickable space" uk-icon="icon: close; ratio: 0.8" (click)="reset()"> |
|
23 |
<svg width="16" height="16" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" data-svg="close"><path |
|
24 |
fill="none" stroke="#000" stroke-width="1.06" d="M16,16 L4,4"></path><path fill="none" stroke="#000" |
|
25 |
stroke-width="1.06" |
|
26 |
d="M16,4 L4,16"></path></svg> |
|
27 |
</span> |
|
28 |
</span> |
|
19 | 29 |
</div> |
20 |
<button [disabled]="loading" class="uk-width-1-6 uk-margin-medium-left search" (click)="toggle()"> |
|
21 |
<img src="assets/usage-statistics-assets/analytics/search.svg"> |
|
22 |
<span class="uk-text-uppercase">search</span> |
|
23 |
</button> |
|
24 | 30 |
</div> |
25 |
<div class="uk-margin-medium-bottom">
|
|
26 |
<div class="uk-text-uppercase">{{(country) ? country : 'world wide'}}</div>
|
|
27 |
<div class="uk-text-muted uk-text-uppercase uk-text-small">Results</div>
|
|
28 |
</div>
|
|
29 |
<div *ngIf="loading" class="uk-animation-fade uk-margin-large-top uk-width-1-1" role="alert">
|
|
30 |
<span class="loading-gif uk-align-center"></span>
|
|
31 |
</div> |
|
32 |
<div *ngIf="display && !loading" class="uk-grid uk-child-width-1-3@m uk-child-width-1-2@s uk-grid-large"
|
|
33 |
uk-grid>
|
|
34 |
<div *ngIf="display.total_repos">
|
|
35 |
<div class="card">
|
|
36 |
<div class="uk-margin-medium-bottom">
|
|
37 |
Repositories
|
|
38 |
</div>
|
|
39 |
<h3>
|
|
40 |
{{display.total_repos | number}}
|
|
41 |
</h3>
|
|
42 |
<img src="assets/usage-statistics-assets/analytics/2.svg">
|
|
31 |
<button [disabled]="loading" class="uk-width-1-6 uk-margin-medium-left search" (click)="toggle()">
|
|
32 |
<img src="assets/usage-statistics-assets/analytics/search.svg">
|
|
33 |
<span class="uk-text-uppercase space">search</span>
|
|
34 |
</button>
|
|
35 |
</div>
|
|
36 |
<div class="uk-margin-medium-bottom">
|
|
37 |
<div class="uk-text-uppercase">{{(country) ? country : 'world wide'}}</div>
|
|
38 |
<div class="uk-text-muted uk-text-uppercase uk-text-small">Results</div>
|
|
39 |
</div>
|
|
40 |
<div *ngIf="loading" class="uk-animation-fade uk-margin-large-top uk-width-1-1" role="alert">
|
|
41 |
<span class="loading-gif uk-align-center"></span>
|
|
42 |
</div>
|
|
43 |
<div *ngIf="display && !loading" class="uk-grid uk-child-width-1-3@m uk-child-width-1-2@s uk-grid-large"
|
|
44 |
uk-grid>
|
|
45 |
<div *ngIf="display.total_repos && state > 0" [class.uk-animation-fade]="state == 1">
|
|
46 |
<div class="card">
|
|
47 |
<div class="uk-margin-medium-bottom">
|
|
48 |
Repositories
|
|
43 | 49 |
</div> |
50 |
<h3> |
|
51 |
{{display.total_repos | number}} |
|
52 |
</h3> |
|
53 |
<img src="assets/usage-statistics-assets/analytics/2.svg"> |
|
44 | 54 |
</div> |
45 |
<div *ngIf="display.repositories"> |
|
46 |
<div class="card"> |
|
47 |
<div class="uk-margin-medium-bottom"> |
|
48 |
Repositories |
|
49 |
</div> |
|
50 |
<h3> |
|
51 |
{{display.repositories | number}} |
|
52 |
</h3> |
|
53 |
<img src="assets/usage-statistics-assets/analytics/2.svg"> |
|
55 |
</div> |
|
56 |
<div *ngIf="display.repositories && state > 0" [class.uk-animation-fade]="state == 1"> |
|
57 |
<div class="card"> |
|
58 |
<div class="uk-margin-medium-bottom"> |
|
59 |
Repositories |
|
54 | 60 |
</div> |
61 |
<h3> |
|
62 |
{{display.repositories | number}} |
|
63 |
</h3> |
|
64 |
<img src="assets/usage-statistics-assets/analytics/2.svg"> |
|
55 | 65 |
</div> |
56 |
<div *ngIf="display.total_views"> |
|
57 |
<div class="card"> |
|
58 |
<div class="uk-margin-medium-bottom"> |
|
59 |
Views |
|
60 |
</div> |
|
61 |
<h3> |
|
62 |
{{display.total_views | number}} |
|
63 |
</h3> |
|
64 |
<img src="assets/usage-statistics-assets/analytics/3.svg"> |
|
66 |
</div> |
|
67 |
<div *ngIf="display.total_views && state > 1" [class.uk-animation-fade]="state == 2"> |
|
68 |
<div class="card"> |
|
69 |
<div class="uk-margin-medium-bottom"> |
|
70 |
Views |
|
65 | 71 |
</div> |
72 |
<h3> |
|
73 |
{{display.total_views | number}} |
|
74 |
</h3> |
|
75 |
<img src="assets/usage-statistics-assets/analytics/3.svg"> |
|
66 | 76 |
</div> |
67 |
<div *ngIf="display.views"> |
|
68 |
<div class="card"> |
|
69 |
<div class="uk-margin-medium-bottom"> |
|
70 |
Views |
|
71 |
</div> |
|
72 |
<h3> |
|
73 |
{{display.views | number}} |
|
74 |
</h3> |
|
75 |
<img src="assets/usage-statistics-assets/analytics/3.svg"> |
|
77 |
</div> |
|
78 |
<div *ngIf="display.views && state > 1" [class.uk-animation-fade]="state == 2"> |
|
79 |
<div class="card"> |
|
80 |
<div class="uk-margin-medium-bottom"> |
|
81 |
Views |
|
76 | 82 |
</div> |
83 |
<h3> |
|
84 |
{{display.views | number}} |
|
85 |
</h3> |
|
86 |
<img src="assets/usage-statistics-assets/analytics/3.svg"> |
|
77 | 87 |
</div> |
78 |
<div *ngIf="display.total_downloads"> |
|
79 |
<div class="card"> |
|
80 |
<div class="uk-margin-medium-bottom"> |
|
81 |
Downloads |
|
82 |
</div> |
|
83 |
<h3> |
|
84 |
{{display.total_downloads | number}} |
|
85 |
</h3> |
|
86 |
<img src="assets/usage-statistics-assets/analytics/4.svg"> |
|
88 |
</div> |
|
89 |
<div *ngIf="display.total_downloads && state > 2" [class.uk-animation-fade]="state == 3"> |
|
90 |
<div class="card"> |
|
91 |
<div class="uk-margin-medium-bottom"> |
|
92 |
Downloads |
|
87 | 93 |
</div> |
94 |
<h3> |
|
95 |
{{display.total_downloads | number}} |
|
96 |
</h3> |
|
97 |
<img src="assets/usage-statistics-assets/analytics/4.svg"> |
|
88 | 98 |
</div> |
89 |
<div *ngIf="display.downloads"> |
|
90 |
<div class="card"> |
|
91 |
<div class="uk-margin-medium-bottom"> |
|
92 |
Downloads |
|
93 |
</div> |
|
94 |
<h3> |
|
95 |
{{display.downloads | number}} |
|
96 |
</h3> |
|
97 |
<img src="assets/usage-statistics-assets/analytics/4.svg"> |
|
99 |
</div> |
|
100 |
<div *ngIf="display.downloads && state > 2" [class.uk-animation-fade]="state == 3"> |
|
101 |
<div class="card"> |
|
102 |
<div class="uk-margin-medium-bottom"> |
|
103 |
Downloads |
|
98 | 104 |
</div> |
105 |
<h3> |
|
106 |
{{display.downloads | number}} |
|
107 |
</h3> |
|
108 |
<img src="assets/usage-statistics-assets/analytics/4.svg"> |
|
99 | 109 |
</div> |
100 | 110 |
</div> |
101 |
<div *ngIf="!display && !loading" class="card">
|
|
102 |
<div class="uk-position-center">
|
|
103 |
No results found for that country
|
|
104 |
</div>
|
|
111 |
</div>
|
|
112 |
<div *ngIf="!display && !loading" class="card uk-animation-fade">
|
|
113 |
<div class="uk-position-center">
|
|
114 |
No results found for that country
|
|
105 | 115 |
</div> |
106 | 116 |
</div> |
107 | 117 |
</div> |
118 |
</div> |
modules/uoa-usage-statistics/trunk/src/app/analytics/analytics.component.ts | ||
---|---|---|
6 | 6 |
import {map, startWith} from 'rxjs/operators'; |
7 | 7 |
import {countries} from '../services/countries'; |
8 | 8 |
import {Title} from '@angular/platform-browser'; |
9 |
import {StringUtils} from '../openaireLibrary/utils/string-utils.class'; |
|
9 | 10 |
|
10 | 11 |
@Component({ |
11 | 12 |
selector: 'analytics', |
12 | 13 |
templateUrl: 'analytics.component.html', |
13 | 14 |
styleUrls: ['analytics.component.css'], |
14 | 15 |
}) |
15 |
export class AnalyticsComponent implements OnInit{ |
|
16 |
export class AnalyticsComponent implements OnInit {
|
|
16 | 17 |
public countryFb: FormGroup; |
17 | 18 |
public countries: Observable<string[]>; |
18 | 19 |
public country: string; |
19 | 20 |
public loading: boolean = true; |
20 | 21 |
public display: UsageStat | CountryUsageStat; |
21 | 22 |
public showSearch: boolean = false; |
22 |
@ViewChild("input") input: ElementRef; |
|
23 |
public state: number = 0; |
|
24 |
private timeouts: any[] = []; |
|
25 |
@ViewChild('input') input: ElementRef; |
|
23 | 26 |
|
24 | 27 |
constructor(private usageStatsService: UsageStatsService, |
25 |
private title: Title) {} |
|
28 |
private title: Title) { |
|
29 |
} |
|
26 | 30 |
|
27 | 31 |
ngOnInit() { |
28 | 32 |
this.title.setTitle('OpenAIRE - UsageCounts | Analytics'); |
29 | 33 |
this.init(); |
30 |
this.usageStatsService.getAllMetrics().subscribe(stats => { |
|
31 |
this.display = stats; |
|
32 |
this.loading = false; |
|
33 |
}, error => { |
|
34 |
this.display = null; |
|
35 |
this.loading = false; |
|
36 |
}); |
|
34 |
this.search(); |
|
37 | 35 |
} |
38 | 36 |
|
39 | 37 |
private init() { |
40 |
this.countryFb= new FormGroup({ |
|
41 |
country: new FormControl('')
|
|
38 |
this.countryFb = new FormGroup({
|
|
39 |
country: new FormControl(null)
|
|
42 | 40 |
}); |
43 | 41 |
this.countries = this.countryFb.get('country').valueChanges |
44 | 42 |
.pipe( |
... | ... | |
50 | 48 |
public search() { |
51 | 49 |
this.country = this.countryFb.value.country; |
52 | 50 |
this.loading = true; |
53 |
if(this.country && this.country != '') { |
|
51 |
this.clearTimeouts(); |
|
52 |
if (this.country && this.country.length > 0) { |
|
53 |
this.country = StringUtils.capitalize(this.country); |
|
54 | 54 |
this.usageStatsService.getCountryMetrics(this.country).subscribe(stats => { |
55 | 55 |
this.display = stats; |
56 | 56 |
this.loading = false; |
57 |
this.init(); |
|
57 |
if(this.display) { |
|
58 |
this.state = 1; |
|
59 |
this.animation(); |
|
60 |
} |
|
58 | 61 |
}, error => { |
59 | 62 |
this.display = null; |
60 | 63 |
this.loading = false; |
... | ... | |
63 | 66 |
this.usageStatsService.getAllMetrics().subscribe(stats => { |
64 | 67 |
this.display = stats; |
65 | 68 |
this.loading = false; |
66 |
this.init(); |
|
67 |
},error => { |
|
69 |
if(this.display) { |
|
70 |
this.state = 1; |
|
71 |
this.animation(); |
|
72 |
} |
|
73 |
}, error => { |
|
68 | 74 |
this.display = null; |
69 | 75 |
this.loading = false; |
70 | 76 |
}); |
71 | 77 |
} |
72 | 78 |
} |
73 | 79 |
|
80 |
private animation() { |
|
81 |
this.timeouts.push(setTimeout(() => { |
|
82 |
if(this.state != 3) { |
|
83 |
this.animation(); |
|
84 |
} |
|
85 |
this.state++; |
|
86 |
}, 800)); |
|
87 |
} |
|
88 |
|
|
74 | 89 |
private _filter(value: string): string[] { |
75 | 90 |
const filterValue = value.toLowerCase(); |
76 | 91 |
return countries.map(value => value.name).filter(option => filterValue && option.toLowerCase().includes(filterValue)); |
... | ... | |
78 | 93 |
|
79 | 94 |
toggle() { |
80 | 95 |
this.showSearch = !this.showSearch; |
81 |
if(this.showSearch) { |
|
82 |
setTimeout(()=>{ // this will make the execution after the above boolean has changed
|
|
96 |
if (this.showSearch) {
|
|
97 |
setTimeout(() => { // this will make the execution after the above boolean has changed
|
|
83 | 98 |
this.input.nativeElement.focus(); |
84 |
},0); |
|
99 |
}, 0);
|
|
85 | 100 |
} |
86 | 101 |
} |
102 |
|
|
103 |
clearTimeouts() { |
|
104 |
this.timeouts.forEach(timeout => { |
|
105 |
clearTimeout(timeout); |
|
106 |
}); |
|
107 |
this.state = 0; |
|
108 |
} |
|
109 |
|
|
110 |
reset() { |
|
111 |
this.clearTimeouts(); |
|
112 |
if(this.state == 0) { |
|
113 |
this.init(); |
|
114 |
this.showSearch = true; |
|
115 |
setTimeout(() => { // this will make the execution after the above boolean has changed |
|
116 |
this.input.nativeElement.focus(); |
|
117 |
}, 0); |
|
118 |
this.search(); |
|
119 |
} |
|
120 |
} |
|
87 | 121 |
} |
Also available in: Unified diff
[UsageCounts]: Add close on seearch result. Add animation on search results. Fix height for countries section