Browse Source
Notifo fixes (#965)
* Fixes to notifo.
* Simplify contributors pages.
pull/966/head
Sebastian Stehle
3 years ago
committed by
GitHub
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with
42 additions and
52 deletions
-
backend/src/Squidex.Domain.Apps.Entities/History/NotifoService.cs
-
backend/src/Squidex.Domain.Users/UserWithClaims.cs
-
backend/src/Squidex.Infrastructure/Reflection/SimpleMapper.cs
-
frontend/src/app/features/content/pages/content/content-page.component.html
-
frontend/src/app/features/settings/pages/contributors/contributors-page.component.html
-
frontend/src/app/features/teams/pages/contributors/contributors-page.component.html
-
frontend/src/app/shared/components/notifo.component.scss
|
|
|
@ -66,20 +66,14 @@ public class NotifoService : IUserEvents |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public async Task OnUserCreatedAsync(IUser user) |
|
|
|
public Task OnUserCreatedAsync(IUser user) |
|
|
|
{ |
|
|
|
if (!string.IsNullOrWhiteSpace(user.Email)) |
|
|
|
{ |
|
|
|
await UpsertUserAsync(user); |
|
|
|
} |
|
|
|
return UpsertUserAsync(user); |
|
|
|
} |
|
|
|
|
|
|
|
public async Task OnUserUpdatedAsync(IUser user, IUser previous) |
|
|
|
public Task OnUserUpdatedAsync(IUser user, IUser previous) |
|
|
|
{ |
|
|
|
if (!string.Equals(user.Email, previous?.Email, StringComparison.OrdinalIgnoreCase)) |
|
|
|
{ |
|
|
|
await UpsertUserAsync(user); |
|
|
|
} |
|
|
|
return UpsertUserAsync(user); |
|
|
|
} |
|
|
|
|
|
|
|
private async Task UpsertUserAsync(IUser user) |
|
|
|
|
|
|
|
@ -7,27 +7,30 @@ |
|
|
|
|
|
|
|
using System.Security.Claims; |
|
|
|
using Microsoft.AspNetCore.Identity; |
|
|
|
using Squidex.Infrastructure.Reflection; |
|
|
|
using Squidex.Shared.Users; |
|
|
|
|
|
|
|
namespace Squidex.Domain.Users; |
|
|
|
|
|
|
|
internal sealed class UserWithClaims : IUser |
|
|
|
{ |
|
|
|
private readonly IdentityUser snapshot; |
|
|
|
|
|
|
|
public IdentityUser Identity { get; } |
|
|
|
|
|
|
|
public string Id |
|
|
|
{ |
|
|
|
get => Identity.Id; |
|
|
|
get => snapshot.Id; |
|
|
|
} |
|
|
|
|
|
|
|
public string Email |
|
|
|
{ |
|
|
|
get => Identity.Email!; |
|
|
|
get => snapshot.Email!; |
|
|
|
} |
|
|
|
|
|
|
|
public bool IsLocked |
|
|
|
{ |
|
|
|
get => Identity.LockoutEnd > DateTime.UtcNow; |
|
|
|
get => snapshot.LockoutEnd > DateTime.UtcNow; |
|
|
|
} |
|
|
|
|
|
|
|
public IReadOnlyList<Claim> Claims { get; } |
|
|
|
@ -38,6 +41,10 @@ internal sealed class UserWithClaims : IUser |
|
|
|
{ |
|
|
|
Identity = user; |
|
|
|
|
|
|
|
// Clone the user so that we capture the previous values, even when the user is updated.
|
|
|
|
snapshot = SimpleMapper.Map(user, new IdentityUser()); |
|
|
|
|
|
|
|
// Claims are immutable so we do not need a copy of them.
|
|
|
|
Claims = claims; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ -206,13 +206,6 @@ public static class SimpleMapper |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public static TTarget Map<TSource, TTarget>(TSource source) |
|
|
|
where TSource : class |
|
|
|
where TTarget : class, new() |
|
|
|
{ |
|
|
|
return Map(source, new TTarget(), CultureInfo.CurrentCulture); |
|
|
|
} |
|
|
|
|
|
|
|
public static TTarget Map<TSource, TTarget>(TSource source, TTarget target) |
|
|
|
where TSource : class |
|
|
|
where TTarget : class |
|
|
|
|
|
|
|
@ -53,7 +53,7 @@ |
|
|
|
<ng-container *ngIf="content; else noContentMenu"> |
|
|
|
<sqx-watching-users resource="{{schema.id}}/{{content.id}}"></sqx-watching-users> |
|
|
|
|
|
|
|
<sqx-notifo topic="apps/{{contentsState.appId}}/schemas/{{schema.name}}/contents/{{content.id}}"></sqx-notifo> |
|
|
|
<sqx-notifo topic="apps/{{contentsState.appId}}/schemas/{{schema.id}}/contents/{{content.id}}"></sqx-notifo> |
|
|
|
|
|
|
|
<sqx-language-selector class="languages-buttons" |
|
|
|
(languageChange)="changeLanguage($event)" |
|
|
|
|
|
|
|
@ -2,20 +2,18 @@ |
|
|
|
|
|
|
|
<sqx-layout layout="main" titleText="i18n:common.contributors" titleIcon="contributors" [innerWidth]="55"> |
|
|
|
<ng-container menu> |
|
|
|
<div class="d-flex justify-content-end"> |
|
|
|
<sqx-notifo topic="apps/{{contributorsState.appId}}/settings/contributors"></sqx-notifo> |
|
|
|
<sqx-notifo topic="apps/{{contributorsState.appId}}/settings/contributors"></sqx-notifo> |
|
|
|
|
|
|
|
<button type="button" class="btn btn-text-secondary me-2" (click)="reload()" title="i18n:contributors.refreshTooltip" shortcut="CTRL + B"> |
|
|
|
<i class="icon-reset"></i> {{ 'common.refresh' | sqxTranslate }} |
|
|
|
</button> |
|
|
|
<button type="button" class="btn btn-text-secondary me-2" (click)="reload()" title="i18n:contributors.refreshTooltip" shortcut="CTRL + B"> |
|
|
|
<i class="icon-reset"></i> {{ 'common.refresh' | sqxTranslate }} |
|
|
|
</button> |
|
|
|
|
|
|
|
<div class="form-inline"> |
|
|
|
<input class="form-control" placeholder="{{ 'contributors.search' | sqxTranslate }}" |
|
|
|
[ngModel]="contributorsState.query | async" |
|
|
|
(ngModelChange)="search($event)" |
|
|
|
shortcut="CTRL + I" |
|
|
|
shortcutAction="focus"> |
|
|
|
</div> |
|
|
|
<div class="form-inline"> |
|
|
|
<input class="form-control" placeholder="{{ 'contributors.search' | sqxTranslate }}" |
|
|
|
[ngModel]="contributorsState.query | async" |
|
|
|
(ngModelChange)="search($event)" |
|
|
|
shortcut="CTRL + I" |
|
|
|
shortcutAction="focus"> |
|
|
|
</div> |
|
|
|
</ng-container> |
|
|
|
|
|
|
|
|
|
|
|
@ -2,20 +2,18 @@ |
|
|
|
|
|
|
|
<sqx-layout layout="main" titleText="i18n:common.contributors" titleIcon="contributors" [innerWidth]="55"> |
|
|
|
<ng-container menu> |
|
|
|
<div class="d-flex justify-content-end"> |
|
|
|
<sqx-notifo topic="apps/{{contributorsState.teamId}}/settings/contributors"></sqx-notifo> |
|
|
|
|
|
|
|
<button type="button" class="btn btn-text-secondary me-2" (click)="reload()" title="i18n:contributors.refreshTooltip" shortcut="CTRL + B"> |
|
|
|
<i class="icon-reset"></i> {{ 'common.refresh' | sqxTranslate }} |
|
|
|
</button> |
|
|
|
|
|
|
|
<div class="form-inline"> |
|
|
|
<input class="form-control" placeholder="{{ 'contributors.search' | sqxTranslate }}" |
|
|
|
[ngModel]="contributorsState.query | async" |
|
|
|
(ngModelChange)="search($event)" |
|
|
|
shortcut="CTRL + I" |
|
|
|
shortcutAction="focus"> |
|
|
|
</div> |
|
|
|
<sqx-notifo topic="apps/{{contributorsState.teamId}}/settings/contributors"></sqx-notifo> |
|
|
|
|
|
|
|
<button type="button" class="btn btn-text-secondary me-2" (click)="reload()" title="i18n:contributors.refreshTooltip" shortcut="CTRL + B"> |
|
|
|
<i class="icon-reset"></i> {{ 'common.refresh' | sqxTranslate }} |
|
|
|
</button> |
|
|
|
|
|
|
|
<div class="form-inline"> |
|
|
|
<input class="form-control" placeholder="{{ 'contributors.search' | sqxTranslate }}" |
|
|
|
[ngModel]="contributorsState.query | async" |
|
|
|
(ngModelChange)="search($event)" |
|
|
|
shortcut="CTRL + I" |
|
|
|
shortcutAction="focus"> |
|
|
|
</div> |
|
|
|
</ng-container> |
|
|
|
|
|
|
|
|
|
|
|
@ -21,11 +21,11 @@ |
|
|
|
fill: $color-text-decent; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
.notifo-container { |
|
|
|
display: inline-block; |
|
|
|
max-width: 5rem; |
|
|
|
min-width: 3rem; |
|
|
|
} |
|
|
|
.notifo-container { |
|
|
|
display: inline-block; |
|
|
|
max-width: 5rem; |
|
|
|
min-width: 3rem; |
|
|
|
} |
|
|
|
} |