Browse Source

Language support

pull/1/head
Sebastian 9 years ago
parent
commit
96b5174e84
  1. 2
      src/Squidex.Read.MongoDb/History/MongoHistoryEventRepository.cs
  2. 24
      src/Squidex.Read/Apps/AppHistoryEventsCreator.cs
  3. 46
      src/Squidex.Read/Contents/ContentHistoryEventsCreator.cs
  4. 20
      src/Squidex.Read/History/HistoryEventsCreatorBase.cs
  5. 85
      src/Squidex.Read/Schemas/SchemaHistoryEventsCreator.cs
  6. 5
      src/Squidex/Config/Domain/ReadModule.cs
  7. 9
      src/Squidex/Config/Domain/Serializers.cs
  8. 10
      src/Squidex/Config/Domain/WriteModule.cs
  9. 8
      src/Squidex/app/features/content/module.ts
  10. 2
      src/Squidex/app/features/content/pages/contents/content-item.component.ts
  11. 5
      src/Squidex/app/features/content/pages/contents/contents-page.component.html
  12. 2
      src/Squidex/app/shared/services/auth.service.ts

2
src/Squidex.Read.MongoDb/History/MongoHistoryEventRepository.cs

@ -67,7 +67,7 @@ namespace Squidex.Read.MongoDb.History
public async Task<List<IHistoryEventEntity>> QueryEventsByChannel(Guid appId, string channelPrefix, int count) public async Task<List<IHistoryEventEntity>> QueryEventsByChannel(Guid appId, string channelPrefix, int count)
{ {
var entities = var entities =
await Collection.Find(x => x.AppId == appId && x.Channel.StartsWith(channelPrefix)) await Collection.Find(x => x.AppId == appId && x.Channel == channelPrefix)
.SortByDescending(x => x.Created).ThenByDescending(x => x.SessionEventIndex).Limit(count).ToListAsync(); .SortByDescending(x => x.Created).ThenByDescending(x => x.SessionEventIndex).Limit(count).ToListAsync();
return entities.Select(x => (IHistoryEventEntity)new ParsedHistoryEvent(x, texts)).ToList(); return entities.Select(x => (IHistoryEventEntity)new ParsedHistoryEvent(x, texts)).ToList();

24
src/Squidex.Read/Apps/AppHistoryEventsCreator.cs

@ -46,36 +46,35 @@ namespace Squidex.Read.Apps
"changed master language to {[Language]}"); "changed master language to {[Language]}");
} }
protected Task<HistoryEventToStore> On(AppContributorAssigned @event, EnvelopeHeaders headers) protected Task<HistoryEventToStore> On(AppContributorRemoved @event, EnvelopeHeaders headers)
{ {
const string channel = "settings.contributors"; const string channel = "settings.contributors";
return Task.FromResult( return Task.FromResult(
ForEvent(@event, channel) ForEvent(@event, channel)
.AddParameter("Contributor", @event.ContributorId) .AddParameter("Contributor", @event.ContributorId));
.AddParameter("Permission", @event.Permission.ToString()));
} }
protected Task<HistoryEventToStore> On(AppContributorRemoved @event, EnvelopeHeaders headers) protected Task<HistoryEventToStore> On(AppContributorAssigned @event, EnvelopeHeaders headers)
{ {
const string channel = "settings.contributors"; const string channel = "settings.contributors";
return Task.FromResult( return Task.FromResult(
ForEvent(@event, channel) ForEvent(@event, channel)
.AddParameter("Contributor", @event.ContributorId)); .AddParameter("Contributor", @event.ContributorId)
.AddParameter("Permission", @event.Permission.ToString()));
} }
protected Task<HistoryEventToStore> On(AppClientRenamed @event, EnvelopeHeaders headers) protected Task<HistoryEventToStore> On(AppClientAttached @event, EnvelopeHeaders headers)
{ {
const string channel = "settings.clients"; const string channel = "settings.clients";
return Task.FromResult( return Task.FromResult(
ForEvent(@event, channel) ForEvent(@event, channel)
.AddParameter("Id", @event.Id) .AddParameter("Id", @event.Id));
.AddParameter("Name", !string.IsNullOrWhiteSpace(@event.Name) ? @event.Name : @event.Id));
} }
protected Task<HistoryEventToStore> On(AppClientAttached @event, EnvelopeHeaders headers) protected Task<HistoryEventToStore> On(AppClientRevoked @event, EnvelopeHeaders headers)
{ {
const string channel = "settings.clients"; const string channel = "settings.clients";
@ -84,13 +83,14 @@ namespace Squidex.Read.Apps
.AddParameter("Id", @event.Id)); .AddParameter("Id", @event.Id));
} }
protected Task<HistoryEventToStore> On(AppClientRevoked @event, EnvelopeHeaders headers) protected Task<HistoryEventToStore> On(AppClientRenamed @event, EnvelopeHeaders headers)
{ {
const string channel = "settings.clients"; const string channel = "settings.clients";
return Task.FromResult( return Task.FromResult(
ForEvent(@event, channel) ForEvent(@event, channel)
.AddParameter("Id", @event.Id)); .AddParameter("Id", @event.Id)
.AddParameter("Name", !string.IsNullOrWhiteSpace(@event.Name) ? @event.Name : @event.Id));
} }
protected Task<HistoryEventToStore> On(AppLanguageAdded @event, EnvelopeHeaders headers) protected Task<HistoryEventToStore> On(AppLanguageAdded @event, EnvelopeHeaders headers)
@ -120,7 +120,7 @@ namespace Squidex.Read.Apps
.AddParameter("Language", @event.Language.EnglishName)); .AddParameter("Language", @event.Language.EnglishName));
} }
public override Task<HistoryEventToStore> CreateEventAsync(Envelope<IEvent> @event) protected override Task<HistoryEventToStore> CreateEventCoreAsync(Envelope<IEvent> @event)
{ {
return this.DispatchFuncAsync(@event.Payload, @event.Headers, (HistoryEventToStore)null); return this.DispatchFuncAsync(@event.Payload, @event.Headers, (HistoryEventToStore)null);
} }

46
src/Squidex.Read/Contents/ContentHistoryEventsCreator.cs

@ -0,0 +1,46 @@
// ==========================================================================
// ContentHistoryEventsCreator.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System.Threading.Tasks;
using Squidex.Events.Contents;
using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS;
using Squidex.Infrastructure.CQRS.Events;
using Squidex.Read.History;
namespace Squidex.Read.Contents
{
public sealed class ContentHistoryEventsCreator : HistoryEventsCreatorBase
{
public ContentHistoryEventsCreator(TypeNameRegistry typeNameRegistry)
: base(typeNameRegistry)
{
AddEventMessage<ContentCreated>(
"created content element.");
AddEventMessage<ContentUpdated>(
"updated content element.");
AddEventMessage<ContentDeleted>(
"deleted content element.");
AddEventMessage<ContentPublished>(
"published content element.");
AddEventMessage<ContentUnpublished>(
"unpublished content element.");
}
protected override Task<HistoryEventToStore> CreateEventCoreAsync(Envelope<IEvent> @event)
{
var channel = $"contents.{@event.Headers.AggregateId()}";
return Task.FromResult(ForEvent(@event.Payload, channel));
}
}
}

20
src/Squidex.Read/History/HistoryEventsCreatorBase.cs

@ -11,6 +11,7 @@ using System.Threading.Tasks;
using Squidex.Infrastructure; using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS; using Squidex.Infrastructure.CQRS;
using Squidex.Infrastructure.CQRS.Events; using Squidex.Infrastructure.CQRS.Events;
// ReSharper disable ConvertIfStatementToReturnStatement
namespace Squidex.Read.History namespace Squidex.Read.History
{ {
@ -38,6 +39,13 @@ namespace Squidex.Read.History
texts[typeNameRegistry.GetName<TEvent>()] = message; texts[typeNameRegistry.GetName<TEvent>()] = message;
} }
protected bool HasEventText(IEvent @event)
{
var message = typeNameRegistry.GetName(@event.GetType());
return texts.ContainsKey(message);
}
protected HistoryEventToStore ForEvent(IEvent @event, string channel) protected HistoryEventToStore ForEvent(IEvent @event, string channel)
{ {
var message = typeNameRegistry.GetName(@event.GetType()); var message = typeNameRegistry.GetName(@event.GetType());
@ -45,6 +53,16 @@ namespace Squidex.Read.History
return new HistoryEventToStore(channel, message); return new HistoryEventToStore(channel, message);
} }
public abstract Task<HistoryEventToStore> CreateEventAsync(Envelope<IEvent> @event); public Task<HistoryEventToStore> CreateEventAsync(Envelope<IEvent> @event)
{
if (HasEventText(@event.Payload))
{
return CreateEventCoreAsync(@event);
}
return Task.FromResult<HistoryEventToStore>(null);
}
protected abstract Task<HistoryEventToStore> CreateEventCoreAsync(Envelope<IEvent> @event);
} }
} }

85
src/Squidex.Read/Schemas/SchemaHistoryEventsCreator.cs

@ -11,13 +11,13 @@ using Squidex.Events.Schemas;
using Squidex.Infrastructure; using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS; using Squidex.Infrastructure.CQRS;
using Squidex.Infrastructure.CQRS.Events; using Squidex.Infrastructure.CQRS.Events;
using Squidex.Infrastructure.Dispatching;
using Squidex.Read.History; using Squidex.Read.History;
using Squidex.Read.Schemas.Services; using Squidex.Read.Schemas.Services;
// ReSharper disable InvertIf
namespace Squidex.Read.Schemas namespace Squidex.Read.Schemas
{ {
public class SchemaHistoryEventsCreator : HistoryEventsCreatorBase public sealed class SchemaHistoryEventsCreator : HistoryEventsCreatorBase
{ {
private readonly ISchemaProvider schemaProvider; private readonly ISchemaProvider schemaProvider;
@ -34,67 +34,70 @@ namespace Squidex.Read.Schemas
AddEventMessage<SchemaUpdated>( AddEventMessage<SchemaUpdated>(
"updated schema {[Name]}"); "updated schema {[Name]}");
AddEventMessage<SchemaDeleted>(
"deleted schema {[Name]}");
AddEventMessage<SchemaPublished>( AddEventMessage<SchemaPublished>(
"published schema {[Name]}"); "published schema {[Name]}");
AddEventMessage<SchemaUnpublished>( AddEventMessage<SchemaUnpublished>(
"unpublished schema {[Name]}"); "unpublished schema {[Name]}");
}
protected Task<HistoryEventToStore> On(SchemaCreated @event, EnvelopeHeaders headers) AddEventMessage<FieldAdded>(
{ "added field {[Field]} to schema {[Name]}");
var name = @event.Name;
string channel = $"schemas.{name}"; AddEventMessage<FieldDeleted>(
"deleted field {[Field]} from schema {[Name]}");
return Task.FromResult( AddEventMessage<FieldDisabled>(
ForEvent(@event, channel) "disabled field {[Field]} of schema {[Name]}");
.AddParameter("Name", name));
}
protected async Task<HistoryEventToStore> On(SchemaUpdated @event, EnvelopeHeaders headers) AddEventMessage<FieldEnabled>(
{ "disabled field {[Field]} of schema {[Name]}");
var name = await FindSchemaNameAsync(headers);
AddEventMessage<FieldHidden>(
"has hidden field {[Field]} of schema {[Name]}");
AddEventMessage<FieldShown>(
"has shown field {[Field]} of schema {[Name]}");
string channel = $"schemas.{name}"; AddEventMessage<FieldUpdated>(
"has updated field {[Field]} of schema {[Name]}");
return AddEventMessage<FieldDeleted>(
ForEvent(@event, channel) "deleted field {[Field]} of schema {[Name]}");
.AddParameter("Name", name);
} }
protected async Task<HistoryEventToStore> On(SchemaPublished @event, EnvelopeHeaders headers) protected override async Task<HistoryEventToStore> CreateEventCoreAsync(Envelope<IEvent> @event)
{ {
var name = await FindSchemaNameAsync(headers); var schemaCreated = @event.Payload as SchemaCreated;
string channel = $"schemas.{name}"; if (schemaCreated != null)
{
string channel = $"schemas.{schemaCreated.Name}";
return return ForEvent(@event.Payload, channel).AddParameter("Name", schemaCreated.Name);
ForEvent(@event, channel) }
.AddParameter("Name", name); else
} {
var schemaEntity = await schemaProvider.FindSchemaByIdAsync(@event.Headers.AggregateId());
var schemaName = schemaEntity.Label ?? schemaEntity.Name;
protected async Task<HistoryEventToStore> On(SchemaUnpublished @event, EnvelopeHeaders headers) string channel = $"schemas.{schemaName}";
{
var name = await FindSchemaNameAsync(headers);
string channel = $"schemas.{name}"; var result = ForEvent(@event.Payload, channel).AddParameter("Name", schemaName);
return var fieldEvent = @event.Payload as FieldEvent;
ForEvent(@event, channel)
.AddParameter("Name", name);
}
public override Task<HistoryEventToStore> CreateEventAsync(Envelope<IEvent> @event) if (fieldEvent != null)
{ {
return this.DispatchFuncAsync(@event.Payload, @event.Headers, (HistoryEventToStore)null); var fieldName = schemaEntity.Schema.Fields.GetOrDefault(fieldEvent.FieldId)?.Name;
}
private async Task<string> FindSchemaNameAsync(EnvelopeHeaders headers) result.AddParameter("Field", fieldName);
{ }
var schema = await schemaProvider.FindSchemaByIdAsync(headers.AggregateId());
return schema.Label ?? schema.Name; return result;
}
} }
} }
} }

5
src/Squidex/Config/Domain/ReadModule.cs

@ -12,6 +12,7 @@ using Squidex.Infrastructure.CQRS.Events;
using Squidex.Read.Apps; using Squidex.Read.Apps;
using Squidex.Read.Apps.Services; using Squidex.Read.Apps.Services;
using Squidex.Read.Apps.Services.Implementations; using Squidex.Read.Apps.Services.Implementations;
using Squidex.Read.Contents;
using Squidex.Read.History; using Squidex.Read.History;
using Squidex.Read.Schemas; using Squidex.Read.Schemas;
using Squidex.Read.Schemas.Services; using Squidex.Read.Schemas.Services;
@ -44,6 +45,10 @@ namespace Squidex.Config.Domain
.As<IHistoryEventsCreator>() .As<IHistoryEventsCreator>()
.SingleInstance(); .SingleInstance();
builder.RegisterType<ContentHistoryEventsCreator>()
.As<IHistoryEventsCreator>()
.SingleInstance();
builder.RegisterType<SchemaHistoryEventsCreator>() builder.RegisterType<SchemaHistoryEventsCreator>()
.As<IHistoryEventsCreator>() .As<IHistoryEventsCreator>()
.SingleInstance(); .SingleInstance();

9
src/Squidex/Config/Domain/Serializers.cs

@ -19,7 +19,8 @@ namespace Squidex.Config.Domain
public static class Serializers public static class Serializers
{ {
private static readonly TypeNameRegistry typeNameRegistry = new TypeNameRegistry(); private static readonly TypeNameRegistry typeNameRegistry = new TypeNameRegistry();
private static JsonSerializerSettings ConfigureJson(JsonSerializerSettings settings)
private static JsonSerializerSettings ConfigureJson(JsonSerializerSettings settings, TypeNameHandling typeNameHandling)
{ {
settings.SerializationBinder = new TypeNameSerializationBinder(typeNameRegistry); settings.SerializationBinder = new TypeNameSerializationBinder(typeNameRegistry);
settings.ContractResolver = new CamelCasePropertyNamesContractResolver(); settings.ContractResolver = new CamelCasePropertyNamesContractResolver();
@ -29,7 +30,7 @@ namespace Squidex.Config.Domain
settings.NullValueHandling = NullValueHandling.Ignore; settings.NullValueHandling = NullValueHandling.Ignore;
settings.DateFormatHandling = DateFormatHandling.IsoDateFormat; settings.DateFormatHandling = DateFormatHandling.IsoDateFormat;
settings.DateParseHandling = DateParseHandling.DateTime; settings.DateParseHandling = DateParseHandling.DateTime;
settings.TypeNameHandling = TypeNameHandling.Auto; settings.TypeNameHandling = typeNameHandling;
return settings; return settings;
} }
@ -41,7 +42,7 @@ namespace Squidex.Config.Domain
private static JsonSerializerSettings CreateSettings() private static JsonSerializerSettings CreateSettings()
{ {
return ConfigureJson(new JsonSerializerSettings()); return ConfigureJson(new JsonSerializerSettings(), TypeNameHandling.Auto);
} }
private static JsonSerializer CreateSerializer(JsonSerializerSettings settings) private static JsonSerializer CreateSerializer(JsonSerializerSettings settings)
@ -62,7 +63,7 @@ namespace Squidex.Config.Domain
{ {
mvc.AddJsonOptions(options => mvc.AddJsonOptions(options =>
{ {
ConfigureJson(options.SerializerSettings); ConfigureJson(options.SerializerSettings, TypeNameHandling.None);
}); });
return mvc; return mvc;

10
src/Squidex/Config/Domain/WriteModule.cs

@ -66,12 +66,12 @@ namespace Squidex.Config.Domain
builder.RegisterType<ClientKeyGenerator>() builder.RegisterType<ClientKeyGenerator>()
.AsSelf() .AsSelf()
.InstancePerDependency(); .SingleInstance();
builder.RegisterType<FieldRegistry>() builder.RegisterType<FieldRegistry>()
.AsSelf() .AsSelf()
.InstancePerDependency(); .SingleInstance();
builder.RegisterType<AppCommandHandler>() builder.RegisterType<AppCommandHandler>()
@ -89,11 +89,11 @@ namespace Squidex.Config.Domain
builder.Register<DomainObjectFactoryFunction<AppDomainObject>>(c => (id => new AppDomainObject(id, 0))) builder.Register<DomainObjectFactoryFunction<AppDomainObject>>(c => (id => new AppDomainObject(id, 0)))
.AsSelf() .AsSelf()
.InstancePerDependency(); .SingleInstance();
builder.Register<DomainObjectFactoryFunction<ContentDomainObject>>(c => (id => new ContentDomainObject(id, 0))) builder.Register<DomainObjectFactoryFunction<ContentDomainObject>>(c => (id => new ContentDomainObject(id, 0)))
.AsSelf() .AsSelf()
.InstancePerDependency(); .SingleInstance();
builder.Register<DomainObjectFactoryFunction<SchemaDomainObject>>(c => builder.Register<DomainObjectFactoryFunction<SchemaDomainObject>>(c =>
{ {
@ -102,7 +102,7 @@ namespace Squidex.Config.Domain
return (id => new SchemaDomainObject(id, 0, fieldRegistry)); return (id => new SchemaDomainObject(id, 0, fieldRegistry));
}) })
.AsSelf() .AsSelf()
.InstancePerDependency(); .SingleInstance();
} }
} }
} }

8
src/Squidex/app/features/content/module.ts

@ -43,12 +43,6 @@ const routes: Routes = [
{ {
path: 'new', path: 'new',
component: ContentPageComponent component: ContentPageComponent
}, {
path: 'history',
component: HistoryComponent,
data: {
channel: 'contents.{schemaName}'
}
}, { }, {
path: ':contentId', path: ':contentId',
component: ContentPageComponent, component: ContentPageComponent,
@ -60,7 +54,7 @@ const routes: Routes = [
path: 'history', path: 'history',
component: HistoryComponent, component: HistoryComponent,
data: { data: {
channel: 'contents.{schemaName}.{contentId}' channel: 'contents.{contentId}'
} }
} }
] ]

2
src/Squidex/app/features/content/pages/contents/content-item.component.ts

@ -59,6 +59,8 @@ export class ContentItemComponent extends AppComponentBase implements OnInit {
} }
public ngOnInit() { public ngOnInit() {
this.values = [];
for (let field of this.fields) { for (let field of this.fields) {
this.values.push(this.getValue(field)); this.values.push(this.getValue(field));
} }

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

@ -78,11 +78,6 @@
</div> </div>
</div> </div>
</div> </div>
<div class="panel-sidebar">
<a class="panel-link" routerLink="history" routerLinkActive="active">
<i class="icon-time"></i>
</a>
</div>
</div> </div>
</sqx-panel> </sqx-panel>

2
src/Squidex/app/shared/services/auth.service.ts

@ -214,6 +214,8 @@ export class AuthService {
options.headers.append('Content-Type', 'application/json'); options.headers.append('Content-Type', 'application/json');
} }
options.headers.append('Accept-Language', '*');
if (this.currentUser && this.currentUser.user) { if (this.currentUser && this.currentUser.user) {
options.headers.append('Authorization', `${this.currentUser.user.token_type} ${this.currentUser.user.access_token}`); options.headers.append('Authorization', `${this.currentUser.user.token_type} ${this.currentUser.user.access_token}`);
} }

Loading…
Cancel
Save