diff options
author | Chocobozzz <me@florianbigard.com> | 2020-06-23 14:10:17 +0200 |
---|---|---|
committer | Chocobozzz <chocobozzz@cpy.re> | 2020-06-23 16:00:49 +0200 |
commit | 67ed6552b831df66713bac9e672738796128d33f (patch) | |
tree | 59c97d41e0b49d75a90aa3de987968ab9b1ff447 /client/src/app/shared/instance | |
parent | 0c4bacbff53bc732f5a2677d62a6ead7752e2405 (diff) | |
download | PeerTube-67ed6552b831df66713bac9e672738796128d33f.tar.gz PeerTube-67ed6552b831df66713bac9e672738796128d33f.tar.zst PeerTube-67ed6552b831df66713bac9e672738796128d33f.zip |
Reorganize client shared modules
Diffstat (limited to 'client/src/app/shared/instance')
11 files changed, 0 insertions, 622 deletions
diff --git a/client/src/app/shared/instance/feature-boolean.component.html b/client/src/app/shared/instance/feature-boolean.component.html deleted file mode 100644 index ccb8a30cc..000000000 --- a/client/src/app/shared/instance/feature-boolean.component.html +++ /dev/null | |||
@@ -1,3 +0,0 @@ | |||
1 | <span *ngIf="value === true" class="glyphicon glyphicon-ok" i18n-aria-label aria-label="yes"></span> | ||
2 | <span *ngIf="value === false" class="glyphicon glyphicon-remove" i18n-aria-label aria-label="no"></span> | ||
3 | |||
diff --git a/client/src/app/shared/instance/feature-boolean.component.scss b/client/src/app/shared/instance/feature-boolean.component.scss deleted file mode 100644 index 56d08af06..000000000 --- a/client/src/app/shared/instance/feature-boolean.component.scss +++ /dev/null | |||
@@ -1,10 +0,0 @@ | |||
1 | @import '_variables'; | ||
2 | @import '_mixins'; | ||
3 | |||
4 | .glyphicon-ok { | ||
5 | color: $green; | ||
6 | } | ||
7 | |||
8 | .glyphicon-remove { | ||
9 | color: $red; | ||
10 | } | ||
diff --git a/client/src/app/shared/instance/feature-boolean.component.ts b/client/src/app/shared/instance/feature-boolean.component.ts deleted file mode 100644 index d02d513d6..000000000 --- a/client/src/app/shared/instance/feature-boolean.component.ts +++ /dev/null | |||
@@ -1,10 +0,0 @@ | |||
1 | import { Component, Input } from '@angular/core' | ||
2 | |||
3 | @Component({ | ||
4 | selector: 'my-feature-boolean', | ||
5 | templateUrl: './feature-boolean.component.html', | ||
6 | styleUrls: [ './feature-boolean.component.scss' ] | ||
7 | }) | ||
8 | export class FeatureBooleanComponent { | ||
9 | @Input() value: boolean | ||
10 | } | ||
diff --git a/client/src/app/shared/instance/follow.service.ts b/client/src/app/shared/instance/follow.service.ts deleted file mode 100644 index ef4c09583..000000000 --- a/client/src/app/shared/instance/follow.service.ts +++ /dev/null | |||
@@ -1,116 +0,0 @@ | |||
1 | import { catchError, map } from 'rxjs/operators' | ||
2 | import { HttpClient, HttpParams } from '@angular/common/http' | ||
3 | import { Injectable } from '@angular/core' | ||
4 | import { Observable } from 'rxjs' | ||
5 | import { ActivityPubActorType, ActorFollow, FollowState, ResultList } from '@shared/index' | ||
6 | import { environment } from '../../../environments/environment' | ||
7 | import { RestExtractor, RestPagination, RestService } from '../rest' | ||
8 | import { SortMeta } from 'primeng/api' | ||
9 | |||
10 | @Injectable() | ||
11 | export class FollowService { | ||
12 | private static BASE_APPLICATION_URL = environment.apiUrl + '/api/v1/server' | ||
13 | |||
14 | constructor ( | ||
15 | private authHttp: HttpClient, | ||
16 | private restService: RestService, | ||
17 | private restExtractor: RestExtractor | ||
18 | ) { | ||
19 | } | ||
20 | |||
21 | getFollowing (options: { | ||
22 | pagination: RestPagination, | ||
23 | sort: SortMeta, | ||
24 | search?: string, | ||
25 | actorType?: ActivityPubActorType, | ||
26 | state?: FollowState | ||
27 | }): Observable<ResultList<ActorFollow>> { | ||
28 | const { pagination, sort, search, state, actorType } = options | ||
29 | |||
30 | let params = new HttpParams() | ||
31 | params = this.restService.addRestGetParams(params, pagination, sort) | ||
32 | |||
33 | if (search) params = params.append('search', search) | ||
34 | if (state) params = params.append('state', state) | ||
35 | if (actorType) params = params.append('actorType', actorType) | ||
36 | |||
37 | return this.authHttp.get<ResultList<ActorFollow>>(FollowService.BASE_APPLICATION_URL + '/following', { params }) | ||
38 | .pipe( | ||
39 | map(res => this.restExtractor.convertResultListDateToHuman(res)), | ||
40 | catchError(res => this.restExtractor.handleError(res)) | ||
41 | ) | ||
42 | } | ||
43 | |||
44 | getFollowers (options: { | ||
45 | pagination: RestPagination, | ||
46 | sort: SortMeta, | ||
47 | search?: string, | ||
48 | actorType?: ActivityPubActorType, | ||
49 | state?: FollowState | ||
50 | }): Observable<ResultList<ActorFollow>> { | ||
51 | const { pagination, sort, search, state, actorType } = options | ||
52 | |||
53 | let params = new HttpParams() | ||
54 | params = this.restService.addRestGetParams(params, pagination, sort) | ||
55 | |||
56 | if (search) params = params.append('search', search) | ||
57 | if (state) params = params.append('state', state) | ||
58 | if (actorType) params = params.append('actorType', actorType) | ||
59 | |||
60 | return this.authHttp.get<ResultList<ActorFollow>>(FollowService.BASE_APPLICATION_URL + '/followers', { params }) | ||
61 | .pipe( | ||
62 | map(res => this.restExtractor.convertResultListDateToHuman(res)), | ||
63 | catchError(res => this.restExtractor.handleError(res)) | ||
64 | ) | ||
65 | } | ||
66 | |||
67 | follow (notEmptyHosts: string[]) { | ||
68 | const body = { | ||
69 | hosts: notEmptyHosts | ||
70 | } | ||
71 | |||
72 | return this.authHttp.post(FollowService.BASE_APPLICATION_URL + '/following', body) | ||
73 | .pipe( | ||
74 | map(this.restExtractor.extractDataBool), | ||
75 | catchError(res => this.restExtractor.handleError(res)) | ||
76 | ) | ||
77 | } | ||
78 | |||
79 | unfollow (follow: ActorFollow) { | ||
80 | return this.authHttp.delete(FollowService.BASE_APPLICATION_URL + '/following/' + follow.following.host) | ||
81 | .pipe( | ||
82 | map(this.restExtractor.extractDataBool), | ||
83 | catchError(res => this.restExtractor.handleError(res)) | ||
84 | ) | ||
85 | } | ||
86 | |||
87 | acceptFollower (follow: ActorFollow) { | ||
88 | const handle = follow.follower.name + '@' + follow.follower.host | ||
89 | |||
90 | return this.authHttp.post(`${FollowService.BASE_APPLICATION_URL}/followers/${handle}/accept`, {}) | ||
91 | .pipe( | ||
92 | map(this.restExtractor.extractDataBool), | ||
93 | catchError(res => this.restExtractor.handleError(res)) | ||
94 | ) | ||
95 | } | ||
96 | |||
97 | rejectFollower (follow: ActorFollow) { | ||
98 | const handle = follow.follower.name + '@' + follow.follower.host | ||
99 | |||
100 | return this.authHttp.post(`${FollowService.BASE_APPLICATION_URL}/followers/${handle}/reject`, {}) | ||
101 | .pipe( | ||
102 | map(this.restExtractor.extractDataBool), | ||
103 | catchError(res => this.restExtractor.handleError(res)) | ||
104 | ) | ||
105 | } | ||
106 | |||
107 | removeFollower (follow: ActorFollow) { | ||
108 | const handle = follow.follower.name + '@' + follow.follower.host | ||
109 | |||
110 | return this.authHttp.delete(`${FollowService.BASE_APPLICATION_URL}/followers/${handle}`) | ||
111 | .pipe( | ||
112 | map(this.restExtractor.extractDataBool), | ||
113 | catchError(res => this.restExtractor.handleError(res)) | ||
114 | ) | ||
115 | } | ||
116 | } | ||
diff --git a/client/src/app/shared/instance/instance-features-table.component.html b/client/src/app/shared/instance/instance-features-table.component.html deleted file mode 100644 index f6a3b7f0b..000000000 --- a/client/src/app/shared/instance/instance-features-table.component.html +++ /dev/null | |||
@@ -1,107 +0,0 @@ | |||
1 | <div class="feature-table"> | ||
2 | |||
3 | <table class="table" *ngIf="serverConfig"> | ||
4 | <caption i18n>Features found on this instance</caption> | ||
5 | <tr> | ||
6 | <th i18n class="label" scope="row">PeerTube version</th> | ||
7 | |||
8 | <td class="value">{{ getServerVersionAndCommit() }}</td> | ||
9 | </tr> | ||
10 | |||
11 | <tr> | ||
12 | <th i18n class="label" scope="row"> | ||
13 | <div>Default NSFW/sensitive videos policy</div> | ||
14 | <div class="more-info">can be redefined by the users</div> | ||
15 | </th> | ||
16 | |||
17 | <td class="value">{{ buildNSFWLabel() }}</td> | ||
18 | </tr> | ||
19 | |||
20 | <tr> | ||
21 | <th i18n class="label" scope="row">User registration allowed</th> | ||
22 | <td> | ||
23 | <my-feature-boolean [value]="serverConfig.signup.allowed"></my-feature-boolean> | ||
24 | </td> | ||
25 | </tr> | ||
26 | |||
27 | <tr> | ||
28 | <th i18n class="label" colspan="2">Video uploads</th> | ||
29 | </tr> | ||
30 | |||
31 | <tr> | ||
32 | <th i18n class="sub-label" scope="row">Transcoding in multiple resolutions</th> | ||
33 | <td> | ||
34 | <my-feature-boolean [value]="serverConfig.transcoding.enabledResolutions.length !== 0"></my-feature-boolean> | ||
35 | </td> | ||
36 | </tr> | ||
37 | |||
38 | <tr> | ||
39 | <th i18n class="sub-label" scope="row">Video uploads</th> | ||
40 | <td> | ||
41 | <span i18n *ngIf="serverConfig.autoBlacklist.videos.ofUsers.enabled">Requires manual validation by moderators</span> | ||
42 | <span i18n *ngIf="!serverConfig.autoBlacklist.videos.ofUsers.enabled">Automatically published</span> | ||
43 | </td> | ||
44 | </tr> | ||
45 | |||
46 | <tr> | ||
47 | <th i18n class="sub-label" scope="row">Video quota</th> | ||
48 | |||
49 | <td class="value"> | ||
50 | <ng-container *ngIf="initialUserVideoQuota !== -1"> | ||
51 | {{ initialUserVideoQuota | bytes: 0 }} <ng-container *ngIf="dailyUserVideoQuota !== -1">({{ dailyUserVideoQuota | bytes: 0 }} per day)</ng-container> | ||
52 | |||
53 | <my-help tooltipPlacement="auto" helpType="custom"> | ||
54 | <ng-template ptTemplate="customHtml"> | ||
55 | <div [innerHTML]="quotaHelpIndication"></div> | ||
56 | </ng-template> | ||
57 | </my-help> | ||
58 | </ng-container> | ||
59 | |||
60 | <ng-container i18n *ngIf="initialUserVideoQuota === -1"> | ||
61 | Unlimited <ng-container *ngIf="dailyUserVideoQuota !== -1">({{ dailyUserVideoQuota | bytes: 0 }} per day)</ng-container> | ||
62 | </ng-container> | ||
63 | </td> | ||
64 | </tr> | ||
65 | |||
66 | <tr> | ||
67 | <th i18n class="label" colspan="2">Import</th> | ||
68 | </tr> | ||
69 | |||
70 | <tr> | ||
71 | <th i18n class="sub-label" scope="row">HTTP import (YouTube, Vimeo, direct URL...)</th> | ||
72 | <td> | ||
73 | <my-feature-boolean [value]="serverConfig.import.videos.http.enabled"></my-feature-boolean> | ||
74 | </td> | ||
75 | </tr> | ||
76 | |||
77 | <tr> | ||
78 | <th i18n class="sub-label" scope="row">Torrent import</th> | ||
79 | <td> | ||
80 | <my-feature-boolean [value]="serverConfig.import.videos.torrent.enabled"></my-feature-boolean> | ||
81 | </td> | ||
82 | </tr> | ||
83 | |||
84 | |||
85 | <tr> | ||
86 | <th i18n class="label" colspan="2">Player</th> | ||
87 | </tr> | ||
88 | |||
89 | <tr> | ||
90 | <th i18n class="sub-label" scope="row">P2P enabled</th> | ||
91 | <td> | ||
92 | <my-feature-boolean [value]="serverConfig.tracker.enabled"></my-feature-boolean> | ||
93 | </td> | ||
94 | </tr> | ||
95 | |||
96 | <tr> | ||
97 | <th i18n class="label" colspan="2">Search</th> | ||
98 | </tr> | ||
99 | |||
100 | <tr> | ||
101 | <th i18n class="sub-label" scope="row">Users can resolve distant content</th> | ||
102 | <td> | ||
103 | <my-feature-boolean [value]="serverConfig.search.remoteUri.users"></my-feature-boolean> | ||
104 | </td> | ||
105 | </tr> | ||
106 | </table> | ||
107 | </div> | ||
diff --git a/client/src/app/shared/instance/instance-features-table.component.scss b/client/src/app/shared/instance/instance-features-table.component.scss deleted file mode 100644 index a51574741..000000000 --- a/client/src/app/shared/instance/instance-features-table.component.scss +++ /dev/null | |||
@@ -1,40 +0,0 @@ | |||
1 | @import '_variables'; | ||
2 | @import '_mixins'; | ||
3 | |||
4 | table { | ||
5 | font-size: 14px; | ||
6 | color: pvar(--mainForegroundColor); | ||
7 | |||
8 | .label, | ||
9 | .sub-label { | ||
10 | min-width: 330px; | ||
11 | |||
12 | &.label { | ||
13 | font-weight: $font-semibold; | ||
14 | } | ||
15 | |||
16 | &.sub-label { | ||
17 | font-weight: $font-regular; | ||
18 | padding-left: 30px; | ||
19 | } | ||
20 | |||
21 | .more-info { | ||
22 | font-style: italic; | ||
23 | font-weight: initial; | ||
24 | font-size: 14px | ||
25 | } | ||
26 | } | ||
27 | |||
28 | td { | ||
29 | vertical-align: middle; | ||
30 | } | ||
31 | |||
32 | caption { | ||
33 | caption-side: top; | ||
34 | font-size: 15px; | ||
35 | font-weight: $font-semibold; | ||
36 | color: pvar(--mainForegroundColor); | ||
37 | } | ||
38 | } | ||
39 | |||
40 | |||
diff --git a/client/src/app/shared/instance/instance-features-table.component.ts b/client/src/app/shared/instance/instance-features-table.component.ts deleted file mode 100644 index 8fd15ebad..000000000 --- a/client/src/app/shared/instance/instance-features-table.component.ts +++ /dev/null | |||
@@ -1,81 +0,0 @@ | |||
1 | import { Component, OnInit } from '@angular/core' | ||
2 | import { ServerService } from '@app/core' | ||
3 | import { I18n } from '@ngx-translate/i18n-polyfill' | ||
4 | import { ServerConfig } from '@shared/models' | ||
5 | |||
6 | @Component({ | ||
7 | selector: 'my-instance-features-table', | ||
8 | templateUrl: './instance-features-table.component.html', | ||
9 | styleUrls: [ './instance-features-table.component.scss' ] | ||
10 | }) | ||
11 | export class InstanceFeaturesTableComponent implements OnInit { | ||
12 | quotaHelpIndication = '' | ||
13 | serverConfig: ServerConfig | ||
14 | |||
15 | constructor ( | ||
16 | private i18n: I18n, | ||
17 | private serverService: ServerService | ||
18 | ) { | ||
19 | } | ||
20 | |||
21 | get initialUserVideoQuota () { | ||
22 | return this.serverConfig.user.videoQuota | ||
23 | } | ||
24 | |||
25 | get dailyUserVideoQuota () { | ||
26 | return Math.min(this.initialUserVideoQuota, this.serverConfig.user.videoQuotaDaily) | ||
27 | } | ||
28 | |||
29 | ngOnInit () { | ||
30 | this.serverConfig = this.serverService.getTmpConfig() | ||
31 | this.serverService.getConfig() | ||
32 | .subscribe(config => { | ||
33 | this.serverConfig = config | ||
34 | this.buildQuotaHelpIndication() | ||
35 | }) | ||
36 | } | ||
37 | |||
38 | buildNSFWLabel () { | ||
39 | const policy = this.serverConfig.instance.defaultNSFWPolicy | ||
40 | |||
41 | if (policy === 'do_not_list') return this.i18n('Hidden') | ||
42 | if (policy === 'blur') return this.i18n('Blurred with confirmation request') | ||
43 | if (policy === 'display') return this.i18n('Displayed') | ||
44 | } | ||
45 | |||
46 | getServerVersionAndCommit () { | ||
47 | return this.serverService.getServerVersionAndCommit() | ||
48 | } | ||
49 | |||
50 | private getApproximateTime (seconds: number) { | ||
51 | const hours = Math.floor(seconds / 3600) | ||
52 | let pluralSuffix = '' | ||
53 | if (hours > 1) pluralSuffix = 's' | ||
54 | if (hours > 0) return `~ ${hours} hour${pluralSuffix}` | ||
55 | |||
56 | const minutes = Math.floor(seconds % 3600 / 60) | ||
57 | |||
58 | return this.i18n('~ {{minutes}} {minutes, plural, =1 {minute} other {minutes}}', { minutes }) | ||
59 | } | ||
60 | |||
61 | private buildQuotaHelpIndication () { | ||
62 | if (this.initialUserVideoQuota === -1) return | ||
63 | |||
64 | const initialUserVideoQuotaBit = this.initialUserVideoQuota * 8 | ||
65 | |||
66 | // 1080p: ~ 6Mbps | ||
67 | // 720p: ~ 4Mbps | ||
68 | // 360p: ~ 1.5Mbps | ||
69 | const fullHdSeconds = initialUserVideoQuotaBit / (6 * 1000 * 1000) | ||
70 | const hdSeconds = initialUserVideoQuotaBit / (4 * 1000 * 1000) | ||
71 | const normalSeconds = initialUserVideoQuotaBit / (1.5 * 1000 * 1000) | ||
72 | |||
73 | const lines = [ | ||
74 | this.i18n('{{seconds}} of full HD videos', { seconds: this.getApproximateTime(fullHdSeconds) }), | ||
75 | this.i18n('{{seconds}} of HD videos', { seconds: this.getApproximateTime(hdSeconds) }), | ||
76 | this.i18n('{{seconds}} of average quality videos', { seconds: this.getApproximateTime(normalSeconds) }) | ||
77 | ] | ||
78 | |||
79 | this.quotaHelpIndication = lines.join('<br />') | ||
80 | } | ||
81 | } | ||
diff --git a/client/src/app/shared/instance/instance-statistics.component.html b/client/src/app/shared/instance/instance-statistics.component.html deleted file mode 100644 index 399cf10fe..000000000 --- a/client/src/app/shared/instance/instance-statistics.component.html +++ /dev/null | |||
@@ -1,101 +0,0 @@ | |||
1 | <p i18n *ngIf="null === serverStats">Loading instance statistics...</p> | ||
2 | |||
3 | <section *ngIf="null !== serverStats"> | ||
4 | <h3 i18n>Local</h3> | ||
5 | |||
6 | <div class="row"> | ||
7 | <div class="col-6 col-lg-4 col-xl-3"> | ||
8 | <div class="card stat"> | ||
9 | <div class="card-body"> | ||
10 | <p class="stat-value">{{ serverStats.totalUsers }}</p> | ||
11 | <p class="stat-label" i18n>users</p> | ||
12 | </div> | ||
13 | <i class="glyphicon glyphicon-user icon-bottom"></i> | ||
14 | </div> | ||
15 | </div> | ||
16 | |||
17 | <div class="col-6 col-lg-4 col-xl-3"> | ||
18 | <div class="card stat"> | ||
19 | <div class="card-body"> | ||
20 | <p class="stat-value">{{ serverStats.totalLocalVideos }}</p> | ||
21 | <p class="stat-label" i18n>videos</p> | ||
22 | </div> | ||
23 | <i class="glyphicon glyphicon-facetime-video"></i> | ||
24 | </div> | ||
25 | </div> | ||
26 | |||
27 | <div class="col-6 col-lg-4 col-xl-3"> | ||
28 | <div class="card stat"> | ||
29 | <div class="card-body"> | ||
30 | <p class="stat-value">{{ serverStats.totalLocalVideoViews }}</p> | ||
31 | <p class="stat-label" i18n>video views</p> | ||
32 | </div> | ||
33 | <i class="glyphicon glyphicon-eye-open"></i> | ||
34 | </div> | ||
35 | </div> | ||
36 | |||
37 | <div class="col-6 col-lg-4 col-xl-3"> | ||
38 | <div class="card stat"> | ||
39 | <div class="card-body"> | ||
40 | <p class="stat-value">{{ serverStats.totalLocalVideoComments }}</p> | ||
41 | <p class="stat-label" i18n>video comments</p> | ||
42 | </div> | ||
43 | <i class="glyphicon glyphicon-comment"></i> | ||
44 | </div> | ||
45 | </div> | ||
46 | |||
47 | <div class="col-6 col-lg-4 col-xl-3"> | ||
48 | <div class="card stat"> | ||
49 | <div class="card-body"> | ||
50 | <p class="stat-value">{{ serverStats.totalLocalVideoFilesSize | bytes:1 }}</p> | ||
51 | <p class="stat-label" i18n>of hosted video</p> | ||
52 | </div> | ||
53 | <i class="glyphicon glyphicon-hdd"></i> | ||
54 | </div> | ||
55 | </div> | ||
56 | </div> | ||
57 | |||
58 | <h3 i18n>Federation</h3> | ||
59 | |||
60 | <div class="row"> | ||
61 | <div class="col-6 col-lg-4 col-xl-3"> | ||
62 | <div class="card stat"> | ||
63 | <div class="card-body"> | ||
64 | <p class="stat-value">{{ serverStats.totalVideos }}</p> | ||
65 | <p class="stat-label" i18n>videos</p> | ||
66 | </div> | ||
67 | <i class="glyphicon glyphicon-facetime-video"></i> | ||
68 | </div> | ||
69 | </div> | ||
70 | |||
71 | <div class="col-6 col-lg-4 col-xl-3"> | ||
72 | <div class="card stat"> | ||
73 | <div class="card-body"> | ||
74 | <p class="stat-value">{{ serverStats.totalVideoComments }}</p> | ||
75 | <p class="stat-label" i18n>video comments</p> | ||
76 | </div> | ||
77 | <i class="glyphicon glyphicon-comment"></i> | ||
78 | </div> | ||
79 | </div> | ||
80 | |||
81 | <div class="col-6 col-lg-4 col-xl-3"> | ||
82 | <div class="card stat"> | ||
83 | <div class="card-body"> | ||
84 | <p class="stat-value">{{ serverStats.totalInstanceFollowers }}</p> | ||
85 | <p class="stat-label" i18n>followers</p> | ||
86 | </div> | ||
87 | <i class="glyphicon glyphicon-retweet"></i> | ||
88 | </div> | ||
89 | </div> | ||
90 | |||
91 | <div class="col-6 col-lg-4 col-xl-3"> | ||
92 | <div class="card stat"> | ||
93 | <div class="card-body"> | ||
94 | <p class="stat-value">{{ serverStats.totalInstanceFollowing }}</p> | ||
95 | <p class="stat-label" i18n>following</p> | ||
96 | </div> | ||
97 | <i class="glyphicon glyphicon-retweet"></i> | ||
98 | </div> | ||
99 | </div> | ||
100 | </div> | ||
101 | </section> | ||
diff --git a/client/src/app/shared/instance/instance-statistics.component.scss b/client/src/app/shared/instance/instance-statistics.component.scss deleted file mode 100644 index 5286ab03a..000000000 --- a/client/src/app/shared/instance/instance-statistics.component.scss +++ /dev/null | |||
@@ -1,40 +0,0 @@ | |||
1 | |||
2 | h3 { | ||
3 | font-size: 1.25rem; | ||
4 | } | ||
5 | |||
6 | .stat { | ||
7 | text-align: center; | ||
8 | margin-bottom: 1em; | ||
9 | overflow: hidden; | ||
10 | |||
11 | .stat-value { | ||
12 | font-size: 2.25em; | ||
13 | line-height: 1em; | ||
14 | margin: 0; | ||
15 | } | ||
16 | |||
17 | .stat-label { | ||
18 | font-size: 1.15em; | ||
19 | margin: 0; | ||
20 | } | ||
21 | |||
22 | .glyphicon { | ||
23 | opacity: 0.12; | ||
24 | position: absolute; | ||
25 | left: 16px; | ||
26 | top: -24px; | ||
27 | |||
28 | &.icon-bottom { | ||
29 | top: 4px; | ||
30 | } | ||
31 | |||
32 | &::before { | ||
33 | font-size: 8em; | ||
34 | } | ||
35 | } | ||
36 | |||
37 | .card-body { | ||
38 | z-index: 2; | ||
39 | } | ||
40 | } | ||
diff --git a/client/src/app/shared/instance/instance-statistics.component.ts b/client/src/app/shared/instance/instance-statistics.component.ts deleted file mode 100644 index 40aa8a4c0..000000000 --- a/client/src/app/shared/instance/instance-statistics.component.ts +++ /dev/null | |||
@@ -1,22 +0,0 @@ | |||
1 | import { Component, OnInit } from '@angular/core' | ||
2 | import { ServerStats } from '@shared/models/server' | ||
3 | import { ServerService } from '@app/core' | ||
4 | |||
5 | @Component({ | ||
6 | selector: 'my-instance-statistics', | ||
7 | templateUrl: './instance-statistics.component.html', | ||
8 | styleUrls: [ './instance-statistics.component.scss' ] | ||
9 | }) | ||
10 | export class InstanceStatisticsComponent implements OnInit { | ||
11 | serverStats: ServerStats = null | ||
12 | |||
13 | constructor ( | ||
14 | private serverService: ServerService | ||
15 | ) { | ||
16 | } | ||
17 | |||
18 | ngOnInit () { | ||
19 | this.serverService.getServerStats() | ||
20 | .subscribe(res => this.serverStats = res) | ||
21 | } | ||
22 | } | ||
diff --git a/client/src/app/shared/instance/instance.service.ts b/client/src/app/shared/instance/instance.service.ts deleted file mode 100644 index 8b26063fb..000000000 --- a/client/src/app/shared/instance/instance.service.ts +++ /dev/null | |||
@@ -1,92 +0,0 @@ | |||
1 | import { catchError, map } from 'rxjs/operators' | ||
2 | import { HttpClient } from '@angular/common/http' | ||
3 | import { Injectable } from '@angular/core' | ||
4 | import { environment } from '../../../environments/environment' | ||
5 | import { RestExtractor, RestService } from '../rest' | ||
6 | import { About } from '../../../../../shared/models/server' | ||
7 | import { MarkdownService } from '@app/shared/renderer' | ||
8 | import { peertubeTranslate } from '@shared/models' | ||
9 | import { ServerService } from '@app/core' | ||
10 | import { forkJoin } from 'rxjs' | ||
11 | |||
12 | @Injectable() | ||
13 | export class InstanceService { | ||
14 | private static BASE_CONFIG_URL = environment.apiUrl + '/api/v1/config' | ||
15 | private static BASE_SERVER_URL = environment.apiUrl + '/api/v1/server' | ||
16 | |||
17 | constructor ( | ||
18 | private authHttp: HttpClient, | ||
19 | private restService: RestService, | ||
20 | private restExtractor: RestExtractor, | ||
21 | private markdownService: MarkdownService, | ||
22 | private serverService: ServerService | ||
23 | ) { | ||
24 | } | ||
25 | |||
26 | getAbout () { | ||
27 | return this.authHttp.get<About>(InstanceService.BASE_CONFIG_URL + '/about') | ||
28 | .pipe(catchError(res => this.restExtractor.handleError(res))) | ||
29 | } | ||
30 | |||
31 | contactAdministrator (fromEmail: string, fromName: string, subject: string, message: string) { | ||
32 | const body = { | ||
33 | fromEmail, | ||
34 | fromName, | ||
35 | subject, | ||
36 | body: message | ||
37 | } | ||
38 | |||
39 | return this.authHttp.post(InstanceService.BASE_SERVER_URL + '/contact', body) | ||
40 | .pipe(catchError(res => this.restExtractor.handleError(res))) | ||
41 | |||
42 | } | ||
43 | |||
44 | async buildHtml (about: About) { | ||
45 | const html = { | ||
46 | description: '', | ||
47 | terms: '', | ||
48 | codeOfConduct: '', | ||
49 | moderationInformation: '', | ||
50 | administrator: '', | ||
51 | hardwareInformation: '' | ||
52 | } | ||
53 | |||
54 | for (const key of Object.keys(html)) { | ||
55 | html[ key ] = await this.markdownService.textMarkdownToHTML(about.instance[ key ]) | ||
56 | } | ||
57 | |||
58 | return html | ||
59 | } | ||
60 | |||
61 | buildTranslatedLanguages (about: About) { | ||
62 | return forkJoin([ | ||
63 | this.serverService.getVideoLanguages(), | ||
64 | this.serverService.getServerLocale() | ||
65 | ]).pipe( | ||
66 | map(([ languagesArray, translations ]) => { | ||
67 | return about.instance.languages | ||
68 | .map(l => { | ||
69 | const languageObj = languagesArray.find(la => la.id === l) | ||
70 | |||
71 | return peertubeTranslate(languageObj.label, translations) | ||
72 | }) | ||
73 | }) | ||
74 | ) | ||
75 | } | ||
76 | |||
77 | buildTranslatedCategories (about: About) { | ||
78 | return forkJoin([ | ||
79 | this.serverService.getVideoCategories(), | ||
80 | this.serverService.getServerLocale() | ||
81 | ]).pipe( | ||
82 | map(([ categoriesArray, translations ]) => { | ||
83 | return about.instance.categories | ||
84 | .map(c => { | ||
85 | const categoryObj = categoriesArray.find(ca => ca.id === c) | ||
86 | |||
87 | return peertubeTranslate(categoryObj.label, translations) | ||
88 | }) | ||
89 | }) | ||
90 | ) | ||
91 | } | ||
92 | } | ||