Add statistics section in about page
authorJulien Maulny <julien.maulny@protonmail.com>
Wed, 2 Oct 2019 20:37:01 +0000 (22:37 +0200)
committerChocobozzz <chocobozzz@cpy.re>
Fri, 18 Oct 2019 13:13:30 +0000 (15:13 +0200)
client/src/app/+about/about-instance/about-instance.component.html
client/src/app/shared/instance/instance-statistics.component.html [new file with mode: 0644]
client/src/app/shared/instance/instance-statistics.component.scss [new file with mode: 0644]
client/src/app/shared/instance/instance-statistics.component.ts [new file with mode: 0644]
client/src/app/shared/shared.module.ts

index 25d41674079cecc99860a0a99015890c7c7bbfd0..f05f33d36a378b8647daa15d5cd4504a0288171b 100644 (file)
     <label i18n>Features found on this instance</label>
     <my-instance-features-table></my-instance-features-table>
   </div>
+
+  <div class="col">
+    <div i18n class="middle-title">
+      Statistics
+    </div>
+    <my-instance-statistics></my-instance-statistics>
+  </div>
 </div>
 
 <my-contact-admin-modal #contactAdminModal></my-contact-admin-modal>
diff --git a/client/src/app/shared/instance/instance-statistics.component.html b/client/src/app/shared/instance/instance-statistics.component.html
new file mode 100644 (file)
index 0000000..181c57b
--- /dev/null
@@ -0,0 +1,101 @@
+<p i18n *ngIf="null === serverStats">Loading instance statistics...</p>
+
+<section *ngIf="null !== serverStats">
+  <h5 i18n>Local</h5>
+
+  <div class="row">
+    <div class="col-6 col-lg-4 col-xl-3">
+      <div class="card stat">
+        <div class="card-body">
+          <p class="stat-value">{{ serverStats.totalUsers }}</p>
+          <p class="stat-label" i18n>users</p>
+        </div>
+        <i class="glyphicon glyphicon-user icon-bottom"></i>
+      </div>
+    </div>
+
+    <div class="col-6 col-lg-4 col-xl-3">
+      <div class="card stat">
+        <div class="card-body">
+          <p class="stat-value">{{ serverStats.totalLocalVideos }}</p>
+          <p class="stat-label" i18n>videos</p>
+        </div>
+        <i class="glyphicon glyphicon-facetime-video"></i>
+      </div>
+    </div>
+
+    <div class="col-6 col-lg-4 col-xl-3">
+      <div class="card stat">
+        <div class="card-body">
+          <p class="stat-value">{{ serverStats.totalLocalVideoViews }}</p>
+          <p class="stat-label" i18n>videos views</p>
+        </div>
+        <i class="glyphicon glyphicon-eye-open"></i>
+      </div>
+    </div>
+
+    <div class="col-6 col-lg-4 col-xl-3">
+      <div class="card stat">
+        <div class="card-body">
+          <p class="stat-value">{{ serverStats.totalLocalVideoComments }}</p>
+          <p class="stat-label" i18n>videos comments</p>
+        </div>
+        <i class="glyphicon glyphicon-comment"></i>
+      </div>
+    </div>
+
+    <div class="col-6 col-lg-4 col-xl-3">
+      <div class="card stat">
+        <div class="card-body">
+          <p class="stat-value">{{ serverStats.totalLocalVideoFilesSize | bytes:1 }}</p>
+          <p class="stat-label" i18n>of hosted video</p>
+        </div>
+        <i class="glyphicon glyphicon-hdd"></i>
+      </div>
+    </div>
+  </div>
+
+  <h5 i18n>Federation</h5>
+
+  <div class="row">
+    <div class="col-6 col-lg-4 col-xl-3">
+      <div class="card stat">
+        <div class="card-body">
+          <p class="stat-value">{{ serverStats.totalVideos }}</p>
+          <p class="stat-label" i18n>videos</p>
+        </div>
+        <i class="glyphicon glyphicon-facetime-video"></i>
+      </div>
+    </div>
+
+    <div class="col-6 col-lg-4 col-xl-3">
+      <div class="card stat">
+        <div class="card-body">
+          <p class="stat-value">{{ serverStats.totalVideoComments }}</p>
+          <p class="stat-label" i18n>videos comments</p>
+        </div>
+        <i class="glyphicon glyphicon-comment"></i>
+      </div>
+    </div>
+
+    <div class="col-6 col-lg-4 col-xl-3">
+      <div class="card stat">
+        <div class="card-body">
+          <p class="stat-value">{{ serverStats.totalInstanceFollowers }}</p>
+          <p class="stat-label" i18n>followers</p>
+        </div>
+        <i class="glyphicon glyphicon-retweet"></i>
+      </div>
+    </div>
+
+    <div class="col-6 col-lg-4 col-xl-3">
+      <div class="card stat">
+        <div class="card-body">
+          <p class="stat-value">{{ serverStats.totalInstanceFollowing }}</p>
+          <p class="stat-label" i18n>following</p>
+        </div>
+        <i class="glyphicon glyphicon-retweet"></i>
+      </div>
+    </div>
+  </div>
+</section>
diff --git a/client/src/app/shared/instance/instance-statistics.component.scss b/client/src/app/shared/instance/instance-statistics.component.scss
new file mode 100644 (file)
index 0000000..63f8911
--- /dev/null
@@ -0,0 +1,35 @@
+.stat {
+  text-align: center;
+  margin-bottom: 1em;
+  overflow: hidden;
+
+  .stat-value {
+    font-size: 2.25em;
+    line-height: 1em;
+    margin: 0;
+  }
+
+  .stat-label {
+    font-size: 1.15em;
+    margin: 0;
+  }
+
+  .glyphicon {
+    opacity: 0.12;
+    position: absolute;
+    left: 16px;
+    top: -24px;
+
+    &.icon-bottom {
+      top: 4px;
+    }
+
+    &::before {
+      font-size: 8em;
+    }
+  }
+
+  .card-body {
+    z-index: 2;
+  }
+}
diff --git a/client/src/app/shared/instance/instance-statistics.component.ts b/client/src/app/shared/instance/instance-statistics.component.ts
new file mode 100644 (file)
index 0000000..8ec728f
--- /dev/null
@@ -0,0 +1,37 @@
+import { map } from 'rxjs/operators'
+import { HttpClient } from '@angular/common/http'
+import { Component, OnInit } from '@angular/core'
+import { I18n } from '@ngx-translate/i18n-polyfill'
+import { ServerStats } from '@shared/models/server'
+import { environment } from '../../../environments/environment'
+
+@Component({
+  selector: 'my-instance-statistics',
+  templateUrl: './instance-statistics.component.html',
+  styleUrls: [ './instance-statistics.component.scss' ]
+})
+export class InstanceStatisticsComponent implements OnInit {
+  private static BASE_STATS_URL = environment.apiUrl + '/api/v1/server/stats'
+
+  serverStats: ServerStats = null
+
+  constructor (
+    private http: HttpClient,
+    private i18n: I18n
+  ) {
+  }
+
+  ngOnInit () {
+    this.getStats()
+      .subscribe(
+        res => {
+          this.serverStats = res
+        }
+      )
+  }
+
+  getStats () {
+    return this.http
+      .get<ServerStats>(InstanceStatisticsComponent.BASE_STATS_URL)
+  }
+}
index 65e0f21a4d9874e9a6de1b76baed229ab9aeaf57..f6991a66da8ccfb5ef4b56b9ac71f9f92a800cf0 100644 (file)
@@ -61,6 +61,7 @@ import {
 } from '@ng-bootstrap/ng-bootstrap'
 import { RemoteSubscribeComponent, SubscribeButtonComponent, UserSubscriptionService } from '@app/shared/user-subscription'
 import { InstanceFeaturesTableComponent } from '@app/shared/instance/instance-features-table.component'
+import { InstanceStatisticsComponent } from '@app/shared/instance/instance-statistics.component'
 import { OverviewService } from '@app/shared/overview'
 import { UserBanModalComponent } from '@app/shared/moderation'
 import { UserModerationDropdownComponent } from '@app/shared/moderation/user-moderation-dropdown.component'
@@ -157,6 +158,7 @@ import { FeatureBooleanComponent } from '@app/shared/instance/feature-boolean.co
     SubscribeButtonComponent,
     RemoteSubscribeComponent,
     InstanceFeaturesTableComponent,
+    InstanceStatisticsComponent,
     FeatureBooleanComponent,
     UserBanModalComponent,
     UserModerationDropdownComponent,
@@ -224,6 +226,7 @@ import { FeatureBooleanComponent } from '@app/shared/instance/feature-boolean.co
     SubscribeButtonComponent,
     RemoteSubscribeComponent,
     InstanceFeaturesTableComponent,
+    InstanceStatisticsComponent,
     UserBanModalComponent,
     UserModerationDropdownComponent,
     TopMenuDropdownComponent,