Browse Source

Status queries.

pull/377/head
Sebastian Stehle 7 years ago
parent
commit
643ba11802
  1. 3
      src/Squidex.Domain.Apps.Entities/Assets/AssetCommandMiddleware.cs
  2. 2
      src/Squidex.Domain.Apps.Entities/Contents/ContentCommandMiddleware.cs
  3. 15
      src/Squidex.Domain.Apps.Entities/Contents/ContentEnricher.cs
  4. 7
      src/Squidex.Domain.Apps.Entities/History/ParsedHistoryEvent.cs
  5. 11
      src/Squidex.Infrastructure/EventSourcing/DefaultEventDataFormatter.cs
  6. 3
      src/Squidex/Areas/Api/Controllers/History/HistoryController.cs
  7. 2
      src/Squidex/app-config/webpack.config.js
  8. 5
      src/Squidex/app/features/content/pages/content/content-page.component.html
  9. 4
      src/Squidex/app/features/content/pages/contents/contents-page.component.ts
  10. 5
      src/Squidex/app/features/content/shared/content-item.component.html
  11. 4
      src/Squidex/app/features/content/shared/content-status.component.html
  12. 12
      src/Squidex/app/features/content/shared/content-status.component.scss
  13. 3
      src/Squidex/app/features/content/shared/content-status.component.ts
  14. 2
      src/Squidex/app/shared/components/schema-category.component.ts
  15. 2
      src/Squidex/app/shared/services/contents.service.spec.ts
  16. 6
      src/Squidex/app/shared/services/contents.service.ts
  17. 4
      src/Squidex/app/theme/_bootstrap.scss
  18. 2
      tools/Migrate_01/OldEvents/ContentCreated.cs
  19. 2
      tools/Migrate_01/OldEvents/ContentStatusChanged.cs
  20. 39
      tools/Migrate_01/OldEvents/ContentStatusScheduled.cs

3
src/Squidex.Domain.Apps.Entities/Assets/AssetCommandMiddleware.cs

@ -73,6 +73,7 @@ namespace Squidex.Domain.Apps.Entities.Assets
var result = new AssetCreatedResult(existing, true);
context.Complete(result);
await next();
return;
}
}
@ -128,7 +129,7 @@ namespace Squidex.Domain.Apps.Entities.Assets
private async Task HandleCoreAsync(CommandContext context, Func<Task> next)
{
await HandleAsync(context, next);
await base.HandleAsync(context, next);
if (context.PlainResult is IAssetEntity asset && !(context.PlainResult is IAssetEntityEnriched))
{

2
src/Squidex.Domain.Apps.Entities/Contents/ContentCommandMiddleware.cs

@ -28,7 +28,7 @@ namespace Squidex.Domain.Apps.Entities.Contents
public override async Task HandleAsync(CommandContext context, Func<Task> next)
{
await HandleAsync(context, next);
await base.HandleAsync(context, next);
if (context.PlainResult is IContentEntity content)
{

15
src/Squidex.Domain.Apps.Entities/Contents/ContentEnricher.cs

@ -72,19 +72,24 @@ namespace Squidex.Domain.Apps.Entities.Contents
private async Task ResolveColorAsync(IContentEntity content, ContentEntity result, Dictionary<(Guid, Status), StatusInfo> cache)
{
if (!cache.TryGetValue((content.SchemaId.Id, content.Status), out var info))
result.StatusColor = await GetColorAsync(content.SchemaId, content.Status, cache);
}
private async Task<string> GetColorAsync(NamedId<Guid> schemaId, Status status, Dictionary<(Guid, Status), StatusInfo> cache)
{
if (!cache.TryGetValue((schemaId.Id, status), out var info))
{
info = await contentWorkflow.GetInfoAsync(content.Status);
info = await contentWorkflow.GetInfoAsync(status);
if (info == null)
{
info = new StatusInfo(content.Status, DefaultColor);
info = new StatusInfo(status, DefaultColor);
}
cache[(content.SchemaId.Id, content.Status)] = info;
cache[(schemaId.Id, status)] = info;
}
result.StatusColor = info.Color;
return info.Color;
}
}
}

7
src/Squidex.Domain.Apps.Entities/History/ParsedHistoryEvent.cs

@ -53,14 +53,17 @@ namespace Squidex.Domain.Apps.Entities.History
message = new Lazy<string>(() =>
{
var result = texts[item.Message];
if (texts.TryGetValue(item.Message, out var result))
{
foreach (var kvp in item.Parameters)
{
result = result.Replace("[" + kvp.Key + "]", kvp.Value);
}
return result;
}
return null;
});
}
}

11
src/Squidex.Infrastructure/EventSourcing/DefaultEventDataFormatter.cs

@ -6,6 +6,7 @@
// ==========================================================================
using System;
using System.Diagnostics;
using Squidex.Infrastructure.Json;
namespace Squidex.Infrastructure.EventSourcing
@ -33,6 +34,11 @@ namespace Squidex.Infrastructure.EventSourcing
if (payloadObj is IMigrated<IEvent> migratedEvent)
{
payloadObj = migratedEvent.Migrate();
if (ReferenceEquals(migratedEvent, payloadObj))
{
Debug.WriteLine("Migration should return new event.");
}
}
var envelope = new Envelope<IEvent>(payloadObj, eventData.Headers);
@ -47,6 +53,11 @@ namespace Squidex.Infrastructure.EventSourcing
if (migrate && eventPayload is IMigrated<IEvent> migratedEvent)
{
eventPayload = migratedEvent.Migrate();
if (ReferenceEquals(migratedEvent, eventPayload))
{
Debug.WriteLine("Migration should return new event.");
}
}
var payloadType = typeNameRegistry.GetName(eventPayload.GetType());

3
src/Squidex/Areas/Api/Controllers/History/HistoryController.cs

@ -5,6 +5,7 @@
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Squidex.Areas.Api.Controllers.History.Models;
@ -48,7 +49,7 @@ namespace Squidex.Areas.Api.Controllers.History
{
var events = await historyService.QueryByChannelAsync(AppId, channel, 100);
var response = events.ToArray(HistoryEventDto.FromHistoryEvent);
var response = events.Select(HistoryEventDto.FromHistoryEvent).Where(x => x.Message != null).ToArray();
return Ok(response);
}

2
src/Squidex/app-config/webpack.config.js

@ -251,7 +251,9 @@ module.exports = function (env) {
waitForLinting: isProduction
})
);
}
if (!isCoverage) {
config.plugins.push(
new plugins.NgToolsWebpack.AngularCompilerPlugin({
directTemplateLoading: true,

5
src/Squidex/app/features/content/pages/content/content-page.component.html

@ -36,6 +36,7 @@
[class.active]="dropdown.isOpen | async" #optionsButton>
<sqx-content-status
[status]="content.status"
[statusColor]="content.statusColor"
[scheduledTo]="content.scheduleJob?.status"
[scheduledAt]="content.scheduleJob?.dueTime"
[isPending]="content.isPending"
@ -56,8 +57,8 @@
</a>
<ng-container *ngIf="!schema.isSingleton">
<a class="dropdown-item" *ngFor="let status of content.statusUpdates" (click)="changeStatus(status)">
Status to {{status}}
<a class="dropdown-item" *ngFor="let info of content.statusUpdates" (click)="changeStatus(info.status)">
Change to <i class="icon-circle icon-sm" [style.color]="info.color"></i> {{info.status}}
</a>
<div class="dropdown-divider"></div>

4
src/Squidex/app/features/content/pages/contents/contents-page.component.ts

@ -207,8 +207,8 @@ export class ContentsPageComponent extends ResourceOwner implements OnInit {
const allActions = {};
for (let content of this.contentsState.snapshot.contents.values) {
for (let status of content.statusUpdates) {
allActions[status] = true;
for (let info of content.statusUpdates) {
allActions[info.status] = info.color;
}
}

5
src/Squidex/app/features/content/shared/content-item.component.html

@ -24,6 +24,7 @@
<td class="cell-time" *ngIf="!isCompact" [sqxStopClick]="isDirty">
<sqx-content-status
[status]="content.status"
[statusColor]="content.statusColor"
[scheduledTo]="content.scheduleJob?.status"
[scheduledAt]="content.scheduleJob?.dueTime"
[isPending]="content.isPending">
@ -55,8 +56,8 @@
<i class="icon-dots"></i>
</button>
<div class="dropdown-menu" *sqxModalView="dropdown;closeAlways:true" [sqxModalTarget]="optionsButton" @fade>
<a class="dropdown-item" *ngFor="let status of content.statusUpdates" (click)="emitChangeStatus(status)">
Status to {{status}}
<a class="dropdown-item" *ngFor="let info of content.statusUpdates" (click)="emitChangeStatus(info.status)">
Change to <i class="icon-circle icon-sm" [style.color]="info.color"></i> {{info.status}}
</a>
<a class="dropdown-item" (click)="emitClone(); dropdown.hide()" *ngIf="canClone">
Clone

4
src/Squidex/app/features/content/shared/content-status.component.html

@ -1,11 +1,11 @@
<ng-container *ngIf="scheduledTo; else noSchedule">
<span class="content-status content-status-{{scheduledTo | lowercase}} mr-1" title="{{tooltipText}}" titlePosition="top">
<span class="content-status pending mr-1"title="{{tooltipText}}" titlePosition="top">
<i class="icon-clock"></i>
</span>
</ng-container>
<ng-template #noSchedule>
<span class="content-status content-status-{{displayStatus | lowercase}} mr-1" title="{{tooltipText}}" titlePosition="top">
<span class="content-status default mr-1" [style.color]="statusColor" title="{{tooltipText}}" titlePosition="top">
<i class="icon-circle"></i>
</span>
</ng-template>

12
src/Squidex/app/features/content/shared/content-status.component.scss

@ -6,19 +6,11 @@
vertical-align: middle;
}
&-published {
color: $color-theme-green;
}
&-draft {
&.default {
color: $color-text-decent;
}
&-archived {
color: $color-theme-error;
}
&-pending {
&.pending {
color: $color-dark-black;
}

3
src/Squidex/app/features/content/shared/content-status.component.ts

@ -19,6 +19,9 @@ export class ContentStatusComponent {
@Input()
public status: string;
@Input()
public statusColor: string;
@Input()
public scheduledTo?: string;

2
src/Squidex/app/shared/components/schema-category.component.ts

@ -74,7 +74,7 @@ export class SchemaCategoryComponent extends StatefulComponent<State> implements
let filtered = this.schemaCategory.schemas;
if (this.forContent) {
filtered = filtered.filter(x => x.canReadContents);
filtered = filtered.filter(x => x.canReadContents && x.isPublished);
}
let isOpen = false;

2
src/Squidex/app/shared/services/contents.service.spec.ts

@ -353,6 +353,7 @@ describe('ContentsService', () => {
return {
id: `id${id}`,
status: `Status${id}`,
statusColor: 'black',
created: `${id % 1000 + 2000}-12-12T10:10:00`,
createdBy: `creator-${id}`,
lastModified: `${id % 1000 + 2000}-11-11T10:10:00`,
@ -381,6 +382,7 @@ export function createContent(id: number, suffix = '') {
return new ContentDto(links,
`id${id}`,
`Status${id}${suffix}`,
'black',
DateTime.parseISO_UTC(`${id % 1000 + 2000}-12-12T10:10:00`), `creator-${id}`,
DateTime.parseISO_UTC(`${id % 1000 + 2000}-11-11T10:10:00`), `modifier-${id}`,
new ScheduleDto('Draft', `Scheduler${id}`, DateTime.parseISO_UTC(`${id % 1000 + 2000}-11-11T10:10:00`)),

6
src/Squidex/app/shared/services/contents.service.ts

@ -58,7 +58,7 @@ export class ContentsDto extends ResultSet<ContentDto> {
export class ContentDto {
public readonly _links: ResourceLinks;
public readonly statusUpdates: string[];
public readonly statusUpdates: StatusInfo[];
public readonly canDelete: boolean;
public readonly canDraftDiscard: boolean;
@ -69,6 +69,7 @@ export class ContentDto {
constructor(links: ResourceLinks,
public readonly id: string,
public readonly status: string,
public readonly statusColor: string,
public readonly created: DateTime,
public readonly createdBy: string,
public readonly lastModified: DateTime,
@ -87,7 +88,7 @@ export class ContentDto {
this.canDraftPublish = hasAnyLink(links, 'draft/publish');
this.canUpdate = hasAnyLink(links, 'update');
this.statusUpdates = Object.keys(links).filter(x => x.startsWith('status/')).map(x => x.substr(7));
this.statusUpdates = Object.keys(links).filter(x => x.startsWith('status/')).map(x => ({ status: x.substr(7), color: links[x].metadata! }));
}
}
@ -284,6 +285,7 @@ function parseContent(response: any) {
return new ContentDto(response._links,
response.id,
response.status,
response.statusColor,
DateTime.parseISO_UTC(response.created), response.createdBy,
DateTime.parseISO_UTC(response.lastModified), response.lastModifiedBy,
response.scheduleJob

4
src/Squidex/app/theme/_bootstrap.scss

@ -304,6 +304,10 @@ a {
}
}
.icon-sm {
font-size: 70%;
}
//
// Button improvements
//

2
tools/Migrate_01/OldEvents/ContentCreated.cs

@ -32,7 +32,7 @@ namespace Migrate_01.OldEvents
migrated.Status = Status.Draft;
}
return this;
return migrated;
}
}
}

2
tools/Migrate_01/OldEvents/ContentStatusChanged.cs

@ -41,7 +41,7 @@ namespace Migrate_01.OldEvents
migrated.Change = StatusChange.Change;
}
return this;
return migrated;
}
}
}

39
tools/Migrate_01/OldEvents/ContentStatusScheduled.cs

@ -1,39 +0,0 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschränkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System;
using NodaTime;
using Squidex.Domain.Apps.Core.Contents;
using Squidex.Domain.Apps.Events.Contents;
using Squidex.Infrastructure;
using Squidex.Infrastructure.EventSourcing;
using Squidex.Infrastructure.Reflection;
using ContentStatusScheduledV2 = Squidex.Domain.Apps.Events.Contents.ContentStatusScheduled;
namespace Migrate_01.OldEvents
{
[EventType(nameof(ContentStatusScheduled))]
[Obsolete]
public sealed class ContentStatusScheduled : ContentEvent, IMigrated<IEvent>
{
public Status Status { get; set; }
public Instant DueTime { get; set; }
public IEvent Migrate()
{
var migrated = SimpleMapper.Map(this, new ContentStatusScheduledV2());
if (migrated.Status == default)
{
migrated.Status = Status.Draft;
}
return this;
}
}
}
Loading…
Cancel
Save