Browse Source

Improved error handling for event consumers

pull/1/head
Sebastian 9 years ago
parent
commit
ff394acc1e
  1. 4
      src/Squidex.Infrastructure.MongoDb/MongoEventConsumerInfo.cs
  2. 12
      src/Squidex.Infrastructure.MongoDb/MongoEventConsumerInfoRepository.cs
  3. 25
      src/Squidex.Infrastructure/CQRS/Events/EventReceiver.cs
  4. 2
      src/Squidex.Infrastructure/CQRS/Events/IEventConsumerInfo.cs
  5. 2
      src/Squidex.Infrastructure/CQRS/Events/IEventConsumerInfoRepository.cs
  6. 2
      src/Squidex/Controllers/Api/EventConsumers/Models/EventConsumerDto.cs
  7. 35
      src/Squidex/app/features/administration/pages/event-consumers/event-consumers-page.component.html
  8. 22
      src/Squidex/app/features/administration/pages/event-consumers/event-consumers-page.component.scss
  9. 22
      src/Squidex/app/features/administration/pages/event-consumers/event-consumers-page.component.ts
  10. 4
      src/Squidex/app/features/apps/pages/apps-page.component.html
  11. 4
      src/Squidex/app/features/schemas/pages/schema/schema-page.component.html
  12. 4
      src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.html
  13. 6
      src/Squidex/app/features/settings/pages/clients/client.component.html
  14. 2
      src/Squidex/app/features/settings/pages/clients/client.component.scss
  15. 2
      src/Squidex/app/features/settings/pages/contributors/contributors-page.component.html
  16. 2
      src/Squidex/app/features/settings/pages/languages/languages-page.component.html
  17. 6
      src/Squidex/app/shared/services/event-consumers.service.ts
  18. 4
      src/Squidex/app/shell/pages/internal/apps-menu.component.html
  19. BIN
      src/Squidex/app/theme/icomoon/fonts/icomoon.eot
  20. 2
      src/Squidex/app/theme/icomoon/fonts/icomoon.svg
  21. BIN
      src/Squidex/app/theme/icomoon/fonts/icomoon.ttf
  22. BIN
      src/Squidex/app/theme/icomoon/fonts/icomoon.woff
  23. 161
      src/Squidex/app/theme/icomoon/selection.json
  24. 16
      src/Squidex/app/theme/icomoon/style.css
  25. 6
      tests/Squidex.Infrastructure.Tests/CQRS/Events/EventReceiverTests.cs

4
src/Squidex.Infrastructure.MongoDb/MongoEventConsumerInfo.cs

@ -18,6 +18,10 @@ namespace Squidex.Infrastructure.MongoDb
[BsonRepresentation(BsonType.String)]
public string Name { get; set; }
[BsonElement]
[BsonIgnoreIfNull]
public string Error { get; set; }
[BsonElement]
[BsonIgnoreIfDefault]
public bool IsStopped { get; set; }

12
src/Squidex.Infrastructure.MongoDb/MongoEventConsumerInfoRepository.cs

@ -64,19 +64,19 @@ namespace Squidex.Infrastructure.MongoDb
return Collection.UpdateOneAsync(x => x.Name == consumerName, Update.Unset(x => x.IsStopped));
}
public Task StopAsync(string consumerName)
public Task StopAsync(string consumerName, string error = null)
{
return Collection.UpdateOneAsync(x => x.Name == consumerName, Update.Set(x => x.IsStopped, true));
return Collection.UpdateOneAsync(x => x.Name == consumerName, Update.Set(x => x.IsStopped, true).Set(x => x.Error, error));
}
public Task SetLastHandledEventNumberAsync(string consumerName, long eventNumber)
public Task ResetAsync(string consumerName)
{
return Collection.UpdateOneAsync(x => x.Name == consumerName, Update.Set(x => x.LastHandledEventNumber, eventNumber).Unset(x => x.IsResetting).Unset(x => x.IsStopped));
return Collection.UpdateOneAsync(x => x.Name == consumerName, Update.Set(x => x.IsResetting, true));
}
public Task ResetAsync(string consumerName)
public Task SetLastHandledEventNumberAsync(string consumerName, long eventNumber)
{
return Collection.UpdateOneAsync(x => x.Name == consumerName, Update.Set(x => x.IsResetting, true));
return Collection.ReplaceOneAsync(x => x.Name == consumerName, new MongoEventConsumerInfo { Name = consumerName, LastHandledEventNumber = eventNumber });
}
}
}

25
src/Squidex.Infrastructure/CQRS/Events/EventReceiver.cs

@ -7,6 +7,7 @@
// ==========================================================================
using System;
using System.Reactive.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Squidex.Infrastructure.Timers;
@ -104,28 +105,19 @@ namespace Squidex.Infrastructure.CQRS.Events
return;
}
var tcs = new TaskCompletionSource<bool>();
await eventStore.GetEventsAsync(lastHandledEventNumber)
.SelectMany(async storedEvent =>
{
await HandleEventAsync(eventConsumer, storedEvent, consumerName);
eventStore.GetEventsAsync(lastHandledEventNumber).Subscribe(storedEvent =>
{
HandleEventAsync(eventConsumer, storedEvent, consumerName).Wait();
}, ex =>
{
tcs.SetException(ex);
}, () =>
{
tcs.SetResult(true);
}, ct);
await tcs.Task;
return storedEvent;
}).DefaultIfEmpty();
}
catch (Exception ex)
{
logger.LogError(InfrastructureErrors.EventHandlingFailed, ex, "Failed to handle events");
await eventConsumerInfoRepository.StopAsync(consumerName);
throw;
await eventConsumerInfoRepository.StopAsync(consumerName, ex.ToString());
}
});
@ -137,7 +129,6 @@ namespace Squidex.Infrastructure.CQRS.Events
var @event = ParseEvent(storedEvent);
await DispatchConsumer(@event, eventConsumer);
await eventConsumerInfoRepository.SetLastHandledEventNumberAsync(consumerName, storedEvent.EventNumber);
}

2
src/Squidex.Infrastructure/CQRS/Events/IEventConsumerInfo.cs

@ -17,5 +17,7 @@ namespace Squidex.Infrastructure.CQRS.Events
bool IsResetting { get; }
string Name { get; }
string Error { get; }
}
}

2
src/Squidex.Infrastructure/CQRS/Events/IEventConsumerInfoRepository.cs

@ -21,7 +21,7 @@ namespace Squidex.Infrastructure.CQRS.Events
Task StartAsync(string consumerName);
Task StopAsync(string consumerName);
Task StopAsync(string consumerName, string error = null);
Task ResetAsync(string consumerName);

2
src/Squidex/Controllers/Api/EventConsumers/Models/EventConsumerDto.cs

@ -17,5 +17,7 @@ namespace Squidex.Controllers.Api.EventConsumers.Models
public bool IsResetting { get; set; }
public string Name { get; set; }
public string Error { get; set; }
}
}

35
src/Squidex/app/features/administration/pages/event-consumers/event-consumers-page.component.html

@ -29,28 +29,32 @@
Event Number
</th>
<th class="col-right">
Options
Actions
</th>
</tr>
</thead>
<tbody>
<template ngFor let-eventConsumer [ngForOf]="eventConsumers">
<tr>
<tr [class.faulted]="eventConsumer.error && eventConsumer.error.length > 0">
<td>
<span class="truncate">{{eventConsumer.name}}</span>
<span class="truncate">
<i class="faulted-icon icon icon-warning" (click)="showError(eventConsumer)" [class.hidden]="!eventConsumer.error || eventConsumer.error.length === 0"></i>
{{eventConsumer.name}}
</span>
</td>
<td class="col-right">
<span>{{eventConsumer.lastHandledEventNumber}}</span>
</td>
<td class="col-right">
<button class="btn btn-simple" (click)="reset(eventConsumer.name)" *ngIf="!eventConsumer.isResetting">
<button class="btn btn-simple" (click)="reset(eventConsumer.name)" *ngIf="!eventConsumer.isResetting" title="Reset Event Consumer">
<i class="icon icon-reset"></i>
</button>
<button class="btn btn-simple" (click)="start(eventConsumer.name)" *ngIf="eventConsumer.isStopped">
<button class="btn btn-simple" (click)="start(eventConsumer.name)" *ngIf="eventConsumer.isStopped" title="Start Event Consumer">
<i class="icon icon-play"></i>
</button>
<button class="btn btn-simple" (click)="stop(eventConsumer.name)" *ngIf="!eventConsumer.isStopped">
<button class="btn btn-simple" (click)="stop(eventConsumer.name)" *ngIf="!eventConsumer.isStopped" title="Stop Event Consumer">
<i class="icon icon-pause"></i>
</button>
</td>
@ -62,3 +66,22 @@
</div>
</div>
</sqx-panel>
<div class="modal" *sqxModalView="eventConsumerErrorDialog" [@fade]>
<div class="modal-backdrop"></div>
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Error</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close" (click)="eventConsumerErrorDialog.hide()">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<textarea readonly class="form-control error-message">{{eventConsumerError}}</textarea>
</div>
</div>
</div>
</div>

22
src/Squidex/app/features/administration/pages/event-consumers/event-consumers-page.component.scss

@ -8,3 +8,25 @@ button {
.col-right {
text-align: right;
}
.faulted-icon {
& {
@include transition(color .3s ease);
cursor: pointer;
color: $color-theme-error;
}
&:hover {
color: darken($color-theme-error, 10%);
}
}
.faulted {
color: $color-theme-error;
}
.error-message {
height: 18rem;
font-size: .8rem;
font-weight: normal;
}

22
src/Squidex/app/features/administration/pages/event-consumers/event-consumers-page.component.ts

@ -11,17 +11,24 @@ import { Observable, Subscription } from 'rxjs';
import {
EventConsumerDto,
EventConsumersService,
ImmutableArray
fadeAnimation,
ImmutableArray,
ModalView
} from 'shared';
@Component({
selector: 'sqx-event-consumers-page',
styleUrls: ['./event-consumers-page.component.scss'],
templateUrl: './event-consumers-page.component.html'
templateUrl: './event-consumers-page.component.html',
animations: [
fadeAnimation
]
})
export class EventConsumersPage implements OnInit, OnDestroy {
private subscription: Subscription;
public eventConsumerErrorDialog = new ModalView();
public eventConsumerError = '';
public eventConsumers = ImmutableArray.empty<EventConsumerDto>();
constructor(
@ -47,7 +54,7 @@ export class EventConsumersPage implements OnInit, OnDestroy {
.subscribe(() => {
this.eventConsumers = this.eventConsumers.map(e => {
if (e.name === name) {
return new EventConsumerDto(name, e.lastHandledEventNumber, false, e.isResetting);
return new EventConsumerDto(name, e.lastHandledEventNumber, false, e.isResetting, e.error);
} else {
return e;
}
@ -60,7 +67,7 @@ export class EventConsumersPage implements OnInit, OnDestroy {
.subscribe(() => {
this.eventConsumers = this.eventConsumers.map(e => {
if (e.name === name) {
return new EventConsumerDto(name, e.lastHandledEventNumber, true, e.isResetting);
return new EventConsumerDto(name, e.lastHandledEventNumber, true, e.isResetting, e.error);
} else {
return e;
}
@ -73,12 +80,17 @@ export class EventConsumersPage implements OnInit, OnDestroy {
.subscribe(() => {
this.eventConsumers = this.eventConsumers.map(e => {
if (e.name === name) {
return new EventConsumerDto(name, e.lastHandledEventNumber, e.isStopped, true);
return new EventConsumerDto(name, e.lastHandledEventNumber, e.isStopped, true, e.error);
} else {
return e;
}
});
});
}
public showError(eventConsumer: EventConsumerDto) {
this.eventConsumerError = eventConsumer.error;
this.eventConsumerErrorDialog.show();
}
}

4
src/Squidex/app/features/apps/pages/apps-page.component.html

@ -23,11 +23,11 @@
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Create App</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close" (click)="addAppDialog.hide()">
<span aria-hidden="true">&times;</span>
</button>
<h4 class="modal-title">Create App</h4>
</div>
<div class="modal-body">

4
src/Squidex/app/features/schemas/pages/schema/schema-page.component.html

@ -68,11 +68,11 @@
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Edit Schema</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close" (click)="editSchemaDialog.hide()">
<span aria-hidden="true">&times;</span>
</button>
<h4 class="modal-title">Edit Schema</h4>
</div>
<div class="modal-body">

4
src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.html

@ -54,11 +54,11 @@
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Create Schema</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close" (click)="addSchemaDialog.hide()">
<span aria-hidden="true">&times;</span>
</button>
<h4 class="modal-title">Create Schema</h4>
</div>
<div class="modal-body">

6
src/Squidex/app/features/settings/pages/clients/client.component.html

@ -74,15 +74,15 @@
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Access Token</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close" (click)="tokenDialog.hide()">
<span aria-hidden="true">&times;</span>
</button>
<h4 class="modal-title">Access Token</h4>
</div>
<div class="modal-body">
<textarea class="form-control access-token">{{token.tokenType}} {{token.accessToken}}</textarea>
<textarea readonly class="form-control access-token">{{token.tokenType}} {{token.accessToken}}</textarea>
</div>
</div>
</div>

2
src/Squidex/app/features/settings/pages/clients/client.component.scss

@ -68,4 +68,6 @@ $color-editor: #eceeef;
.access-token {
height: 18rem;
font-size: .8rem;
font-weight: normal;
}

2
src/Squidex/app/features/settings/pages/contributors/contributors-page.component.html

@ -34,7 +34,7 @@
Email
</th>
<th>
Options
Actions
</th>
</tr>
</thead>

2
src/Squidex/app/features/settings/pages/languages/languages-page.component.html

@ -30,7 +30,7 @@
Name
</th>
<th>
Options
Actions
</th>
</tr>
</thead>

6
src/Squidex/app/shared/services/event-consumers.service.ts

@ -18,7 +18,8 @@ export class EventConsumerDto {
public readonly name: string,
public readonly lastHandledEventNumber: number,
public readonly isStopped: boolean,
public readonly isResetting: boolean
public readonly isResetting: boolean,
public readonly error: string
) {
}
}
@ -44,7 +45,8 @@ export class EventConsumersService {
item.name,
item.lastHandledEventNumber,
item.isStopped,
item.isResetting);
item.isResetting,
item.error);
});
})
.catchError('Failed to load event consumers. Please reload.');

4
src/Squidex/app/shell/pages/internal/apps-menu.component.html

@ -28,11 +28,11 @@
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Create App</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close" (click)="modalDialog.hide()">
<span aria-hidden="true">&times;</span>
</button>
<h4 class="modal-title">Create App</h4>
</div>
<div class="modal-body">

BIN
src/Squidex/app/theme/icomoon/fonts/icomoon.eot

Binary file not shown.

2
src/Squidex/app/theme/icomoon/fonts/icomoon.svg

@ -56,4 +56,6 @@
<glyph unicode="&#xe92e;" glyph-name="reset" d="M889.68 793.68c-93.608 102.216-228.154 166.32-377.68 166.32-282.77 0-512-229.23-512-512h96c0 229.75 186.25 416 416 416 123.020 0 233.542-53.418 309.696-138.306l-149.696-149.694h352v352l-134.32-134.32zM928 448c0-229.75-186.25-416-416-416-123.020 0-233.542 53.418-309.694 138.306l149.694 149.694h-352v-352l134.32 134.32c93.608-102.216 228.154-166.32 377.68-166.32 282.77 0 512 229.23 512 512h-96z" />
<glyph unicode="&#xe92f;" glyph-name="pause" d="M128 832h320v-768h-320zM576 832h320v-768h-320z" />
<glyph unicode="&#xe930;" glyph-name="play" d="M192 832l640-384-640-384z" />
<glyph unicode="&#xea07;" glyph-name="warning" d="M512 867.226l429.102-855.226h-858.206l429.104 855.226zM512 960c-22.070 0-44.14-14.882-60.884-44.648l-437.074-871.112c-33.486-59.532-5-108.24 63.304-108.24h869.308c68.3 0 96.792 48.708 63.3 108.24h0.002l-437.074 871.112c-16.742 29.766-38.812 44.648-60.882 44.648v0zM576 128c0-35.346-28.654-64-64-64s-64 28.654-64 64c0 35.346 28.654 64 64 64s64-28.654 64-64zM512 256c-35.346 0-64 28.654-64 64v192c0 35.346 28.654 64 64 64s64-28.654 64-64v-192c0-35.346-28.654-64-64-64z" />
<glyph unicode="&#xea08;" glyph-name="notification" d="M512 864c-111.118 0-215.584-43.272-294.156-121.844s-121.844-183.038-121.844-294.156c0-111.118 43.272-215.584 121.844-294.156s183.038-121.844 294.156-121.844c111.118 0 215.584 43.272 294.156 121.844s121.844 183.038 121.844 294.156c0 111.118-43.272 215.584-121.844 294.156s-183.038 121.844-294.156 121.844zM512 960v0c282.77 0 512-229.23 512-512s-229.23-512-512-512c-282.77 0-512 229.23-512 512s229.23 512 512 512zM448 256h128v-128h-128zM448 768h128v-384h-128z" />
</font></defs></svg>

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 41 KiB

BIN
src/Squidex/app/theme/icomoon/fonts/icomoon.ttf

Binary file not shown.

BIN
src/Squidex/app/theme/icomoon/fonts/icomoon.woff

Binary file not shown.

161
src/Squidex/app/theme/icomoon/selection.json

@ -1,6 +1,67 @@
{
"IcoMoonType": "selection",
"icons": [
{
"icon": {
"paths": [
"M512 92.774l429.102 855.226h-858.206l429.104-855.226zM512 0c-22.070 0-44.14 14.882-60.884 44.648l-437.074 871.112c-33.486 59.532-5 108.24 63.304 108.24h869.308c68.3 0 96.792-48.708 63.3-108.24h0.002l-437.074-871.112c-16.742-29.766-38.812-44.648-60.882-44.648v0z",
"M576 832c0 35.346-28.654 64-64 64s-64-28.654-64-64c0-35.346 28.654-64 64-64s64 28.654 64 64z",
"M512 704c-35.346 0-64-28.654-64-64v-192c0-35.346 28.654-64 64-64s64 28.654 64 64v192c0 35.346-28.654 64-64 64z"
],
"attrs": [],
"isMulticolor": false,
"isMulticolor2": false,
"tags": [
"warning",
"sign"
],
"defaultCode": 59911,
"grid": 16
},
"attrs": [],
"properties": {
"ligatures": "warning, sign",
"name": "warning",
"id": 263,
"order": 52,
"prevSize": 32,
"code": 59911
},
"setIdx": 0,
"setId": 3,
"iconIdx": 263
},
{
"icon": {
"paths": [
"M512 96c-111.118 0-215.584 43.272-294.156 121.844s-121.844 183.038-121.844 294.156c0 111.118 43.272 215.584 121.844 294.156s183.038 121.844 294.156 121.844c111.118 0 215.584-43.272 294.156-121.844s121.844-183.038 121.844-294.156c0-111.118-43.272-215.584-121.844-294.156s-183.038-121.844-294.156-121.844zM512 0v0c282.77 0 512 229.23 512 512s-229.23 512-512 512c-282.77 0-512-229.23-512-512s229.23-512 512-512zM448 704h128v128h-128zM448 192h128v384h-128z"
],
"attrs": [],
"isMulticolor": false,
"isMulticolor2": false,
"tags": [
"notification",
"warning",
"notice",
"note",
"exclamation"
],
"defaultCode": 59912,
"grid": 16
},
"attrs": [],
"properties": {
"ligatures": "notification, warning2",
"name": "notification",
"id": 264,
"order": 50,
"prevSize": 32,
"code": 59912
},
"setIdx": 0,
"setId": 3,
"iconIdx": 264
},
{
"icon": {
"paths": [
@ -30,13 +91,13 @@
{}
],
"properties": {
"order": 1,
"order": 49,
"id": 2,
"prevSize": 32,
"code": 59694,
"name": "reset"
},
"setIdx": 0,
"setIdx": 1,
"setId": 2,
"iconIdx": 0
},
@ -66,7 +127,7 @@
"code": 59695,
"name": "pause"
},
"setIdx": 0,
"setIdx": 1,
"setId": 2,
"iconIdx": 1
},
@ -96,7 +157,7 @@
"code": 59696,
"name": "play"
},
"setIdx": 0,
"setIdx": 1,
"setId": 2,
"iconIdx": 2
},
@ -131,7 +192,7 @@
"code": 59693,
"name": "settings2"
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 0
},
@ -168,7 +229,7 @@
"prevSize": 32,
"code": 59650
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 1
},
@ -197,7 +258,7 @@
"prevSize": 32,
"code": 59652
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 2
},
@ -226,7 +287,7 @@
"prevSize": 32,
"code": 59653
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 3
},
@ -255,7 +316,7 @@
"prevSize": 32,
"code": 59654
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 4
},
@ -284,7 +345,7 @@
"prevSize": 32,
"code": 59655
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 5
},
@ -313,7 +374,7 @@
"prevSize": 32,
"code": 59656
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 6
},
@ -342,7 +403,7 @@
"prevSize": 32,
"code": 59657
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 7
},
@ -371,7 +432,7 @@
"prevSize": 32,
"code": 59658
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 8
},
@ -400,7 +461,7 @@
"prevSize": 32,
"code": 59659
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 9
},
@ -429,7 +490,7 @@
"prevSize": 32,
"code": 59660
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 10
},
@ -458,7 +519,7 @@
"prevSize": 32,
"code": 59661
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 11
},
@ -487,7 +548,7 @@
"prevSize": 32,
"code": 59662
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 12
},
@ -516,7 +577,7 @@
"prevSize": 32,
"code": 59663
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 13
},
@ -545,7 +606,7 @@
"prevSize": 32,
"code": 59664
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 14
},
@ -574,7 +635,7 @@
"prevSize": 32,
"code": 59665
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 15
},
@ -603,7 +664,7 @@
"prevSize": 32,
"code": 59666
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 16
},
@ -632,7 +693,7 @@
"prevSize": 32,
"code": 59667
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 17
},
@ -661,7 +722,7 @@
"prevSize": 32,
"code": 59668
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 18
},
@ -690,7 +751,7 @@
"prevSize": 32,
"code": 59669
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 19
},
@ -719,7 +780,7 @@
"prevSize": 32,
"code": 59670
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 20
},
@ -748,7 +809,7 @@
"prevSize": 32,
"code": 59671
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 21
},
@ -777,7 +838,7 @@
"prevSize": 32,
"code": 59672
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 22
},
@ -806,7 +867,7 @@
"prevSize": 32,
"code": 59673
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 23
},
@ -835,7 +896,7 @@
"prevSize": 32,
"code": 59674
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 24
},
@ -864,7 +925,7 @@
"prevSize": 32,
"code": 59675
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 25
},
@ -893,7 +954,7 @@
"prevSize": 32,
"code": 59676
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 26
},
@ -922,7 +983,7 @@
"prevSize": 32,
"code": 59677
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 27
},
@ -951,7 +1012,7 @@
"prevSize": 32,
"code": 59678
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 28
},
@ -980,7 +1041,7 @@
"prevSize": 32,
"code": 59679
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 29
},
@ -1009,7 +1070,7 @@
"prevSize": 32,
"code": 59680
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 30
},
@ -1038,7 +1099,7 @@
"prevSize": 32,
"code": 59681
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 31
},
@ -1067,7 +1128,7 @@
"prevSize": 32,
"code": 59682
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 32
},
@ -1096,7 +1157,7 @@
"prevSize": 32,
"code": 59683
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 33
},
@ -1125,7 +1186,7 @@
"prevSize": 32,
"code": 59684
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 34
},
@ -1154,7 +1215,7 @@
"prevSize": 32,
"code": 59685
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 35
},
@ -1183,7 +1244,7 @@
"prevSize": 32,
"code": 59686
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 36
},
@ -1212,7 +1273,7 @@
"prevSize": 32,
"code": 59687
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 37
},
@ -1241,7 +1302,7 @@
"prevSize": 32,
"code": 59688
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 38
},
@ -1271,7 +1332,7 @@
"code": 59689,
"name": "caret-right"
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 39
},
@ -1301,7 +1362,7 @@
"code": 59690,
"name": "caret-left"
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 40
},
@ -1331,7 +1392,7 @@
"code": 59691,
"name": "caret-up"
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 41
},
@ -1361,7 +1422,7 @@
"code": 59692,
"name": "caret-down"
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 42
},
@ -1391,7 +1452,7 @@
"code": 59651,
"name": "angle-up"
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 43
},
@ -1421,7 +1482,7 @@
"code": 59648,
"name": "angle-down"
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 44
},
@ -1451,7 +1512,7 @@
"code": 59649,
"name": "angle-left"
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 45
}

16
src/Squidex/app/theme/icomoon/style.css

@ -1,10 +1,10 @@
@font-face {
font-family: 'icomoon';
src: url('fonts/icomoon.eot?oo54rp');
src: url('fonts/icomoon.eot?oo54rp#iefix') format('embedded-opentype'),
url('fonts/icomoon.ttf?oo54rp') format('truetype'),
url('fonts/icomoon.woff?oo54rp') format('woff'),
url('fonts/icomoon.svg?oo54rp#icomoon') format('svg');
src: url('fonts/icomoon.eot?prmkzn');
src: url('fonts/icomoon.eot?prmkzn#iefix') format('embedded-opentype'),
url('fonts/icomoon.ttf?prmkzn') format('truetype'),
url('fonts/icomoon.woff?prmkzn') format('woff'),
url('fonts/icomoon.svg?prmkzn#icomoon') format('svg');
font-weight: normal;
font-style: normal;
}
@ -24,6 +24,12 @@
-moz-osx-font-smoothing: grayscale;
}
.icon-warning:before {
content: "\ea07";
}
.icon-notification:before {
content: "\ea08";
}
.icon-reset:before {
content: "\e92e";
}

6
tests/Squidex.Infrastructure.Tests/CQRS/Events/EventReceiverTests.cs

@ -33,6 +33,8 @@ namespace Squidex.Infrastructure.CQRS.Events
public bool IsResetting { get; set; }
public string Name { get; set; }
public string Error { get; set; }
}
private sealed class MyLogger : ILogger<EventReceiver>
@ -147,7 +149,7 @@ namespace Squidex.Infrastructure.CQRS.Events
eventConsumer.Verify(x => x.On(envelope2), Times.Once());
eventConsumer.Verify(x => x.On(envelope3), Times.Never());
eventConsumerInfoRepository.Verify(x => x.StopAsync(consumerName), Times.Once());
eventConsumerInfoRepository.Verify(x => x.StopAsync(consumerName, It.IsAny<string>()), Times.Once());
}
[Fact]
@ -169,7 +171,7 @@ namespace Squidex.Infrastructure.CQRS.Events
eventConsumer.Verify(x => x.On(envelope2), Times.Never());
eventConsumer.Verify(x => x.On(envelope3), Times.Never());
eventConsumerInfoRepository.Verify(x => x.StopAsync(consumerName), Times.Once());
eventConsumerInfoRepository.Verify(x => x.StopAsync(consumerName, It.IsAny<string>()), Times.Once());
}
[Fact]

Loading…
Cancel
Save