From 2587a57a57f652630eafb65b2917bc74ccd908ae Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Thu, 4 May 2017 20:30:04 +0200 Subject: [PATCH] Monthly aggregation. --- .../UsageTracking/BackgroundUsageTracker.cs | 7 ++-- .../Api/Apps/AppUsageController.cs | 21 +++++++++++- .../Api/Apps/Models/MonthlyCallsDto.cs | 18 ++++++++++ .../assets/pages/assets-page.component.ts | 4 +-- .../pages/content/content-page.component.ts | 4 +-- .../pages/contents/contents-page.component.ts | 8 ++--- .../pages/schemas/schemas-page.component.ts | 2 +- .../pages/dashboard-page.component.html | 14 ++++++-- .../pages/dashboard-page.component.scss | 34 +++++++++++++++---- .../pages/dashboard-page.component.ts | 12 +++++++ .../pages/schema/schema-page.component.ts | 22 ++++++------ .../pages/schemas/schemas-page.component.ts | 2 +- .../pages/clients/clients-page.component.ts | 8 ++--- .../contributors-page.component.ts | 8 ++--- .../languages/languages-page.component.ts | 8 ++--- .../shared/components/app.component-base.ts | 4 +++ .../app/shared/components/asset.component.ts | 6 ++-- .../components/assets-editor.component.ts | 2 +- .../shared/components/history.component.ts | 2 +- .../shared/services/usages.service.spec.ts | 23 +++++++++++++ .../app/shared/services/usages.service.ts | 18 ++++++++++ src/Squidex/package.json | 2 +- 22 files changed, 176 insertions(+), 53 deletions(-) create mode 100644 src/Squidex/Controllers/Api/Apps/Models/MonthlyCallsDto.cs diff --git a/src/Squidex.Infrastructure/UsageTracking/BackgroundUsageTracker.cs b/src/Squidex.Infrastructure/UsageTracking/BackgroundUsageTracker.cs index 4bee1df6a..8f1baa41d 100644 --- a/src/Squidex.Infrastructure/UsageTracking/BackgroundUsageTracker.cs +++ b/src/Squidex.Infrastructure/UsageTracking/BackgroundUsageTracker.cs @@ -111,15 +111,14 @@ namespace Squidex.Infrastructure.UsageTracking ThrowIfDisposed(); var originalUsages = await usageStore.FindAsync(key, fromDate, toDate); - - var result = new List(); + var enrichedUsages = new List(); for (var date = fromDate; date <= toDate; date = date.AddDays(1)) { - result.Add(originalUsages.FirstOrDefault(x => x.Date == date) ?? new StoredUsage(date, 0, 0)); + enrichedUsages.Add(originalUsages.FirstOrDefault(x => x.Date == date) ?? new StoredUsage(date, 0, 0)); } - return result; + return enrichedUsages; } public async Task GetMonthlyCalls(string key, DateTime date) diff --git a/src/Squidex/Controllers/Api/Apps/AppUsageController.cs b/src/Squidex/Controllers/Api/Apps/AppUsageController.cs index 16c6b8004..56ae8bfa1 100644 --- a/src/Squidex/Controllers/Api/Apps/AppUsageController.cs +++ b/src/Squidex/Controllers/Api/Apps/AppUsageController.cs @@ -37,7 +37,26 @@ namespace Squidex.Controllers.Api.Apps } /// - /// Get app usages. + /// Get api calls for this month. + /// + /// The name of the app. + /// + /// 200 => Usage tracking results returned. + /// 404 => App not found. + /// + [Authorize(Roles = SquidexRoles.AppEditor)] + [HttpGet] + [Route("apps/{app}/usages/monthly")] + [ProducesResponseType(typeof(MonthlyCallsDto), 200)] + public async Task GetMonthlyCalls(string app) + { + var count = await usageTracker.GetMonthlyCalls(App.Id.ToString(), DateTime.Today); + + return Ok(new MonthlyCallsDto { Count = count }); + } + + /// + /// Get api calls in date range. /// /// The name of the app. /// The from date. diff --git a/src/Squidex/Controllers/Api/Apps/Models/MonthlyCallsDto.cs b/src/Squidex/Controllers/Api/Apps/Models/MonthlyCallsDto.cs new file mode 100644 index 000000000..684011bb4 --- /dev/null +++ b/src/Squidex/Controllers/Api/Apps/Models/MonthlyCallsDto.cs @@ -0,0 +1,18 @@ +// ========================================================================== +// MonthlyCallsDto.cs +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex Group +// All rights reserved. +// ========================================================================== + +namespace Squidex.Controllers.Api.Apps.Models +{ + public class MonthlyCallsDto + { + /// + /// The number of calls. + /// + public long Count { get; set; } + } +} diff --git a/src/Squidex/app/features/assets/pages/assets-page.component.ts b/src/Squidex/app/features/assets/pages/assets-page.component.ts index 04e73b7fd..0fd5b69e9 100644 --- a/src/Squidex/app/features/assets/pages/assets-page.component.ts +++ b/src/Squidex/app/features/assets/pages/assets-page.component.ts @@ -73,7 +73,7 @@ export class AssetsPageComponent extends AppComponentBase implements OnDestroy, } public load(showInfo = false) { - this.appName() + this.appNameOnce() .switchMap(app => this.assetsService.getAssets(app, this.assetsPager.pageSize, this.assetsPager.skip, this.assertQuery)) .subscribe(dtos => { this.assetsItems = ImmutableArray.of(dtos.items); @@ -88,7 +88,7 @@ export class AssetsPageComponent extends AppComponentBase implements OnDestroy, } public onAssetDeleting(asset: AssetDto) { - this.appName() + this.appNameOnce() .switchMap(app => this.assetsService.deleteAsset(app, asset.id, asset.version)) .subscribe(dtos => { this.assetsItems = this.assetsItems.filter(x => x.id !== asset.id); diff --git a/src/Squidex/app/features/content/pages/content/content-page.component.ts b/src/Squidex/app/features/content/pages/content/content-page.component.ts index a555754b7..370a6af7e 100644 --- a/src/Squidex/app/features/content/pages/content/content-page.component.ts +++ b/src/Squidex/app/features/content/pages/content/content-page.component.ts @@ -138,7 +138,7 @@ export class ContentPageComponent extends AppComponentBase implements CanCompone const data = this.contentForm.value; if (this.isNewMode) { - this.appName() + this.appNameOnce() .switchMap(app => this.contentsService.postContent(app, this.schema.name, data, publish, this.version)) .subscribe(created => { this.contentId = created.id; @@ -154,7 +154,7 @@ export class ContentPageComponent extends AppComponentBase implements CanCompone this.enable(); }); } else { - this.appName() + this.appNameOnce() .switchMap(app => this.contentsService.putContent(app, this.schema.name, this.contentId!, data, this.version)) .subscribe(() => { this.messageBus.publish(new ContentUpdated(this.contentId!, data, this.version.value)); diff --git a/src/Squidex/app/features/content/pages/contents/contents-page.component.ts b/src/Squidex/app/features/content/pages/contents/contents-page.component.ts index 6b9df641d..96fd3480b 100644 --- a/src/Squidex/app/features/content/pages/contents/contents-page.component.ts +++ b/src/Squidex/app/features/content/pages/contents/contents-page.component.ts @@ -114,7 +114,7 @@ export class ContentsPageComponent extends AppComponentBase implements OnDestroy } public publishContent(content: ContentDto) { - this.appName() + this.appNameOnce() .switchMap(app => this.contentsService.publishContent(app, this.schema.name, content.id, content.version)) .subscribe(() => { this.updateContents(content.id, true, content.data, content.version.value); @@ -124,7 +124,7 @@ export class ContentsPageComponent extends AppComponentBase implements OnDestroy } public unpublishContent(content: ContentDto) { - this.appName() + this.appNameOnce() .switchMap(app => this.contentsService.unpublishContent(app, this.schema.name, content.id, content.version)) .subscribe(() => { this.updateContents(content.id, false, content.data, content.version.value); @@ -134,7 +134,7 @@ export class ContentsPageComponent extends AppComponentBase implements OnDestroy } public deleteContent(content: ContentDto) { - this.appName() + this.appNameOnce() .switchMap(app => this.contentsService.deleteContent(app, this.schema.name, content.id, content.version)) .subscribe(() => { this.contentItems = this.contentItems.removeAll(x => x.id === content.id); @@ -161,7 +161,7 @@ export class ContentsPageComponent extends AppComponentBase implements OnDestroy } public load(showInfo = false) { - this.appName() + this.appNameOnce() .switchMap(app => this.contentsService.getContents(app, this.schema.name, this.contentsPager.pageSize, this.contentsPager.skip, this.contentsQuery)) .subscribe(dtos => { this.contentItems = ImmutableArray.of(dtos.items); diff --git a/src/Squidex/app/features/content/pages/schemas/schemas-page.component.ts b/src/Squidex/app/features/content/pages/schemas/schemas-page.component.ts index 4bdf7e299..c9c24de2c 100644 --- a/src/Squidex/app/features/content/pages/schemas/schemas-page.component.ts +++ b/src/Squidex/app/features/content/pages/schemas/schemas-page.component.ts @@ -59,7 +59,7 @@ export class SchemasPageComponent extends AppComponentBase { } private loadSchemas(): Observable { - return this.appName() + return this.appNameOnce() .switchMap(app => this.schemasService.getSchemas(app).retry(2)) .catch(error => { this.notifyError(error); diff --git a/src/Squidex/app/features/dashboard/pages/dashboard-page.component.html b/src/Squidex/app/features/dashboard/pages/dashboard-page.component.html index f7f8e16b1..c935d2f6f 100644 --- a/src/Squidex/app/features/dashboard/pages/dashboard-page.component.html +++ b/src/Squidex/app/features/dashboard/pages/dashboard-page.component.html @@ -1,6 +1,8 @@
+
+

Hi {{profileDisplayName}}

@@ -50,19 +52,25 @@

Get the source code from Github and report bugs or ask for support.

-
-
-
+ +
+
+
+
API calls this month
+
{{monthlyCalls}}
+
+
+
\ No newline at end of file diff --git a/src/Squidex/app/features/dashboard/pages/dashboard-page.component.scss b/src/Squidex/app/features/dashboard/pages/dashboard-page.component.scss index 5470b902d..67bbb5a54 100644 --- a/src/Squidex/app/features/dashboard/pages/dashboard-page.component.scss +++ b/src/Squidex/app/features/dashboard/pages/dashboard-page.component.scss @@ -2,8 +2,16 @@ @import '_mixins'; .dashboard { - padding: 2rem; - padding-right: 1rem; + & { + @include absolute(0, 0, 0, 0); + overflow-y: auto; + } + + &-inner { + padding: 2rem; + padding-right: 1rem; + max-width: 75rem; + } } h1 { @@ -17,10 +25,6 @@ h1 { color: $color-subtext; } -.app-name { - color: $color-title; -} - a { &.card { cursor: pointer; @@ -71,4 +75,22 @@ a { font-size: 1.2rem; margin-top: .4rem; } +} + +.monthly-calls { + & { + text-align: center; + } + + &-value { + font-size: 5rem; + } + + &-label { + color: $color-subtext; + } +} + +.app-name { + color: $color-title; } \ No newline at end of file diff --git a/src/Squidex/app/features/dashboard/pages/dashboard-page.component.ts b/src/Squidex/app/features/dashboard/pages/dashboard-page.component.ts index 0f61ca3c9..6dd0346f6 100644 --- a/src/Squidex/app/features/dashboard/pages/dashboard-page.component.ts +++ b/src/Squidex/app/features/dashboard/pages/dashboard-page.component.ts @@ -37,6 +37,8 @@ export class DashboardPageComponent extends AppComponentBase implements OnInit, public chartPerformance: any; public chartOptions = { }; + public monthlyCalls: string = null; + constructor(apps: AppsStoreService, notifications: NotificationService, private readonly auth: AuthService, private readonly usagesService: UsagesService @@ -49,6 +51,16 @@ export class DashboardPageComponent extends AppComponentBase implements OnInit, } public ngOnInit() { + this.appName() + .switchMap(app => this.usagesService.getMonthlyCalls(app)) + .subscribe(dto => { + if (dto.count > 1000) { + this.monthlyCalls = Math.round(dto.count / 1000) + 'k'; + } else { + this.monthlyCalls = dto.count.toString(); + } + }); + this.appName() .switchMap(app => this.usagesService.getUsages(app, DateTime.today().addDays(-30), DateTime.today())) .subscribe(dtos => { diff --git a/src/Squidex/app/features/schemas/pages/schema/schema-page.component.ts b/src/Squidex/app/features/schemas/pages/schema/schema-page.component.ts index 1c5170456..582b61c10 100644 --- a/src/Squidex/app/features/schemas/pages/schema/schema-page.component.ts +++ b/src/Squidex/app/features/schemas/pages/schema/schema-page.component.ts @@ -105,7 +105,7 @@ export class SchemaPageComponent extends AppComponentBase implements OnInit { } public publish() { - this.appName() + this.appNameOnce() .switchMap(app => this.schemasService.publishSchema(app, this.schemaName, this.version)).retry(2) .subscribe(() => { this.isPublished = true; @@ -116,7 +116,7 @@ export class SchemaPageComponent extends AppComponentBase implements OnInit { } public unpublish() { - this.appName() + this.appNameOnce() .switchMap(app => this.schemasService.unpublishSchema(app, this.schemaName, this.version)).retry(2) .subscribe(() => { this.isPublished = false; @@ -127,7 +127,7 @@ export class SchemaPageComponent extends AppComponentBase implements OnInit { } public enableField(field: FieldDto) { - this.appName() + this.appNameOnce() .switchMap(app => this.schemasService.enableField(app, this.schemaName, field.fieldId, this.version)).retry(2) .subscribe(() => { this.updateField(field, new FieldDto(field.fieldId, field.name, field.isHidden, false, field.properties)); @@ -137,7 +137,7 @@ export class SchemaPageComponent extends AppComponentBase implements OnInit { } public disableField(field: FieldDto) { - this.appName() + this.appNameOnce() .switchMap(app => this.schemasService.disableField(app, this.schemaName, field.fieldId, this.version)).retry(2) .subscribe(() => { this.updateField(field, new FieldDto(field.fieldId, field.name, field.isHidden, true, field.properties)); @@ -147,7 +147,7 @@ export class SchemaPageComponent extends AppComponentBase implements OnInit { } public showField(field: FieldDto) { - this.appName() + this.appNameOnce() .switchMap(app => this.schemasService.showField(app, this.schemaName, field.fieldId, this.version)).retry(2) .subscribe(() => { this.updateField(field, new FieldDto(field.fieldId, field.name, false, field.isDisabled, field.properties)); @@ -157,7 +157,7 @@ export class SchemaPageComponent extends AppComponentBase implements OnInit { } public hideField(field: FieldDto) { - this.appName() + this.appNameOnce() .switchMap(app => this.schemasService.hideField(app, this.schemaName, field.fieldId, this.version)).retry(2) .subscribe(() => { this.updateField(field, new FieldDto(field.fieldId, field.name, true, field.isDisabled, field.properties)); @@ -167,7 +167,7 @@ export class SchemaPageComponent extends AppComponentBase implements OnInit { } public deleteField(field: FieldDto) { - this.appName() + this.appNameOnce() .switchMap(app => this.schemasService.deleteField(app, this.schemaName, field.fieldId, this.version)).retry(2) .subscribe(() => { this.updateFields(this.schemaFields.remove(field)); @@ -179,7 +179,7 @@ export class SchemaPageComponent extends AppComponentBase implements OnInit { public sortFields(fields: FieldDto[]) { this.updateFields(ImmutableArray.of(fields)); - this.appName() + this.appNameOnce() .switchMap(app => this.schemasService.putFieldOrdering(app, this.schemaName, fields.map(t => t.fieldId), this.version)).retry(2) .subscribe(() => { this.updateFields(ImmutableArray.of(fields)); @@ -191,7 +191,7 @@ export class SchemaPageComponent extends AppComponentBase implements OnInit { public saveField(field: FieldDto, newField: FieldDto) { const request = new UpdateFieldDto(newField.properties); - this.appName() + this.appNameOnce() .switchMap(app => this.schemasService.putField(app, this.schemaName, field.fieldId, request, this.version)).retry(2) .subscribe(() => { this.updateField(field, new FieldDto(field.fieldId, field.name, newField.isHidden, field.isDisabled, newField.properties)); @@ -201,7 +201,7 @@ export class SchemaPageComponent extends AppComponentBase implements OnInit { } public deleteSchema() { - this.appName() + this.appNameOnce() .switchMap(app => this.schemasService.deleteSchema(app, this.schemaName, this.version)).retry(2) .finally(() => { this.confirmDeleteDialog.hide(); @@ -231,7 +231,7 @@ export class SchemaPageComponent extends AppComponentBase implements OnInit { this.addFieldFormSubmitted = false; }; - this.appName() + this.appNameOnce() .switchMap(app => this.schemasService.postField(app, this.schemaName, requestDto, this.version)) .subscribe(dto => { const newField = diff --git a/src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.ts b/src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.ts index 4354914af..7b7b5a07e 100644 --- a/src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.ts +++ b/src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.ts @@ -91,7 +91,7 @@ export class SchemasPageComponent extends AppComponentBase implements OnDestroy, } private load() { - this.appName() + this.appNameOnce() .switchMap(app => this.schemasService.getSchemas(app).retry(2)) .subscribe(dtos => { this.updateSchemas(ImmutableArray.of(dtos)); diff --git a/src/Squidex/app/features/settings/pages/clients/clients-page.component.ts b/src/Squidex/app/features/settings/pages/clients/clients-page.component.ts index 7a38974a3..eed955f43 100644 --- a/src/Squidex/app/features/settings/pages/clients/clients-page.component.ts +++ b/src/Squidex/app/features/settings/pages/clients/clients-page.component.ts @@ -60,7 +60,7 @@ export class ClientsPageComponent extends AppComponentBase implements OnInit { } public load() { - this.appName() + this.appNameOnce() .switchMap(app => this.appClientsService.getClients(app, this.version).retry(2)) .subscribe(dtos => { this.updateClients(ImmutableArray.of(dtos)); @@ -70,7 +70,7 @@ export class ClientsPageComponent extends AppComponentBase implements OnInit { } public revokeClient(client: AppClientDto) { - this.appName() + this.appNameOnce() .switchMap(app => this.appClientsService.deleteClient(app, client.id, this.version)) .subscribe(() => { this.updateClients(this.appClients.remove(client)); @@ -82,7 +82,7 @@ export class ClientsPageComponent extends AppComponentBase implements OnInit { public renameClient(client: AppClientDto, name: string) { const request = new UpdateAppClientDto(name); - this.appName() + this.appNameOnce() .switchMap(app => this.appClientsService.updateClient(app, client.id, request, this.version)) .subscribe(() => { this.updateClients(this.appClients.replace(client, rename(client, name))); @@ -111,7 +111,7 @@ export class ClientsPageComponent extends AppComponentBase implements OnInit { this.addClientForm.enable(); }; - this.appName() + this.appNameOnce() .switchMap(app => this.appClientsService.postClient(app, requestDto, this.version)) .subscribe(dto => { this.updateClients(this.appClients.push(dto)); diff --git a/src/Squidex/app/features/settings/pages/contributors/contributors-page.component.ts b/src/Squidex/app/features/settings/pages/contributors/contributors-page.component.ts index 73ff180f8..8ee1fdfdf 100644 --- a/src/Squidex/app/features/settings/pages/contributors/contributors-page.component.ts +++ b/src/Squidex/app/features/settings/pages/contributors/contributors-page.component.ts @@ -97,7 +97,7 @@ export class ContributorsPageComponent extends AppComponentBase implements OnIni } public load() { - this.appName() + this.appNameOnce() .switchMap(app => this.appContributorsService.getContributors(app, this.version).retry(2)) .subscribe(dtos => { this.updateContributors(ImmutableArray.of(dtos)); @@ -107,7 +107,7 @@ export class ContributorsPageComponent extends AppComponentBase implements OnIni } public removeContributor(contributor: AppContributorDto) { - this.appName() + this.appNameOnce() .switchMap(app => this.appContributorsService.deleteContributor(app, contributor.contributorId, this.version)) .subscribe(() => { this.updateContributors(this.appContributors.remove(contributor)); @@ -119,7 +119,7 @@ export class ContributorsPageComponent extends AppComponentBase implements OnIni public assignContributor() { const newContributor = new AppContributorDto(this.addContributorForm.get('user')!.value.model.id, 'Editor'); - this.appName() + this.appNameOnce() .switchMap(app => this.appContributorsService.postContributor(app, newContributor, this.version)) .subscribe(() => { this.updateContributors(this.appContributors.push(newContributor)); @@ -133,7 +133,7 @@ export class ContributorsPageComponent extends AppComponentBase implements OnIni public changePermission(contributor: AppContributorDto, permission: string) { const newContributor = changePermission(contributor, permission); - this.appName() + this.appNameOnce() .switchMap(app => this.appContributorsService.postContributor(app, newContributor, this.version)) .subscribe(() => { this.updateContributors(this.appContributors.replace(contributor, newContributor)); diff --git a/src/Squidex/app/features/settings/pages/languages/languages-page.component.ts b/src/Squidex/app/features/settings/pages/languages/languages-page.component.ts index de06f4e11..a9992e90f 100644 --- a/src/Squidex/app/features/settings/pages/languages/languages-page.component.ts +++ b/src/Squidex/app/features/settings/pages/languages/languages-page.component.ts @@ -67,7 +67,7 @@ export class LanguagesPageComponent extends AppComponentBase implements OnInit { } public load() { - this.appName() + this.appNameOnce() .switchMap(app => this.appLanguagesService.getLanguages(app, this.version).retry(2)) .subscribe(dtos => { this.updateLanguages(ImmutableArray.of(dtos)); @@ -77,7 +77,7 @@ export class LanguagesPageComponent extends AppComponentBase implements OnInit { } public removeLanguage(language: AppLanguageDto) { - this.appName() + this.appNameOnce() .switchMap(app => this.appLanguagesService.deleteLanguage(app, language.iso2Code, this.version)) .subscribe(dto => { this.updateLanguages(this.appLanguages.remove(language)); @@ -89,7 +89,7 @@ export class LanguagesPageComponent extends AppComponentBase implements OnInit { public addLanguage() { const request = new AddAppLanguageDto(this.addLanguageForm.get('language')!.value.iso2Code); - this.appName() + this.appNameOnce() .switchMap(app => this.appLanguagesService.postLanguages(app, request, this.version)) .subscribe(dto => { this.updateLanguages(this.appLanguages.push(dto)); @@ -101,7 +101,7 @@ export class LanguagesPageComponent extends AppComponentBase implements OnInit { public setMasterLanguage(language: AppLanguageDto) { const request = new UpdateAppLanguageDto(true); - this.appName() + this.appNameOnce() .switchMap(app => this.appLanguagesService.updateLanguage(app, language.iso2Code, request, this.version)) .subscribe(() => { this.updateLanguages(this.appLanguages.map(l => { diff --git a/src/Squidex/app/shared/components/app.component-base.ts b/src/Squidex/app/shared/components/app.component-base.ts index a40517237..f3b807c5e 100644 --- a/src/Squidex/app/shared/components/app.component-base.ts +++ b/src/Squidex/app/shared/components/app.component-base.ts @@ -25,5 +25,9 @@ export abstract class AppComponentBase extends ComponentBase { public appName(): Observable { return this.appName$; } + + public appNameOnce(): Observable { + return this.appName$.take(1); + } } diff --git a/src/Squidex/app/shared/components/asset.component.ts b/src/Squidex/app/shared/components/asset.component.ts index 29f1972e0..54f06ac8f 100644 --- a/src/Squidex/app/shared/components/asset.component.ts +++ b/src/Squidex/app/shared/components/asset.component.ts @@ -93,7 +93,7 @@ export class AssetComponent extends AppComponentBase implements OnInit { const initFile = this.initFile; if (initFile) { - this.appName() + this.appNameOnce() .switchMap(app => this.assetsService.uploadFile(app, initFile)) .subscribe(result => { if (result instanceof AssetCreatedDto) { @@ -128,7 +128,7 @@ export class AssetComponent extends AppComponentBase implements OnInit { public updateFile(files: FileList) { if (files.length === 1) { - this.appName() + this.appNameOnce() .switchMap(app => this.assetsService.replaceFile(app, this.asset.id, files[0], this.version)) .subscribe(result => { if (result instanceof AssetReplacedDto) { @@ -166,7 +166,7 @@ export class AssetComponent extends AppComponentBase implements OnInit { const dto = new UpdateAssetDto(this.renameForm.controls['name'].value); - this.appName() + this.appNameOnce() .switchMap(app => this.assetsService.putAsset(app, this.asset.id, dto, this.version)) .subscribe(_ => { const me = `subject:${this.authService.user!.id}`; diff --git a/src/Squidex/app/shared/components/assets-editor.component.ts b/src/Squidex/app/shared/components/assets-editor.component.ts index ead742211..6dae05aba 100644 --- a/src/Squidex/app/shared/components/assets-editor.component.ts +++ b/src/Squidex/app/shared/components/assets-editor.component.ts @@ -71,7 +71,7 @@ export class AssetsEditorComponent extends AppComponentBase implements ControlVa this.oldAssets = ImmutableArray.empty(); if (value) { - this.appName() + this.appNameOnce() .switchMap(app => this.assetsService.getAssets(app, 10000, 0, undefined, undefined, value)) .subscribe(dtos => { this.oldAssets = ImmutableArray.of(dtos.items); diff --git a/src/Squidex/app/shared/components/history.component.ts b/src/Squidex/app/shared/components/history.component.ts index 19238abc2..59d03a9a3 100644 --- a/src/Squidex/app/shared/components/history.component.ts +++ b/src/Squidex/app/shared/components/history.component.ts @@ -47,7 +47,7 @@ export class HistoryComponent extends AppComponentBase { public events: Observable = Observable.timer(0, 10000) .merge(this.messageBus.of(HistoryChannelUpdated).delay(1000)) - .switchMap(() => this.appName()) + .switchMap(() => this.appNameOnce()) .switchMap(app => this.historyService.getHistory(app, this.channel).retry(2)); constructor(appsStore: AppsStoreService, notifications: NotificationService, diff --git a/src/Squidex/app/shared/services/usages.service.spec.ts b/src/Squidex/app/shared/services/usages.service.spec.ts index ad55ad324..d5a6336fb 100644 --- a/src/Squidex/app/shared/services/usages.service.spec.ts +++ b/src/Squidex/app/shared/services/usages.service.spec.ts @@ -13,6 +13,7 @@ import { ApiUrlConfig, AuthService, DateTime, + MonthlyCallsDto, UsageDto, UsagesService } from './../'; @@ -59,4 +60,26 @@ describe('UsagesService', () => { authService.verifyAll(); }); + + it('should make get request to get monthly calls', () => { + authService.setup(x => x.authGet('http://service/p/api/apps/my-app/usages/monthly')) + .returns(() => Observable.of( + new Response( + new ResponseOptions({ + body: { count: 130 } + }) + ) + )) + .verifiable(Times.once()); + + let usages: MonthlyCallsDto | null = null; + + usagesService.getMonthlyCalls('my-app').subscribe(result => { + usages = result; + }).unsubscribe(); + + expect(usages).toEqual(new MonthlyCallsDto(130)); + + authService.verifyAll(); + }); }); \ No newline at end of file diff --git a/src/Squidex/app/shared/services/usages.service.ts b/src/Squidex/app/shared/services/usages.service.ts index 360fe11dd..8c15a2a37 100644 --- a/src/Squidex/app/shared/services/usages.service.ts +++ b/src/Squidex/app/shared/services/usages.service.ts @@ -22,6 +22,13 @@ export class UsageDto { } } +export class MonthlyCallsDto { + constructor( + public readonly count: number + ) { + } +} + @Injectable() export class UsagesService { constructor( @@ -30,6 +37,17 @@ export class UsagesService { ) { } + public getMonthlyCalls(app: string): Observable { + const url = this.apiUrl.buildUrl(`api/apps/${app}/usages/monthly`); + + return this.authService.authGet(url) + .map(response => response.json()) + .map(response => { + return new MonthlyCallsDto(response.count); + }) + .catchError('Failed to load monthly calls. Please reload.'); + } + public getUsages(app: string, fromDate: DateTime, toDate: DateTime): Observable { const url = this.apiUrl.buildUrl(`api/apps/${app}/usages/${fromDate.toStringFormat('YYYY-MM-DD')}/${toDate.toStringFormat('YYYY-MM-DD')}`); diff --git a/src/Squidex/package.json b/src/Squidex/package.json index f8c62af5f..e9f19ef71 100644 --- a/src/Squidex/package.json +++ b/src/Squidex/package.json @@ -24,6 +24,7 @@ "@angular/platform-browser": "4.1.0", "@angular/platform-browser-dynamic": "4.1.0", "@angular/router": "4.1.0", + "angular2-chartjs": "^0.2.0", "angular-progress-http": "0.5.0", "babel-polyfill": "6.23.0", "bootstrap": "4.0.0-alpha.6", @@ -46,7 +47,6 @@ "@types/jasmine": "2.5.43", "@types/mousetrap": "1.5.33", "@types/node": "7.0.5", - "angular2-chartjs": "^0.2.0", "angular2-router-loader": "0.3.5", "angular2-template-loader": "0.6.2", "awesome-typescript-loader": "3.1.3",