Browse Source

1) DateTime => Instant

2) Bugfix: Language selector not visible
3) Bugfix: Instant conversion
pull/1/head
Sebastian 9 years ago
parent
commit
3978642a6a
  1. 3
      src/Squidex.Core/Schemas/BooleanFieldEditor.cs
  2. 11
      src/Squidex.Core/Schemas/DateTimeField.cs
  3. 3
      src/Squidex.Infrastructure.MongoDb/EventStore/MongoEventCommit.cs
  4. 9
      src/Squidex.Infrastructure.MongoDb/EventStore/MongoEventStore.cs
  5. 54
      src/Squidex.Infrastructure.MongoDb/InstantSerializer.cs
  6. 5
      src/Squidex.Infrastructure.MongoDb/MongoEntity.cs
  7. 1
      src/Squidex.Infrastructure.MongoDb/MongoRepositoryBase.cs
  8. 16
      src/Squidex.Infrastructure/CQRS/Commands/EnrichWithTimestampHandler.cs
  9. 4
      src/Squidex.Infrastructure/CQRS/Commands/ITimestampCommand.cs
  10. 55
      src/Squidex.Infrastructure/Json/InstantConverter.cs
  11. 2
      src/Squidex.Infrastructure/Languages.cs
  12. 3
      src/Squidex.Infrastructure/Reflection/SimpleMapper.cs
  13. 5
      src/Squidex.Read.MongoDb/Apps/MongoAppClientEntity.cs
  14. 5
      src/Squidex.Read.MongoDb/History/ParsedHistoryEvent.cs
  15. 1
      src/Squidex.Read.MongoDb/Users/MongoUserEntity.cs
  16. 4
      src/Squidex.Read.MongoDb/Utils/EntityMapper.cs
  17. 4
      src/Squidex.Read/Apps/IAppClientEntity.cs
  18. 5
      src/Squidex.Read/IEntity.cs
  19. 6
      src/Squidex.Write/Apps/Commands/AttachClient.cs
  20. 3
      src/Squidex/Config/Domain/EventStoreModule.cs
  21. 5
      src/Squidex/Config/Domain/InfrastructureModule.cs
  22. 9
      src/Squidex/Config/Domain/Serializers.cs
  23. 2
      src/Squidex/Config/Identity/LazyClientStore.cs
  24. 6
      src/Squidex/Config/Swagger/SwaggerServices.cs
  25. 5
      src/Squidex/Controllers/Api/Apps/Models/AppDto.cs
  26. 3
      src/Squidex/Controllers/Api/History/Models/HistoryEventDto.cs
  27. 8
      src/Squidex/Controllers/Api/Schemas/Models/DateTimeFieldPropertiesDto.cs
  28. 5
      src/Squidex/Controllers/Api/Schemas/Models/SchemaDetailsDto.cs
  29. 5
      src/Squidex/Controllers/Api/Schemas/Models/SchemaDto.cs
  30. 5
      src/Squidex/Controllers/ContentApi/Models/ContentDto.cs
  31. 1
      src/Squidex/Squidex.csproj
  32. 4
      src/Squidex/app/features/content/pages/content/content-field.component.html
  33. 2
      src/Squidex/app/features/schemas/declarations.ts
  34. 4
      src/Squidex/app/features/schemas/module.ts
  35. 6
      src/Squidex/app/features/schemas/pages/schema/field.component.html
  36. 2
      src/Squidex/app/features/schemas/pages/schema/field.component.scss
  37. 5
      src/Squidex/app/features/schemas/pages/schema/schema-page.component.ts
  38. 9
      src/Squidex/app/features/schemas/pages/schema/types/boolean-ui.component.html
  39. 10
      src/Squidex/app/features/schemas/pages/schema/types/boolean-validation.component.scss
  40. 33
      src/Squidex/app/features/schemas/pages/schema/types/date-time-ui.component.html
  41. 2
      src/Squidex/app/features/schemas/pages/schema/types/date-time-ui.component.scss
  42. 40
      src/Squidex/app/features/schemas/pages/schema/types/date-time-ui.component.ts
  43. 33
      src/Squidex/app/features/schemas/pages/schema/types/date-time-validation.component.html
  44. 6
      src/Squidex/app/features/schemas/pages/schema/types/date-time-validation.component.scss
  45. 49
      src/Squidex/app/features/schemas/pages/schema/types/date-time-validation.component.ts
  46. 2
      src/Squidex/app/features/schemas/pages/schema/types/number-ui.component.html
  47. 2
      src/Squidex/app/features/schemas/pages/schema/types/number-validation.component.scss
  48. 2
      src/Squidex/app/features/schemas/pages/schema/types/string-ui.component.html
  49. 2
      src/Squidex/app/features/schemas/pages/schema/types/string-validation.component.scss
  50. 3
      src/Squidex/app/features/settings/pages/clients/clients-page.component.html
  51. 1
      src/Squidex/app/framework/angular/control-errors.component.ts
  52. 7
      src/Squidex/app/framework/angular/date-time-editor.component.html
  53. 31
      src/Squidex/app/framework/angular/date-time-editor.component.scss
  54. 154
      src/Squidex/app/framework/angular/date-time-editor.component.ts
  55. 18
      src/Squidex/app/framework/angular/validators.ts
  56. 1
      src/Squidex/app/framework/utils/date-time.ts
  57. 2
      src/Squidex/app/shared/components/language-selector.component.ts
  58. 22
      src/Squidex/app/shared/services/schemas.service.ts
  59. 5
      src/Squidex/app/theme/icomoon/demo-files/demo.css
  60. 169
      src/Squidex/app/theme/icomoon/demo.html
  61. BIN
      src/Squidex/app/theme/icomoon/fonts/icomoon.eot
  62. 3
      src/Squidex/app/theme/icomoon/fonts/icomoon.svg
  63. BIN
      src/Squidex/app/theme/icomoon/fonts/icomoon.ttf
  64. BIN
      src/Squidex/app/theme/icomoon/fonts/icomoon.woff
  65. 141
      src/Squidex/app/theme/icomoon/selection.json
  66. 19
      src/Squidex/app/theme/icomoon/style.css
  67. 1
      tests/Squidex.Core.Tests/Schemas/DateTimeFieldTests.cs
  68. 24
      tests/Squidex.Core.Tests/Schemas/SchemaTests.cs
  69. 5
      tests/Squidex.Core.Tests/Schemas/SchemaValidationTests.cs
  70. 32
      tests/Squidex.Infrastructure.Tests/CQRS/Commands/EnrichWithTimestampHandlerTests.cs
  71. 9
      tests/Squidex.Infrastructure.Tests/Reflection/SimpleMapperTests.cs
  72. 4
      tests/Squidex.Write.Tests/Apps/AppCommandHandlerTests.cs
  73. 4
      tests/Squidex.Write.Tests/Apps/AppDomainObjectTests.cs
  74. 2
      tools/GenerateLanguages/Program.cs

3
src/Squidex.Core/Schemas/BooleanFieldEditor.cs

@ -10,7 +10,6 @@ namespace Squidex.Core.Schemas
{
public enum BooleanFieldEditor
{
Checkbox,
Toggle
Checkbox
}
}

11
src/Squidex.Core/Schemas/DateTimeField.cs

@ -17,6 +17,7 @@ using NodaTime.Text;
using Squidex.Core.Schemas.Validators;
using Squidex.Infrastructure;
// ReSharper disable ConvertIfStatementToConditionalTernaryExpression
// ReSharper disable ConvertIfStatementToSwitchStatement
namespace Squidex.Core.Schemas
@ -67,7 +68,15 @@ namespace Squidex.Core.Schemas
protected override void PrepareJsonSchema(JsonProperty jsonProperty)
{
jsonProperty.Type = JsonObjectType.String;
jsonProperty.Format = "date-time";
if (Properties.Editor == DateTimeFieldEditor.Date)
{
jsonProperty.Format = JsonFormatStrings.Date;
}
else
{
jsonProperty.Format = JsonFormatStrings.DateTime;
}
}
protected override IEdmTypeReference CreateEdmType()

3
src/Squidex.Infrastructure.MongoDb/EventStore/MongoEventCommit.cs

@ -10,6 +10,7 @@ using System;
using System.Collections.Generic;
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
using NodaTime;
namespace Squidex.Infrastructure.MongoDb.EventStore
{
@ -22,7 +23,7 @@ namespace Squidex.Infrastructure.MongoDb.EventStore
[BsonRequired]
[BsonElement]
public DateTime Timestamp { get; set; }
public Instant Timestamp { get; set; }
[BsonElement]
[BsonRequired]

9
src/Squidex.Infrastructure.MongoDb/EventStore/MongoEventStore.cs

@ -13,6 +13,7 @@ using System.Reactive.Linq;
using System.Threading.Tasks;
using MongoDB.Bson;
using MongoDB.Driver;
using NodaTime;
using Squidex.Infrastructure.CQRS.Events;
using Squidex.Infrastructure.Reflection;
@ -26,13 +27,17 @@ namespace Squidex.Infrastructure.MongoDb.EventStore
{
private const int Retries = 500;
private readonly IEventNotifier notifier;
private readonly IClock clock;
private string eventsOffsetIndex;
public MongoEventStore(IMongoDatabase database, IEventNotifier notifier)
public MongoEventStore(IMongoDatabase database, IEventNotifier notifier, IClock clock)
: base(database)
{
Guard.NotNull(clock, nameof(clock));
Guard.NotNull(notifier, nameof(notifier));
this.clock = clock;
this.notifier = notifier;
}
@ -115,7 +120,7 @@ namespace Squidex.Infrastructure.MongoDb.EventStore
throw new WrongEventVersionException(currentVersion, expectedVersion);
}
var now = DateTime.UtcNow;
var now = clock.GetCurrentInstant();
var commitEvents = events.Select(x => SimpleMapper.Map(x, new MongoEvent())).ToList();

54
src/Squidex.Infrastructure.MongoDb/InstantSerializer.cs

@ -0,0 +1,54 @@
// ==========================================================================
// InstantSerializer.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Serializers;
using NodaTime;
using NodaTime.Text;
// ReSharper disable InvertIf
namespace Squidex.Infrastructure.MongoDb
{
public sealed class InstantSerializer : SerializerBase<Instant>
{
private static bool isRegistered;
private static readonly object LockObject = new object();
public static bool Register()
{
if (!isRegistered)
{
lock (LockObject)
{
if (!isRegistered)
{
BsonSerializer.RegisterSerializer(new InstantSerializer());
isRegistered = true;
return true;
}
}
}
return false;
}
public override Instant Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
{
var value = context.Reader.ReadDateTime();
return Instant.FromUnixTimeMilliseconds(value);
}
public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, Instant value)
{
context.Writer.WriteDateTime(value.ToUnixTimeMilliseconds());
}
}
}

5
src/Squidex.Infrastructure.MongoDb/MongoEntity.cs

@ -9,6 +9,7 @@
using System;
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
using NodaTime;
namespace Squidex.Infrastructure.MongoDb
{
@ -21,10 +22,10 @@ namespace Squidex.Infrastructure.MongoDb
[BsonRequired]
[BsonElement]
public DateTime Created { get; set; }
public Instant Created { get; set; }
[BsonRequired]
[BsonElement]
public DateTime LastModified { get; set; }
public Instant LastModified { get; set; }
}
}

1
src/Squidex.Infrastructure.MongoDb/MongoRepositoryBase.cs

@ -88,6 +88,7 @@ namespace Squidex.Infrastructure.MongoDb
static MongoRepositoryBase()
{
RefTokenSerializer.Register();
InstantSerializer.Register();
}
protected MongoRepositoryBase(IMongoDatabase database)

16
src/Squidex.Infrastructure/CQRS/Commands/EnrichWithTimestampHandler.cs

@ -8,23 +8,19 @@
using System;
using System.Threading.Tasks;
using NodaTime;
namespace Squidex.Infrastructure.CQRS.Commands
{
public sealed class EnrichWithTimestampHandler : ICommandHandler
{
private readonly Func<DateTime> timestamp;
private readonly IClock clock;
public EnrichWithTimestampHandler()
: this(() => DateTime.UtcNow)
public EnrichWithTimestampHandler(IClock clock)
{
}
public EnrichWithTimestampHandler(Func<DateTime> timestamp)
{
Guard.NotNull(timestamp, nameof(timestamp));
Guard.NotNull(clock, nameof(clock));
this.timestamp = timestamp;
this.clock = clock;
}
public Task<bool> HandleAsync(CommandContext context)
@ -33,7 +29,7 @@ namespace Squidex.Infrastructure.CQRS.Commands
if (timestampCommand != null)
{
timestampCommand.Timestamp = timestamp();
timestampCommand.Timestamp = clock.GetCurrentInstant();
}
return Task.FromResult(false);

4
src/Squidex.Infrastructure/CQRS/Commands/ITimestampCommand.cs

@ -6,12 +6,12 @@
// All rights reserved.
// ==========================================================================
using System;
using NodaTime;
namespace Squidex.Infrastructure.CQRS.Commands
{
public interface ITimestampCommand : ICommand
{
DateTime Timestamp { get; set; }
Instant Timestamp { get; set; }
}
}

55
src/Squidex.Infrastructure/Json/InstantConverter.cs

@ -0,0 +1,55 @@
// ==========================================================================
// InstantConverter.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System;
using Newtonsoft.Json;
using NodaTime;
using NodaTime.Text;
// ReSharper disable ConvertIfStatementToSwitchStatement
namespace Squidex.Infrastructure.Json
{
public sealed class InstantConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
if (value != null)
{
writer.WriteValue(value.ToString());
}
else
{
writer.WriteNull();
}
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.String)
{
return InstantPattern.General.Parse(reader.Value.ToString()).Value;
}
if (reader.TokenType == JsonToken.Date)
{
return Instant.FromDateTimeUtc((DateTime)reader.Value);
}
if (reader.TokenType == JsonToken.Null && objectType == typeof(Instant?))
{
return null;
}
throw new JsonException($"Not a valid date time, expected String or Date, but got {reader.TokenType}.");
}
public override bool CanConvert(Type objectType)
{
return objectType == typeof(Instant) || objectType == typeof(Instant?);
}
}
}

2
src/Squidex.Infrastructure/Languages.cs

@ -1,5 +1,5 @@
// ==========================================================================
// Langauges.cs
// Languages.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group

3
src/Squidex.Infrastructure/Reflection/SimpleMapper.cs

@ -101,8 +101,7 @@ namespace Squidex.Infrastructure.Reflection
typeof(short),
typeof(int),
typeof(long),
typeof(string),
typeof(DateTime)
typeof(string)
};
static ClassMapper()

5
src/Squidex.Read.MongoDb/Apps/MongoAppClientEntity.cs

@ -6,7 +6,6 @@
// All rights reserved.
// ==========================================================================
using System;
using MongoDB.Bson.Serialization.Attributes;
using Squidex.Read.Apps;
@ -22,10 +21,6 @@ namespace Squidex.Read.MongoDb.Apps
[BsonElement]
public string Secret { get; set; }
[BsonRequired]
[BsonElement]
public DateTime ExpiresUtc { get; set; }
[BsonRequired]
[BsonElement]
public string Name { get; set; }

5
src/Squidex.Read.MongoDb/History/ParsedHistoryEvent.cs

@ -8,6 +8,7 @@
using System;
using System.Collections.Generic;
using NodaTime;
using Squidex.Infrastructure;
using Squidex.Read.History;
@ -35,12 +36,12 @@ namespace Squidex.Read.MongoDb.History
get { return inner.Actor; }
}
public DateTime Created
public Instant Created
{
get { return inner.Created; }
}
public DateTime LastModified
public Instant LastModified
{
get { return inner.LastModified; }
}

1
src/Squidex.Read.MongoDb/Users/MongoUserEntity.cs

@ -31,6 +31,7 @@ namespace Squidex.Read.MongoDb.Users
{
get { return inner.Claims.Find(x => x.Type == SquidexClaimTypes.SquidexDisplayName)?.Value; }
}
public string PictureUrl
{
get { return inner.Claims.Find(x => x.Type == SquidexClaimTypes.SquidexPictureUrl)?.Value; }

4
src/Squidex.Read.MongoDb/Utils/EntityMapper.cs

@ -46,12 +46,12 @@ namespace Squidex.Read.MongoDb.Utils
private static void SetCreated(EnvelopeHeaders headers, MongoEntity entity)
{
entity.Created = headers.Timestamp().ToDateTimeUtc();
entity.Created = headers.Timestamp();
}
private static void SetLastModified(EnvelopeHeaders headers, MongoEntity entity)
{
entity.LastModified = headers.Timestamp().ToDateTimeUtc();
entity.LastModified = headers.Timestamp();
}
private static void SetCreatedBy(SquidexEvent @event, MongoEntity entity)

4
src/Squidex.Read/Apps/IAppClientEntity.cs

@ -6,8 +6,6 @@
// All rights reserved.
// ==========================================================================
using System;
namespace Squidex.Read.Apps
{
public interface IAppClientEntity
@ -17,7 +15,5 @@ namespace Squidex.Read.Apps
string Name { get; }
string Secret { get; }
DateTime ExpiresUtc { get; }
}
}

5
src/Squidex.Read/IEntity.cs

@ -7,6 +7,7 @@
// ==========================================================================
using System;
using NodaTime;
namespace Squidex.Read
{
@ -14,8 +15,8 @@ namespace Squidex.Read
{
Guid Id { get; }
DateTime Created { get; }
Instant Created { get; }
DateTime LastModified { get; }
Instant LastModified { get; }
}
}

6
src/Squidex.Write/Apps/Commands/AttachClient.cs

@ -6,19 +6,15 @@
// All rights reserved.
// ==========================================================================
using System;
using System.Collections.Generic;
using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS.Commands;
namespace Squidex.Write.Apps.Commands
{
public sealed class AttachClient : AppAggregateCommand, ITimestampCommand, IValidatable
public sealed class AttachClient : AppAggregateCommand, IValidatable
{
public string Id { get; set; }
public DateTime Timestamp { get; set; }
public void Validate(IList<ValidationError> errors)
{
if (!Id.IsSlug())

3
src/Squidex/Config/Domain/EventStoreModule.cs

@ -10,6 +10,7 @@ using System;
using Autofac;
using Microsoft.Extensions.Configuration;
using MongoDB.Driver;
using NodaTime;
using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS.Events;
using Squidex.Infrastructure.MongoDb.EventStore;
@ -55,7 +56,7 @@ namespace Squidex.Config.Domain
var mongoDbClient = new MongoClient(connectionString);
var mongoDatabase = mongoDbClient.GetDatabase(databaseName);
var eventStore = new MongoEventStore(mongoDatabase, c.Resolve<IEventNotifier>());
var eventStore = new MongoEventStore(mongoDatabase, c.Resolve<IEventNotifier>(), c.Resolve<IClock>());
return eventStore;
})

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

@ -12,6 +12,7 @@ using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Options;
using NodaTime;
using Squidex.Core.Schemas;
using Squidex.Core.Schemas.Json;
using Squidex.Infrastructure;
@ -32,6 +33,10 @@ namespace Squidex.Config.Domain
protected override void Load(ContainerBuilder builder)
{
builder.Register(c => SystemClock.Instance)
.As<IClock>()
.SingleInstance();
builder.RegisterType<HttpContextAccessor>()
.As<IHttpContextAccessor>()
.SingleInstance();

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

@ -10,6 +10,8 @@ using System.Reflection;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using NodaTime;
using NodaTime.Serialization.JsonNet;
using Squidex.Events;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Json;
@ -26,20 +28,23 @@ namespace Squidex.Config.Domain
settings.ContractResolver = new CamelCasePropertyNamesContractResolver();
settings.Converters.Add(new InstantConverter());
settings.Converters.Add(new LanguageConverter());
settings.Converters.Add(new NamedGuidIdConverter());
settings.Converters.Add(new NamedLongIdConverter());
settings.Converters.Add(new NamedStringIdConverter());
settings.Converters.Add(new LanguageConverter());
settings.Converters.Add(new PropertiesBagConverter());
settings.Converters.Add(new RefTokenConverter());
settings.NullValueHandling = NullValueHandling.Ignore;
settings.DateFormatHandling = DateFormatHandling.IsoDateFormat;
settings.DateParseHandling = DateParseHandling.DateTime;
settings.DateParseHandling = DateParseHandling.None;
settings.TypeNameHandling = typeNameHandling;
settings.ConfigureForNodaTime(DateTimeZoneProviders.Tzdb);
return settings;
}

2
src/Squidex/Config/Identity/LazyClientStore.cs

@ -72,7 +72,7 @@ namespace Squidex.Config.Identity
{
ClientId = id,
ClientName = id,
ClientSecrets = new List<Secret> { new Secret(appClient.Secret.Sha256(), appClient.ExpiresUtc) },
ClientSecrets = new List<Secret> { new Secret(appClient.Secret.Sha256()) },
AccessTokenLifetime = (int)TimeSpan.FromDays(30).TotalSeconds,
AllowedGrantTypes = GrantTypes.ClientCredentials,
AllowedScopes = new List<string>

6
src/Squidex/Config/Swagger/SwaggerServices.cs

@ -11,6 +11,7 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using NJsonSchema;
using NJsonSchema.Generation.TypeMappers;
using NodaTime;
using NSwag.AspNetCore;
using NSwag.SwaggerGeneration.WebApi.Processors.Security;
using Squidex.Controllers.ContentApi.Generator;
@ -70,6 +71,11 @@ namespace Squidex.Config.Swagger
settings.TypeMappers = new List<ITypeMapper>
{
new PrimitiveTypeMapper(typeof(Instant), schema =>
{
schema.Type = JsonObjectType.String;
schema.Format = JsonFormatStrings.DateTime;
}),
new PrimitiveTypeMapper(typeof(Language), s => s.Type = JsonObjectType.String),
new PrimitiveTypeMapper(typeof(RefToken), s => s.Type = JsonObjectType.String)
};

5
src/Squidex/Controllers/Api/Apps/Models/AppDto.cs

@ -10,6 +10,7 @@ using System;
using System.ComponentModel.DataAnnotations;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using NodaTime;
using Squidex.Core.Apps;
namespace Squidex.Controllers.Api.Apps.Models
@ -31,12 +32,12 @@ namespace Squidex.Controllers.Api.Apps.Models
/// <summary>
/// The date and time when the app has been created.
/// </summary>
public DateTime Created { get; set; }
public Instant Created { get; set; }
/// <summary>
/// The date and time when the app has been modified last.
/// </summary>
public DateTime LastModified { get; set; }
public Instant LastModified { get; set; }
/// <summary>
/// The permission level of the user.

3
src/Squidex/Controllers/Api/History/Models/HistoryEventDto.cs

@ -8,6 +8,7 @@
using System;
using System.ComponentModel.DataAnnotations;
using NodaTime;
namespace Squidex.Controllers.Api.History.Models
{
@ -33,6 +34,6 @@ namespace Squidex.Controllers.Api.History.Models
/// <summary>
/// The time when the event happened.
/// </summary>
public DateTime Created { get; set; }
public Instant Created { get; set; }
}
}

8
src/Squidex/Controllers/Api/Schemas/Models/DateTimeFieldPropertiesDto.cs

@ -6,10 +6,10 @@
// All rights reserved.
// ==========================================================================
using System.Collections.Immutable;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using NJsonSchema.Annotations;
using NodaTime;
using Squidex.Core.Schemas;
using Squidex.Infrastructure.Reflection;
@ -21,17 +21,17 @@ namespace Squidex.Controllers.Api.Schemas.Models
/// <summary>
/// The default value for the field value.
/// </summary>
public string DefaultValue { get; set; }
public Instant? DefaultValue { get; set; }
/// <summary>
/// The maximum allowed value for the field value.
/// </summary>
public string MaxValue { get; set; }
public Instant? MaxValue { get; set; }
/// <summary>
/// The minimum allowed value for the field value.
/// </summary>
public string MinValue { get; set; }
public Instant? MinValue { get; set; }
/// <summary>
/// The editor that is used to manage this field.

5
src/Squidex/Controllers/Api/Schemas/Models/SchemaDetailsDto.cs

@ -10,6 +10,7 @@ using Squidex.Infrastructure;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using NodaTime;
namespace Squidex.Controllers.Api.Schemas.Models
{
@ -65,11 +66,11 @@ namespace Squidex.Controllers.Api.Schemas.Models
/// <summary>
/// The date and time when the schema has been created.
/// </summary>
public DateTime Created { get; set; }
public Instant Created { get; set; }
/// <summary>
/// The date and time when the schema has been modified last.
/// </summary>
public DateTime LastModified { get; set; }
public Instant LastModified { get; set; }
}
}

5
src/Squidex/Controllers/Api/Schemas/Models/SchemaDto.cs

@ -9,6 +9,7 @@
using Squidex.Infrastructure;
using System;
using System.ComponentModel.DataAnnotations;
using NodaTime;
namespace Squidex.Controllers.Api.Schemas.Models
{
@ -52,11 +53,11 @@ namespace Squidex.Controllers.Api.Schemas.Models
/// <summary>
/// The date and time when the schema has been created.
/// </summary>
public DateTime Created { get; set; }
public Instant Created { get; set; }
/// <summary>
/// The date and time when the schema has been modified last.
/// </summary>
public DateTime LastModified { get; set; }
public Instant LastModified { get; set; }
}
}

5
src/Squidex/Controllers/ContentApi/Models/ContentDto.cs

@ -8,6 +8,7 @@
using System;
using System.ComponentModel.DataAnnotations;
using NodaTime;
using Squidex.Infrastructure;
namespace Squidex.Controllers.ContentApi.Models
@ -40,12 +41,12 @@ namespace Squidex.Controllers.ContentApi.Models
/// <summary>
/// The date and time when the content element has been created.
/// </summary>
public DateTime Created { get; set; }
public Instant Created { get; set; }
/// <summary>
/// The date and time when the content element has been modified last.
/// </summary>
public DateTime LastModified { get; set; }
public Instant LastModified { get; set; }
/// <summary>
/// Indicates if the content element is publihed.

1
src/Squidex/Squidex.csproj

@ -58,6 +58,7 @@
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="1.1.0" />
<PackageReference Include="MongoDB.Driver" Version="2.4.2" />
<PackageReference Include="NJsonSchema" Version="8.5.6255.20253" />
<PackageReference Include="NodaTime.Serialization.JsonNet" Version="2.0.0-beta20170123" />
<PackageReference Include="NSwag.AspNetCore" Version="9.5.0" />
<PackageReference Include="OpenCover" Version="4.6.519" />
<PackageReference Include="ReportGenerator" Version="2.5.3-beta2" />

4
src/Squidex/app/features/content/pages/content/content-field.component.html

@ -55,6 +55,8 @@
</div>
</div>
</div>
</div><div *ngSwitchCase="'dateTime'">
<sqx-date-time-editor [mode]="field.properties.editor" [formControlName]="language"></sqx-date-time-editor>
</div>
<div *ngSwitchCase="'boolean'">
<div [ngSwitch]="field.properties.editor">
@ -65,8 +67,6 @@
</label>
</div>
</div>
<div *ngSwitchCase="'Toggle'">
</div>
</div>
</div>
</div>

2
src/Squidex/app/features/schemas/declarations.ts

@ -7,6 +7,8 @@
export * from './pages/schema/types/boolean-ui.component';
export * from './pages/schema/types/boolean-validation.component';
export * from './pages/schema/types/date-time-ui.component';
export * from './pages/schema/types/date-time-validation.component';
export * from './pages/schema/types/number-ui.component';
export * from './pages/schema/types/number-validation.component';
export * from './pages/schema/types/string-ui.component';

4
src/Squidex/app/features/schemas/module.ts

@ -20,6 +20,8 @@ import {
FieldComponent,
BooleanUIComponent,
BooleanValidationComponent,
DateTimeUIComponent,
DateTimeValidationComponent,
NumberUIComponent,
NumberValidationComponent,
SchemaEditFormComponent,
@ -74,6 +76,8 @@ const routes: Routes = [
FieldComponent,
BooleanUIComponent,
BooleanValidationComponent,
DateTimeUIComponent,
DateTimeValidationComponent,
NumberUIComponent,
NumberValidationComponent,
SchemaEditFormComponent,

6
src/Squidex/app/features/schemas/pages/schema/field.component.html

@ -138,6 +138,9 @@
<div *ngSwitchCase="'boolean'">
<sqx-boolean-validation [editForm]="editForm" [properties]="field.properties"></sqx-boolean-validation>
</div>
<div *ngSwitchCase="'dateTime'">
<sqx-date-time-validation [editForm]="editForm" [properties]="field.properties"></sqx-date-time-validation>
</div>
</div>
</div>
@ -152,6 +155,9 @@
<div *ngSwitchCase="'boolean'">
<sqx-boolean-ui [editForm]="editForm" [properties]="field.properties"></sqx-boolean-ui>
</div>
<div *ngSwitchCase="'dateTime'">
<sqx-date-time-ui [editForm]="editForm" [properties]="field.properties"></sqx-date-time-ui>
</div>
</div>
</div>
</form>

2
src/Squidex/app/features/schemas/pages/schema/field.component.scss

@ -35,7 +35,7 @@ $field-header: #e7ebef;
&.active {
background: $color-theme-blue;
border: 0;
border-color: $color-theme-blue;
color: $color-accent-dark;
}
}

5
src/Squidex/app/features/schemas/pages/schema/schema-page.component.ts

@ -43,7 +43,8 @@ export class SchemaPageComponent extends AppComponentBase implements OnInit {
public fieldTypes: string[] = [
'string',
'number',
'boolean'
'boolean',
'dateTime'
];
public schemaName: string;
@ -65,7 +66,7 @@ export class SchemaPageComponent extends AppComponentBase implements OnInit {
[
Validators.required,
Validators.maxLength(40),
ValidatorsEx.pattern('[a-z0-9]+(\-[a-z0-9]+)*', 'Name must be a valid javascript name in camel case.')
ValidatorsEx.pattern('[a-zA-Z0-9]+(\\-[a-zA-Z0-9]+)*', 'Name must be a valid javascript name in camel case.')
]]
});

9
src/Squidex/app/features/schemas/pages/schema/types/boolean-ui.component.html

@ -3,8 +3,6 @@
<label for="field-placeholder" class="col col-3 col-form-label">Placeholder</label>
<div class="col col-6">
<sqx-control-errors for="placeholder" [submitted]="editFormSubmitted"></sqx-control-errors>
<input type="text" class="form-control" id="field-placeholder" maxlength="100" formControlName="placeholder" />
<span class="form-hint">
@ -23,13 +21,6 @@
<span class="radio-label">Checkbox</span>
</label>
<label class="btn btn-radio" [class.active]="editForm.controls.editor.value === 'Toggle'">
<input type="radio" class="radio-input" formControlName="editor" value="Toggle" />
<i class="icon-control-toggle"></i>
<span class="radio-label" clas>Toggle</span>
</label>
</div>
</div>
</div>

10
src/Squidex/app/features/schemas/pages/schema/types/boolean-validation.component.scss

@ -1,16 +1,6 @@
@import '_vars';
@import '_mixins';
.minlength {
&-col {
position: relative;
}
&-label {
@include absolute(0, -.25rem, auto, auto);
}
}
.form-check-input {
margin: 0;
}

33
src/Squidex/app/features/schemas/pages/schema/types/date-time-ui.component.html

@ -0,0 +1,33 @@
<div [formGroup]="editForm">
<div class="form-group row">
<label for="field-placeholder" class="col col-3 col-form-label">Placeholder</label>
<div class="col col-6">
<input type="text" class="form-control" id="field-placeholder" maxlength="100" formControlName="placeholder" />
<span class="form-hint">
Define the placeholder for the input control.
</span>
</div>
</div>
<div class="form-group row">
<label for="field-editor" class="col col-3 col-form-label">Editor</label>
<div class="col col-9">
<label class="btn btn-radio" [class.active]="editForm.controls.editor.value === 'Date'">
<input type="radio" class="radio-input" formControlName="editor" value="Date" />
<i class="icon-control-date"></i>
<span class="radio-label">Date</span>
</label>
<label class="btn btn-radio" [class.active]="editForm.controls.editor.value === 'DateTime'">
<input type="radio" class="radio-input" formControlName="editor" value="DateTime" />
<i class="icon-control-datetime"></i>
<span class="radio-label" clas>DateTime</span>
</label>
</div>
</div>
</div>

2
src/Squidex/app/features/schemas/pages/schema/types/date-time-ui.component.scss

@ -0,0 +1,2 @@
@import '_vars';
@import '_mixins';

40
src/Squidex/app/features/schemas/pages/schema/types/date-time-ui.component.ts

@ -0,0 +1,40 @@
/*
* Squidex Headless CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved
*/
import { Component, Input, OnInit } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { Observable } from 'rxjs';
import { FloatConverter, NumberFieldPropertiesDto } from 'shared';
@Component({
selector: 'sqx-date-time-ui',
styleUrls: ['date-time-ui.component.scss'],
templateUrl: 'date-time-ui.component.html'
})
export class DateTimeUIComponent implements OnInit {
@Input()
public editForm: FormGroup;
@Input()
public properties: NumberFieldPropertiesDto;
public converter = new FloatConverter();
public hideAllowedValues: Observable<boolean>;
public ngOnInit() {
this.editForm.addControl('editor',
new FormControl(this.properties.editor, [
Validators.required
]));
this.editForm.addControl('placeholder',
new FormControl(this.properties.placeholder, [
Validators.maxLength(100)
]));
}
}

33
src/Squidex/app/features/schemas/pages/schema/types/date-time-validation.component.html

@ -0,0 +1,33 @@
<div [formGroup]="editForm">
<div class="form-group row">
<label class="col col-3 col-form-checkbox-label" for="field-required">Required</label>
<div class="col col-6">
<input type="checkbox" class="form-check-input" id="field-required" formControlName="isRequired" />
</div>
</div>
<div class="form-group row">
<label class="col col-3 col-form-label">Min Value</label>
<div class="col col-9">
<sqx-date-time-editor enforceTime="true" mode="DateTime" formControlName="minValue"></sqx-date-time-editor>
</div>
</div>
<div class="form-group row">
<label class="col col-3 col-form-label">Max Value</label>
<div class="col col-9">
<sqx-date-time-editor enforceTime="true" mode="DateTime" formControlName="maxValue"></sqx-date-time-editor>
</div>
</div>
<div class="form-group row" [class.hidden]="(hideDefaultValue | async)">
<label class="col col-3 col-form-label" for="field-default-value">Default Value</label>
<div class="col col-9">
<sqx-date-time-editor enforceTime="true" formControlName="defaultValue"></sqx-date-time-editor>
</div>
</div>
</div>

6
src/Squidex/app/features/schemas/pages/schema/types/date-time-validation.component.scss

@ -0,0 +1,6 @@
@import '_vars';
@import '_mixins';
.form-check-input {
margin: 0;
}

49
src/Squidex/app/features/schemas/pages/schema/types/date-time-validation.component.ts

@ -0,0 +1,49 @@
/*
* Squidex Headless CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved
*/
import { Component, Input, OnInit } from '@angular/core';
import { FormControl, FormGroup } from '@angular/forms';
import { Observable } from 'rxjs';
import { NumberFieldPropertiesDto, ValidatorsEx } from 'shared';
@Component({
selector: 'sqx-date-time-validation',
styleUrls: ['date-time-validation.component.scss'],
templateUrl: 'date-time-validation.component.html'
})
export class DateTimeValidationComponent implements OnInit {
@Input()
public editForm: FormGroup;
@Input()
public properties: NumberFieldPropertiesDto;
public hideDefaultValue: Observable<boolean>;
public ngOnInit() {
this.editForm.addControl('maxValue',
new FormControl(this.properties.maxValue, [
ValidatorsEx.validDateTime()
]));
this.editForm.addControl('minValue',
new FormControl(this.properties.minValue, [
ValidatorsEx.validDateTime()
]));
this.editForm.addControl('defaultValue',
new FormControl(this.properties.defaultValue, [
ValidatorsEx.validDateTime()
]));
this.hideDefaultValue =
Observable.of(this.properties.isRequired)
.merge(this.editForm.get('isRequired').valueChanges)
.map(x => !!x);
}
}

2
src/Squidex/app/features/schemas/pages/schema/types/number-ui.component.html

@ -3,8 +3,6 @@
<label for="field-placeholder" class="col col-3 col-form-label">Placeholder</label>
<div class="col col-6">
<sqx-control-errors for="placeholder" [submitted]="editFormSubmitted"></sqx-control-errors>
<input type="text" class="form-control" id="field-placeholder" maxlength="100" formControlName="placeholder" />
<span class="form-hint">

2
src/Squidex/app/features/schemas/pages/schema/types/number-validation.component.scss

@ -7,7 +7,7 @@
}
&-label {
@include absolute(0, -25rem, auto, auto);
@include absolute(0, -2rem, auto, auto);
}
}

2
src/Squidex/app/features/schemas/pages/schema/types/string-ui.component.html

@ -3,8 +3,6 @@
<label for="field-input-placeholder" class="col col-3 col-form-label">Placeholder</label>
<div class="col col-6">
<sqx-control-errors for="placeholder" [submitted]="editFormSubmitted"></sqx-control-errors>
<input type="text" class="form-control" id="field-input-placeholder" maxlength="100" formControlName="placeholder" />
<span class="form-hint">

2
src/Squidex/app/features/schemas/pages/schema/types/string-validation.component.scss

@ -7,7 +7,7 @@
}
&-label {
@include absolute(0, -25rem, auto, auto);
@include absolute(0, -2rem, auto, auto);
}
}

3
src/Squidex/app/features/settings/pages/clients/clients-page.component.html

@ -13,10 +13,9 @@
<div class="panel-main">
<div class="panel-content panel-content-scroll">
<div><sqx-date-time-editor mode="DateTime" ngModel="other"></sqx-date-time-editor></div>
<div><sqx-date-time-editor mode="Date" ngModel="2013-01-01T00:00:00-13:00"></sqx-date-time-editor></div>
<div><sqx-date-time-editor mode="DateWithTimezone" ngModel="2013-01-01T00:00:00-13:00"></sqx-date-time-editor></div>
<div><sqx-date-time-editor mode="DateTime" ngModel="2013-01-01T00:00:00-13:00"></sqx-date-time-editor></div>
<div><sqx-date-time-editor mode="DateTimeWithTimezone" ngModel="2013-01-01T00:00:00-13:00"></sqx-date-time-editor></div>
<div class="table-items-row" *ngIf="appClients && appClients.length === 0">
No client created yet.

1
src/Squidex/app/framework/angular/control-errors.component.ts

@ -18,6 +18,7 @@ const DEFAULT_ERRORS: { [key: string]: string } = {
maxvalue: '{field} must be smaller than {maxValue}.',
minlength: '{field} must have more than {requiredLength} characters.',
maxlength: '{field} cannot have more than {requiredLength} characters.',
validdatetime: '{field} is not a valid date time',
validnumber: '{field} is not a valid number.',
validvalues: '{field} is not a valid value.'
};

7
src/Squidex/app/framework/angular/date-time-editor.component.html

@ -1,15 +1,10 @@
<div>
<div class="form-inline">
<div class="form-group date-group">
<input type="text" class="form-control" #dateInput [disabled]="isDisabled" readonly />
<input type="text" class="form-control" [formControl]="dateControl" (blur)="touched()" #dateInput />
</div>
<div class="form-group time-group" *ngIf="showTime">
<input type="text" class="form-control" [formControl]="timeControl" (blur)="touched()" />
</div>
<div class="form-group timezone-group" *ngIf="showTimezone">
<select class="form-control" [formControl]="timeZoneControl">
<option *ngFor="let timezone of timezones" [ngValue]="timezone.value">{{timezone.label}}</option>
</select>
</div>
</div>
</div>

31
src/Squidex/app/framework/angular/date-time-editor.component.scss

@ -3,6 +3,21 @@
$form-color: #fff;
:host(.ng-invalid) {
&.ng-dirty {
.form-control {
& {
border-color: $color-theme-error;
}
&:hover,
&:focus {
border-color: $color-theme-error-dark;
}
}
}
}
.form-control {
&[readonly] {
background: $form-color;
@ -11,26 +26,16 @@ $form-color: #fff;
.date-group {
& {
padding-right: .5rem;
padding-right: .25rem;
}
.form-control {
width: 8rem;
width: 7.5rem;
}
}
.time-group {
& {
padding-right: .5rem;
}
.form-control {
width: 5rem;
}
}
.timezone-group {
.form-control {
width: 8.5rem;
width: 7.5rem;
}
}

154
src/Squidex/app/framework/angular/date-time-editor.component.ts

@ -11,7 +11,6 @@ import * as moment from 'moment';
let Pikaday = require('pikaday/pikaday');
/* tslint:disable:no-empty */
const NOOP = () => { };
@ -22,50 +21,6 @@ export const SQX_DATE_TIME_EDITOR_CONTROL_VALUE_ACCESSOR: any = {
multi: true
};
const TIMEZONES: any[] = [
{ label: 'UTC-13:00', value: -780 },
{ label: 'UTC-12:00', value: -720 },
{ label: 'UTC-11:00', value: -660 },
{ label: 'UTC-10:00', value: -600 },
{ label: 'UTC-09:30', value: -570 },
{ label: 'UTC-09:00', value: -540 },
{ label: 'UTC-08:00', value: -480 },
{ label: 'UTC-07:00', value: -420 },
{ label: 'UTC-06:00', value: -360 },
{ label: 'UTC-05:00', value: -300 },
{ label: 'UTC-04:30', value: -270 },
{ label: 'UTC-04:00', value: -240 },
{ label: 'UTC-03:30', value: -210 },
{ label: 'UTC-03:00', value: -180 },
{ label: 'UTC-02:00', value: -120 },
{ label: 'UTC-01:00', value: -60 },
{ label: 'UTC+00:00', value: 0 },
{ label: 'UTC+01:00', value: 60 },
{ label: 'UTC+02:00', value: 120 },
{ label: 'UTC+03:00', value: 180 },
{ label: 'UTC+03:30', value: 210 },
{ label: 'UTC+04:00', value: 240 },
{ label: 'UTC+04:30', value: 270 },
{ label: 'UTC+05:00', value: 300 },
{ label: 'UTC+05:30', value: 330 },
{ label: 'UTC+05:45', value: 345 },
{ label: 'UTC+06:00', value: 360 },
{ label: 'UTC+06:30', value: 390 },
{ label: 'UTC+07:00', value: 420 },
{ label: 'UTC+08:00', value: 480 },
{ label: 'UTC+08:45', value: 425 },
{ label: 'UTC+09:00', value: 540 },
{ label: 'UTC+09:30', value: 570 },
{ label: 'UTC+10:00', value: 600 },
{ label: 'UTC+10:30', value: 630 },
{ label: 'UTC+11:00', value: 660 },
{ label: 'UTC+11:30', value: 690 },
{ label: 'UTC+12:00', value: 720 },
{ label: 'UTC+12:45', value: 765 },
{ label: 'UTC+13:00', value: 780 },
{ label: 'UTC+14:00', value: 840 }
];
@Component({
selector: 'sqx-date-time-editor',
styleUrls: ['./date-time-editor.component.scss'],
@ -74,75 +29,75 @@ const TIMEZONES: any[] = [
})
export class DateTimeEditorComponent implements ControlValueAccessor, OnInit, AfterViewInit {
private picker: any;
private time: any;
private date: any;
private offset: number;
private timeValue: any | null = null;
private dateValue: any | null = null;
private suppressEvents = false;
private changeCallback: (value: any) => void = NOOP;
private touchedCallback: () => void = NOOP;
public get showTime() {
return this.mode === 'DateTime' || this.mode === 'DateTimeWithTimezone';
}
public get showTimezone() {
return this.mode === 'DateWithTimezone' || this.mode === 'DateTimeWithTimezone';
return this.mode === 'DateTime';
}
public timezones = TIMEZONES;
public timeControl = new FormControl();
public timeControl =
new FormControl();
public timeZoneControl =
new FormControl();
public isDisabled = false;
public dateControl = new FormControl();
@Input()
public mode: string;
@Input()
public enforceTime: boolean;
@ViewChild('dateInput')
public dateInput: ElementRef;
public ngOnInit() {
this.timeControl.valueChanges.subscribe(value => {
const time = moment(value, 'HH:mm:ss');
this.time = moment();
this.time.hours(time.hours()).minutes(time.minutes()).seconds(time.seconds());
if (!value || value.length === 0) {
this.timeValue = null;
} else {
this.timeValue = moment(value, 'HH:mm:ss');
}
this.updateValue();
});
this.timeZoneControl.valueChanges.subscribe(value => {
this.offset = value;
this.dateControl.valueChanges.subscribe(value => {
if (!value || value.length === 0) {
this.dateValue = null;
} else {
this.dateValue = moment(value, 'YYYY-MM-DD');
}
this.updateValue();
this.touched();
});
}
public writeValue(value: any) {
const parsed = (moment.parseZone(value) || moment());
if (!value || value.length === 0) {
this.timeValue = null;
this.dateValue = null;
} else {
const parsed = moment.parseZone(value);
this.time = moment(parsed);
this.date = moment(parsed);
this.dateValue = moment(parsed);
this.offset = parsed.utcOffset();
if (this.showTime) {
this.timeValue = moment(parsed);
}
}
this.updateControls();
}
public setDisabledState(isDisabled: boolean): void {
this.isDisabled = isDisabled;
if (isDisabled) {
this.dateControl.disable();
this.timeControl.disable();
this.timeZoneControl.disable();
} else {
this.dateControl.enable();
this.timeControl.enable();
this.timeZoneControl.enable();
}
}
@ -155,17 +110,9 @@ export class DateTimeEditorComponent implements ControlValueAccessor, OnInit, Af
}
public ngAfterViewInit() {
this.picker = new Pikaday({
field: this.dateInput.nativeElement,
format: 'YYYY-MM-DD',
this.picker = new Pikaday({ field: this.dateInput.nativeElement, format: 'YYYY-MM-DD',
onSelect: () => {
if (this.suppressEvents) {
return;
}
const date = this.picker.getMoment();
this.date.years(date.years()).months(date.months()).dates(date.dates());
this.dateValue = this.picker.getMoment();
this.updateValue();
this.touched();
@ -180,34 +127,43 @@ export class DateTimeEditorComponent implements ControlValueAccessor, OnInit, Af
}
private updateValue() {
let result = this.date.format('YYYY-MM-DD');
let result: string = null;
if (this.showTime) {
result += 'T';
result += this.time.format('HH:mm:ss');
}
if ((this.dateValue && !this.dateValue.isValid()) || (this.timeValue && !this.timeValue.isValid())) {
result = 'Invalid DateTime';
} else if (!this.dateValue && !this.timeValue) {
result = null;
} else {
result = this.dateValue.format('YYYY-MM-DD');
if (this.showTimezone) {
result += moment().utcOffset(this.offset).format('Z');
} else if (this.showTime) {
if (this.showTime && this.timeValue) {
result += 'T';
result += this.timeValue.format('HH:mm:ss');
result += 'Z';
} else if (this.enforceTime) {
result += 'T00:00:00Z';
}
}
console.error(result);
this.changeCallback(result);
}
private updateControls() {
if (!this.date) {
if (!this.dateValue) {
return;
}
this.suppressEvents = true;
this.timeControl.setValue(this.time.format('HH:mm'), { emitEvent: false });
this.timeZoneControl.setValue(this.offset, { emitEvent: false });
if (this.timeValue && this.timeValue.isValid()) {
this.timeControl.setValue(this.timeValue.format('HH:mm:ss'), { emitEvent: false });
}
if (this.dateValue && this.dateValue.isValid()) {
this.dateControl.setValue(this.dateValue.format('YYYY-MM-DD'), { emitEvent: false });
if (this.picker) {
this.picker.setMoment(this.date);
this.picker.setMoment(this.dateValue);
}
this.suppressEvents = false;

18
src/Squidex/app/framework/angular/validators.ts

@ -11,6 +11,8 @@ import {
Validators
} from '@angular/forms';
import { DateTime } from './../utils/date-time';
export module ValidatorsEx {
export function pattern(pattern: string | RegExp, message?: string): ValidatorFn {
if (!pattern) {
@ -47,6 +49,22 @@ export module ValidatorsEx {
};
}
export function validDateTime() {
return (control: AbstractControl): { [key: string]: any } => {
const v: string = control.value;
if (v) {
try {
DateTime.parseISO_UTC(v);
} catch (e) {
return { validdateTime: false };
}
}
return {};
};
}
export function between(minValue?: number, maxValue?: number) {
if (!minValue || !maxValue) {
return Validators.nullValidator;

1
src/Squidex/app/framework/utils/date-time.ts

@ -111,7 +111,6 @@ export class DateTime {
return new DateTime(parsedMoment.toDate());
} else {
throw `${value} is not a valid date time string`;
}
}

2
src/Squidex/app/shared/components/language-selector.component.ts

@ -35,7 +35,7 @@ export class LanguageSelectorComponent implements OnInit {
public selectedLanguageChanged = new EventEmitter<Language>();
public get isSmallMode(): boolean {
return this.languages && this.languages.length > 0 && this.languages.length <= 0;
return this.languages && this.languages.length > 0 && this.languages.length <= 3;
}
public get isLargeMode(): boolean {

22
src/Squidex/app/shared/services/schemas.service.ts

@ -40,6 +40,12 @@ export function createProperties(fieldType: string, values: Object | null = null
undefined, undefined, undefined, false, false, false, 'Checkbox',
undefined);
break;
case 'dateTime':
properties =
new DateTimeFieldPropertiesDto(
undefined, undefined, undefined, false, false, false, 'DateTime',
undefined, undefined, undefined);
break;
default:
throw 'Invalid properties type';
}
@ -140,6 +146,22 @@ export class StringFieldPropertiesDto extends FieldPropertiesDto {
}
}
export class DateTimeFieldPropertiesDto extends FieldPropertiesDto {
constructor(label: string | undefined, hints: string | undefined, placeholder: string | undefined,
isRequired: boolean,
isListField: boolean,
isLocalizable: boolean,
public readonly editor: string,
public readonly defaultValue?: string,
public readonly maxValue?: string,
public readonly minValue?: string
) {
super(label, hints, placeholder, isRequired, isListField, isLocalizable);
this['fieldType'] = 'dateTime';
}
}
export class BooleanFieldPropertiesDto extends FieldPropertiesDto {
constructor(label: string | undefined, hints: string | undefined, placeholder: string | undefined,
isRequired: boolean,

5
src/Squidex/app/theme/icomoon/demo-files/demo.css

@ -150,9 +150,12 @@ p {
font-size: 32px;
}
.fs2 {
font-size: 28px;
font-size: 32px;
}
.fs3 {
font-size: 28px;
}
.fs4 {
font-size: 32px;
}

169
src/Squidex/app/theme/icomoon/demo.html

@ -9,11 +9,30 @@
<link rel="stylesheet" href="style.css"></head>
<body>
<div class="bgc1 clearfix">
<h1 class="mhmm mvm"><span class="fgc1">Font Name:</span> icomoon <small class="fgc1">(Glyphs:&nbsp;53)</small></h1>
<h1 class="mhmm mvm"><span class="fgc1">Font Name:</span> icomoon <small class="fgc1">(Glyphs:&nbsp;54)</small></h1>
</div>
<div class="clearfix mhl ptl">
<h1 class="mvm mtn fgc1">Grid Size: 16</h1>
<h1 class="mvm mtn fgc1">Grid Size: 32</h1>
<div class="glyph fs1">
<div class="clearfix bshadow0 pbs">
<span class="icon-browser">
</span>
<span class="mls"> icon-browser</span>
</div>
<fieldset class="fs0 size1of1 clearfix hidden-false">
<input type="text" readonly value="e935" class="unit size1of2" />
<input type="text" maxlength="1" readonly value="&#xe935;" class="unitRight size1of2 talign-right" />
</fieldset>
<div class="fs0 bshadow0 clearfix hidden-true">
<span class="unit pvs fgc1">liga: </span>
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
</div>
<div class="clearfix mhl ptl">
<h1 class="mvm mtn fgc1">Grid Size: 16</h1>
<div class="glyph fs2">
<div class="clearfix bshadow0 pbs">
<span class="icon-unlocked">
@ -29,7 +48,7 @@
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs1">
<div class="glyph fs2">
<div class="clearfix bshadow0 pbs">
<span class="icon-lock">
@ -45,7 +64,7 @@
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs1">
<div class="glyph fs2">
<div class="clearfix bshadow0 pbs">
<span class="icon-reset">
@ -61,7 +80,7 @@
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs1">
<div class="glyph fs2">
<div class="clearfix bshadow0 pbs">
<span class="icon-pause">
@ -77,7 +96,7 @@
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs1">
<div class="glyph fs2">
<div class="clearfix bshadow0 pbs">
<span class="icon-play">
@ -93,7 +112,7 @@
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs1">
<div class="glyph fs2">
<div class="clearfix bshadow0 pbs">
<span class="icon-settings2">
@ -109,7 +128,7 @@
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs1">
<div class="glyph fs2">
<div class="clearfix bshadow0 pbs">
<span class="icon-bin2">
@ -128,7 +147,7 @@
</div>
<div class="clearfix mhl ptl">
<h1 class="mvm mtn fgc1">Grid Size: 14</h1>
<div class="glyph fs2">
<div class="glyph fs3">
<div class="clearfix bshadow0 pbs">
<span class="icon-angle-right">
@ -144,7 +163,7 @@
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs2">
<div class="glyph fs3">
<div class="clearfix bshadow0 pbs">
<span class="icon-user-o">
@ -160,7 +179,7 @@
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs2">
<div class="glyph fs3">
<div class="clearfix bshadow0 pbs">
<span class="icon-caret-right">
@ -176,7 +195,7 @@
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs2">
<div class="glyph fs3">
<div class="clearfix bshadow0 pbs">
<span class="icon-caret-left">
@ -192,7 +211,7 @@
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs2">
<div class="glyph fs3">
<div class="clearfix bshadow0 pbs">
<span class="icon-caret-up">
@ -208,7 +227,7 @@
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs2">
<div class="glyph fs3">
<div class="clearfix bshadow0 pbs">
<span class="icon-caret-down">
@ -224,7 +243,7 @@
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs2">
<div class="glyph fs3">
<div class="clearfix bshadow0 pbs">
<span class="icon-angle-up">
@ -240,7 +259,7 @@
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs2">
<div class="glyph fs3">
<div class="clearfix bshadow0 pbs">
<span class="icon-angle-down">
@ -256,7 +275,7 @@
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs2">
<div class="glyph fs3">
<div class="clearfix bshadow0 pbs">
<span class="icon-angle-left">
@ -275,7 +294,7 @@
</div>
<div class="clearfix mhl ptl">
<h1 class="mvm mtn fgc1">Grid Size: Unknown</h1>
<div class="glyph fs3">
<div class="glyph fs4">
<div class="clearfix bshadow0 pbs">
<span class="icon-activity">
@ -291,7 +310,7 @@
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs3">
<div class="glyph fs4">
<div class="clearfix bshadow0 pbs">
<span class="icon-history">
@ -307,7 +326,7 @@
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs3">
<div class="glyph fs4">
<div class="clearfix bshadow0 pbs">
<span class="icon-time">
@ -323,7 +342,7 @@
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs3">
<div class="glyph fs4">
<div class="clearfix bshadow0 pbs">
<span class="icon-add">
@ -339,7 +358,7 @@
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs3">
<div class="glyph fs4">
<div class="clearfix bshadow0 pbs">
<span class="icon-plus">
@ -355,7 +374,7 @@
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs3">
<div class="glyph fs4">
<div class="clearfix bshadow0 pbs">
<span class="icon-check-circle">
@ -371,7 +390,7 @@
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs3">
<div class="glyph fs4">
<div class="clearfix bshadow0 pbs">
<span class="icon-check-circle-filled">
@ -387,7 +406,7 @@
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs3">
<div class="glyph fs4">
<div class="clearfix bshadow0 pbs">
<span class="icon-close">
@ -403,7 +422,7 @@
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs3">
<div class="glyph fs4">
<div class="clearfix bshadow0 pbs">
<span class="icon-content">
@ -419,7 +438,7 @@
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs3">
<div class="glyph fs4">
<div class="clearfix bshadow0 pbs">
<span class="icon-control-checkbox">
@ -435,7 +454,7 @@
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs3">
<div class="glyph fs4">
<div class="clearfix bshadow0 pbs">
<span class="icon-control-dropdown">
@ -451,7 +470,7 @@
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs3">
<div class="glyph fs4">
<div class="clearfix bshadow0 pbs">
<span class="icon-control-input">
@ -467,7 +486,7 @@
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs3">
<div class="glyph fs4">
<div class="clearfix bshadow0 pbs">
<span class="icon-control-radio">
@ -483,7 +502,7 @@
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs3">
<div class="glyph fs4">
<div class="clearfix bshadow0 pbs">
<span class="icon-control-textarea">
@ -499,7 +518,7 @@
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs3">
<div class="glyph fs4">
<div class="clearfix bshadow0 pbs">
<span class="icon-control-toggle">
@ -515,7 +534,7 @@
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs3">
<div class="glyph fs4">
<div class="clearfix bshadow0 pbs">
<span class="icon-copy">
@ -531,7 +550,7 @@
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs3">
<div class="glyph fs4">
<div class="clearfix bshadow0 pbs">
<span class="icon-dashboard">
@ -547,7 +566,7 @@
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs3">
<div class="glyph fs4">
<div class="clearfix bshadow0 pbs">
<span class="icon-delete">
@ -563,7 +582,7 @@
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs3">
<div class="glyph fs4">
<div class="clearfix bshadow0 pbs">
<span class="icon-bin">
@ -579,7 +598,7 @@
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs3">
<div class="glyph fs4">
<div class="clearfix bshadow0 pbs">
<span class="icon-delete-filled">
@ -595,7 +614,7 @@
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs3">
<div class="glyph fs4">
<div class="clearfix bshadow0 pbs">
<span class="icon-document-delete">
@ -611,7 +630,7 @@
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs3">
<div class="glyph fs4">
<div class="clearfix bshadow0 pbs">
<span class="icon-document-disable">
@ -627,7 +646,7 @@
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs3">
<div class="glyph fs4">
<div class="clearfix bshadow0 pbs">
<span class="icon-document-publish">
@ -643,7 +662,7 @@
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs3">
<div class="glyph fs4">
<div class="clearfix bshadow0 pbs">
<span class="icon-drag">
@ -659,7 +678,7 @@
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs3">
<div class="glyph fs4">
<div class="clearfix bshadow0 pbs">
<span class="icon-filter">
@ -675,7 +694,7 @@
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs3">
<div class="glyph fs4">
<div class="clearfix bshadow0 pbs">
<span class="icon-help">
@ -691,7 +710,7 @@
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs3">
<div class="glyph fs4">
<div class="clearfix bshadow0 pbs">
<span class="icon-json">
@ -707,7 +726,7 @@
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs3">
<div class="glyph fs4">
<div class="clearfix bshadow0 pbs">
<span class="icon-location">
@ -723,7 +742,7 @@
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs3">
<div class="glyph fs4">
<div class="clearfix bshadow0 pbs">
<span class="icon-logo">
@ -739,7 +758,7 @@
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs3">
<div class="glyph fs4">
<div class="clearfix bshadow0 pbs">
<span class="icon-media">
@ -755,7 +774,7 @@
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs3">
<div class="glyph fs4">
<div class="clearfix bshadow0 pbs">
<span class="icon-more">
@ -771,7 +790,7 @@
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs3">
<div class="glyph fs4">
<div class="clearfix bshadow0 pbs">
<span class="icon-dots">
@ -787,7 +806,7 @@
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs3">
<div class="glyph fs4">
<div class="clearfix bshadow0 pbs">
<span class="icon-pencil">
@ -803,7 +822,7 @@
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs3">
<div class="glyph fs4">
<div class="clearfix bshadow0 pbs">
<span class="icon-reference">
@ -819,7 +838,7 @@
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs3">
<div class="glyph fs4">
<div class="clearfix bshadow0 pbs">
<span class="icon-schemas">
@ -835,7 +854,7 @@
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs3">
<div class="glyph fs4">
<div class="clearfix bshadow0 pbs">
<span class="icon-search">
@ -851,7 +870,7 @@
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs3">
<div class="glyph fs4">
<div class="clearfix bshadow0 pbs">
<span class="icon-settings">
@ -867,7 +886,7 @@
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs3">
<div class="glyph fs4">
<div class="clearfix bshadow0 pbs">
<span class="icon-type-boolean">
@ -883,7 +902,7 @@
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs3">
<div class="glyph fs4">
<div class="clearfix bshadow0 pbs">
<span class="icon-type-datetime">
@ -899,7 +918,39 @@
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs3">
<div class="glyph fs4">
<div class="clearfix bshadow0 pbs">
<span class="icon-type-date-time">
</span>
<span class="mls"> icon-type-date-time</span>
</div>
<fieldset class="fs0 size1of1 clearfix hidden-false">
<input type="text" readonly value="e925" class="unit size1of2" />
<input type="text" maxlength="1" readonly value="&#xe925;" class="unitRight size1of2 talign-right" />
</fieldset>
<div class="fs0 bshadow0 clearfix hidden-true">
<span class="unit pvs fgc1">liga: </span>
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs4">
<div class="clearfix bshadow0 pbs">
<span class="icon-type-dateTime">
</span>
<span class="mls"> icon-type-dateTime</span>
</div>
<fieldset class="fs0 size1of1 clearfix hidden-false">
<input type="text" readonly value="e925" class="unit size1of2" />
<input type="text" maxlength="1" readonly value="&#xe925;" class="unitRight size1of2 talign-right" />
</fieldset>
<div class="fs0 bshadow0 clearfix hidden-true">
<span class="unit pvs fgc1">liga: </span>
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs4">
<div class="clearfix bshadow0 pbs">
<span class="icon-type-number">
@ -915,7 +966,7 @@
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs3">
<div class="glyph fs4">
<div class="clearfix bshadow0 pbs">
<span class="icon-type-string">
@ -931,7 +982,7 @@
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs3">
<div class="glyph fs4">
<div class="clearfix bshadow0 pbs">
<span class="icon-user">

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

Binary file not shown.

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

@ -44,7 +44,7 @@
<glyph unicode="&#xe922;" glyph-name="search" d="M939.776-43.776c-27.2-27.008-71.232-27.008-98.368 0l-168.96 168.96c-66.176-38.464-142.016-62.080-224-62.080-247.744 0-448.448 200.832-448.448 448.448 0 247.744 200.704 448.448 448.448 448.448 247.68 0 448.512-200.704 448.512-448.448 0-115.136-44.672-218.944-115.904-298.304l158.656-158.656c27.008-27.136 27.008-71.168 0.064-98.368zM448.448 831.872c-176.896 0-320.32-143.36-320.32-320.32s143.424-320.32 320.32-320.32c176.96 0 320.384 143.36 320.384 320.32s-143.488 320.32-320.384 320.32z" />
<glyph unicode="&#xe923;" glyph-name="settings" d="M1019.11 519.245c-1.946 13.747-14.438 23.398-28.16 21.888-16.947-1.843-34.253 0.589-50.048 7.091-52.25 21.504-77.261 81.459-55.757 133.709 6.605 15.846 16.947 29.85 30.208 40.602 10.803 8.653 12.698 24.294 4.352 35.354-28.902 37.99-62.797 71.706-100.838 100.045-10.701 8.090-25.805 6.451-34.662-3.661-28.8-33.254-75.546-44.262-116.198-27.546-40.704 16.742-66.099 57.498-63.206 101.453 0.845 13.338-8.755 25.19-21.99 27.008-47.002 6.605-94.797 6.605-142.054-0.077-13.722-1.946-23.398-14.387-21.862-28.211 1.843-16.896-0.614-34.202-7.168-49.997-21.504-52.25-81.408-77.21-133.632-55.706-15.821 6.502-29.85 16.947-40.602 30.157-8.653 10.752-24.32 12.698-35.379 4.301-37.99-28.851-71.68-62.694-100.045-100.762-8.090-10.701-6.451-25.83 3.635-34.637 33.28-28.902 44.288-75.597 27.546-116.301-16.742-40.653-57.498-66.048-101.427-63.155-13.363 0.845-25.19-8.755-26.982-21.99-6.63-47.002-6.63-94.822 0.102-142.080 1.946-13.696 14.387-23.322 28.16-21.811 16.896 1.818 34.202-0.691 50.022-7.168 52.224-21.53 77.21-81.459 55.706-133.734-6.502-15.795-16.947-29.773-30.157-40.525-10.803-8.73-12.698-24.346-4.352-35.354 28.877-38.042 62.822-71.731 100.813-100.122 1.741-1.357 3.661-2.355 5.606-3.2 9.933-4.045 21.709-1.536 29.082 6.938 28.826 33.178 75.571 44.262 116.275 27.52 40.653-16.742 66.048-57.498 63.13-101.453-0.819-13.338 8.755-25.165 22.067-27.059 47.002-6.579 94.72-6.554 142.029 0.102 13.645 1.971 23.347 14.464 21.811 28.237-1.843 16.947 0.691 34.253 7.194 50.048 21.504 52.25 81.459 77.21 133.658 55.68 15.795-6.528 29.85-16.947 40.55-30.157 8.704-10.803 24.346-12.698 35.405-4.326 37.99 28.902 71.654 62.746 100.096 100.813 7.987 10.675 6.4 25.805-3.712 34.662-33.254 28.826-44.288 75.571-27.546 116.224 16.742 40.73 57.498 66.099 101.453 63.232 13.338-0.922 25.139 8.678 27.008 21.965 6.554 47.002 6.502 94.771-0.128 142.003zM971.059 405.99c-56.141-5.274-105.702-41.114-127.642-94.464s-12.058-113.613 24.090-156.902c-17.69-21.478-37.453-41.318-58.854-59.315-12.749 11.213-27.392 20.352-43.238 26.854-78.259 32.282-168.243-5.197-200.499-83.584-6.502-15.718-10.291-32.563-11.29-49.536-27.853-2.56-55.859-2.637-83.61-0.077-5.274 56.090-41.114 105.677-94.464 127.616-53.35 21.99-113.613 11.981-156.928-24.064-21.504 17.69-41.318 37.453-59.29 58.88 11.213 12.723 20.352 27.392 26.906 43.136 32.205 78.387-5.274 168.294-83.584 200.55-15.821 6.502-32.589 10.342-49.613 11.366-2.534 27.853-2.586 55.859 0 83.558 56.090 5.299 105.626 41.088 127.565 94.438 21.965 53.402 12.058 113.638-24.090 156.902 17.69 21.555 37.478 41.395 58.88 59.341 12.749-11.213 27.392-20.352 43.213-26.854 78.285-32.256 168.218 5.248 200.474 83.558 6.528 15.795 10.342 32.589 11.366 49.613 27.853 2.509 55.808 2.56 83.558 0 5.299-56.090 41.139-105.6 94.49-127.59 53.35-21.939 113.638-12.006 156.902 24.090 21.504-17.741 41.293-37.453 59.29-58.854-11.213-12.8-20.352-27.392-26.854-43.213-32.256-78.31 5.248-168.294 83.507-200.499 15.846-6.502 32.691-10.342 49.638-11.392 2.56-27.853 2.611-55.808 0.077-83.558zM512 652.8c-113.101 0-204.8-91.699-204.8-204.8 0-113.126 91.699-204.826 204.8-204.826s204.8 91.699 204.8 204.826c0 113.101-91.699 204.8-204.8 204.8zM512 294.374c-84.813 0-153.6 68.813-153.6 153.626 0 84.838 68.787 153.6 153.6 153.6 84.838 0 153.6-68.762 153.6-153.6 0-84.813-68.762-153.626-153.6-153.626z" />
<glyph unicode="&#xe924;" glyph-name="type-boolean" d="M77.005 857.395h128v-332.8c0-14.131 11.418-25.6 25.6-25.6 14.106 0 25.6 11.469 25.6 25.6v332.8h128c14.106 0 25.6 11.469 25.6 25.6 0 14.157-11.494 25.6-25.6 25.6h-307.2c-14.182 0-25.6-11.443-25.6-25.6 0-14.106 11.418-25.6 25.6-25.6zM947.405 243.021h-179.2v102.4h179.2c14.157 0 25.6 11.443 25.6 25.6s-11.443 25.6-25.6 25.6h-204.8c-14.182 0-25.6-11.443-25.6-25.6v-358.4c0-14.157 11.418-25.6 25.6-25.6 14.157 0 25.6 11.443 25.6 25.6v179.2h179.2c14.157 0 25.6 11.443 25.6 25.6s-11.494 25.6-25.6 25.6zM965.094 901.53c-9.958 9.933-26.112 9.933-36.045 0l-870.605-870.579c-9.958-9.984-9.958-26.086 0-36.045 10.010-9.984 26.112-9.984 36.045 0l870.605 870.579c9.958 9.933 9.958 26.086 0 36.045z" />
<glyph unicode="&#xe925;" glyph-name="type-datetime" d="M947.2 857.6h-128v25.6c0 14.131-11.469 25.6-25.6 25.6s-25.6-11.469-25.6-25.6v-25.6h-512v25.6c0 14.131-11.52 25.6-25.6 25.6s-25.6-11.469-25.6-25.6v-25.6h-128c-42.342 0-76.8-34.458-76.8-76.8v-716.8c0-42.342 34.458-76.8 76.8-76.8h870.4c42.342 0 76.8 34.458 76.8 76.8v716.8c0 42.342-34.458 76.8-76.8 76.8zM972.8 64c0-14.131-11.469-25.6-25.6-25.6h-870.4c-14.080 0-25.6 11.469-25.6 25.6v537.6h921.6v-537.6zM972.8 652.8h-921.6v128c0 14.080 11.52 25.6 25.6 25.6h128v-76.8c0-14.080 11.52-25.6 25.6-25.6s25.6 11.52 25.6 25.6v76.8h512v-76.8c0-14.080 11.469-25.6 25.6-25.6s25.6 11.52 25.6 25.6v76.8h128c14.131 0 25.6-11.52 25.6-25.6v-128zM332.8 448h51.2c14.080 0 25.6 11.52 25.6 25.6s-11.52 25.6-25.6 25.6h-51.2c-14.080 0-25.6-11.52-25.6-25.6s11.52-25.6 25.6-25.6zM486.4 448h51.2c14.131 0 25.6 11.52 25.6 25.6s-11.469 25.6-25.6 25.6h-51.2c-14.080 0-25.6-11.52-25.6-25.6s11.52-25.6 25.6-25.6zM640 448h51.2c14.131 0 25.6 11.52 25.6 25.6s-11.469 25.6-25.6 25.6h-51.2c-14.131 0-25.6-11.52-25.6-25.6s11.469-25.6 25.6-25.6zM793.6 448h51.2c14.131 0 25.6 11.52 25.6 25.6s-11.469 25.6-25.6 25.6h-51.2c-14.131 0-25.6-11.52-25.6-25.6s11.469-25.6 25.6-25.6zM179.2 345.6h51.2c14.080 0 25.6 11.469 25.6 25.6s-11.52 25.6-25.6 25.6h-51.2c-14.080 0-25.6-11.469-25.6-25.6s11.52-25.6 25.6-25.6zM332.8 345.6h51.2c14.080 0 25.6 11.469 25.6 25.6s-11.52 25.6-25.6 25.6h-51.2c-14.080 0-25.6-11.469-25.6-25.6s11.52-25.6 25.6-25.6zM486.4 345.6h51.2c14.131 0 25.6 11.469 25.6 25.6s-11.469 25.6-25.6 25.6h-51.2c-14.080 0-25.6-11.469-25.6-25.6s11.52-25.6 25.6-25.6zM640 345.6h51.2c14.131 0 25.6 11.469 25.6 25.6s-11.469 25.6-25.6 25.6h-51.2c-14.131 0-25.6-11.469-25.6-25.6s11.469-25.6 25.6-25.6zM793.6 345.6h51.2c14.131 0 25.6 11.469 25.6 25.6s-11.469 25.6-25.6 25.6h-51.2c-14.131 0-25.6-11.469-25.6-25.6s11.469-25.6 25.6-25.6zM179.2 243.2h51.2c14.080 0 25.6 11.469 25.6 25.6s-11.52 25.6-25.6 25.6h-51.2c-14.080 0-25.6-11.469-25.6-25.6s11.52-25.6 25.6-25.6zM332.8 243.2h51.2c14.080 0 25.6 11.469 25.6 25.6s-11.52 25.6-25.6 25.6h-51.2c-14.080 0-25.6-11.469-25.6-25.6s11.52-25.6 25.6-25.6zM486.4 243.2h51.2c14.131 0 25.6 11.469 25.6 25.6s-11.469 25.6-25.6 25.6h-51.2c-14.080 0-25.6-11.469-25.6-25.6s11.52-25.6 25.6-25.6zM640 243.2h51.2c14.131 0 25.6 11.469 25.6 25.6s-11.469 25.6-25.6 25.6h-51.2c-14.131 0-25.6-11.469-25.6-25.6s11.469-25.6 25.6-25.6zM793.6 243.2h51.2c14.131 0 25.6 11.469 25.6 25.6s-11.469 25.6-25.6 25.6h-51.2c-14.131 0-25.6-11.469-25.6-25.6s11.469-25.6 25.6-25.6zM179.2 140.8h51.2c14.080 0 25.6 11.469 25.6 25.6s-11.52 25.6-25.6 25.6h-51.2c-14.080 0-25.6-11.469-25.6-25.6s11.52-25.6 25.6-25.6zM332.8 140.8h51.2c14.080 0 25.6 11.469 25.6 25.6s-11.52 25.6-25.6 25.6h-51.2c-14.080 0-25.6-11.469-25.6-25.6s11.52-25.6 25.6-25.6zM486.4 140.8h51.2c14.131 0 25.6 11.469 25.6 25.6s-11.469 25.6-25.6 25.6h-51.2c-14.080 0-25.6-11.469-25.6-25.6s11.52-25.6 25.6-25.6zM640 140.8h51.2c14.131 0 25.6 11.469 25.6 25.6s-11.469 25.6-25.6 25.6h-51.2c-14.131 0-25.6-11.469-25.6-25.6s11.469-25.6 25.6-25.6zM793.6 140.8h51.2c14.131 0 25.6 11.469 25.6 25.6s-11.469 25.6-25.6 25.6h-51.2c-14.131 0-25.6-11.469-25.6-25.6s11.469-25.6 25.6-25.6z" />
<glyph unicode="&#xe925;" glyph-name="type-datetime, type-date-time, type-dateTime" d="M947.2 857.6h-128v25.6c0 14.131-11.469 25.6-25.6 25.6s-25.6-11.469-25.6-25.6v-25.6h-512v25.6c0 14.131-11.52 25.6-25.6 25.6s-25.6-11.469-25.6-25.6v-25.6h-128c-42.342 0-76.8-34.458-76.8-76.8v-716.8c0-42.342 34.458-76.8 76.8-76.8h870.4c42.342 0 76.8 34.458 76.8 76.8v716.8c0 42.342-34.458 76.8-76.8 76.8zM972.8 64c0-14.131-11.469-25.6-25.6-25.6h-870.4c-14.080 0-25.6 11.469-25.6 25.6v537.6h921.6v-537.6zM972.8 652.8h-921.6v128c0 14.080 11.52 25.6 25.6 25.6h128v-76.8c0-14.080 11.52-25.6 25.6-25.6s25.6 11.52 25.6 25.6v76.8h512v-76.8c0-14.080 11.469-25.6 25.6-25.6s25.6 11.52 25.6 25.6v76.8h128c14.131 0 25.6-11.52 25.6-25.6v-128zM332.8 448h51.2c14.080 0 25.6 11.52 25.6 25.6s-11.52 25.6-25.6 25.6h-51.2c-14.080 0-25.6-11.52-25.6-25.6s11.52-25.6 25.6-25.6zM486.4 448h51.2c14.131 0 25.6 11.52 25.6 25.6s-11.469 25.6-25.6 25.6h-51.2c-14.080 0-25.6-11.52-25.6-25.6s11.52-25.6 25.6-25.6zM640 448h51.2c14.131 0 25.6 11.52 25.6 25.6s-11.469 25.6-25.6 25.6h-51.2c-14.131 0-25.6-11.52-25.6-25.6s11.469-25.6 25.6-25.6zM793.6 448h51.2c14.131 0 25.6 11.52 25.6 25.6s-11.469 25.6-25.6 25.6h-51.2c-14.131 0-25.6-11.52-25.6-25.6s11.469-25.6 25.6-25.6zM179.2 345.6h51.2c14.080 0 25.6 11.469 25.6 25.6s-11.52 25.6-25.6 25.6h-51.2c-14.080 0-25.6-11.469-25.6-25.6s11.52-25.6 25.6-25.6zM332.8 345.6h51.2c14.080 0 25.6 11.469 25.6 25.6s-11.52 25.6-25.6 25.6h-51.2c-14.080 0-25.6-11.469-25.6-25.6s11.52-25.6 25.6-25.6zM486.4 345.6h51.2c14.131 0 25.6 11.469 25.6 25.6s-11.469 25.6-25.6 25.6h-51.2c-14.080 0-25.6-11.469-25.6-25.6s11.52-25.6 25.6-25.6zM640 345.6h51.2c14.131 0 25.6 11.469 25.6 25.6s-11.469 25.6-25.6 25.6h-51.2c-14.131 0-25.6-11.469-25.6-25.6s11.469-25.6 25.6-25.6zM793.6 345.6h51.2c14.131 0 25.6 11.469 25.6 25.6s-11.469 25.6-25.6 25.6h-51.2c-14.131 0-25.6-11.469-25.6-25.6s11.469-25.6 25.6-25.6zM179.2 243.2h51.2c14.080 0 25.6 11.469 25.6 25.6s-11.52 25.6-25.6 25.6h-51.2c-14.080 0-25.6-11.469-25.6-25.6s11.52-25.6 25.6-25.6zM332.8 243.2h51.2c14.080 0 25.6 11.469 25.6 25.6s-11.52 25.6-25.6 25.6h-51.2c-14.080 0-25.6-11.469-25.6-25.6s11.52-25.6 25.6-25.6zM486.4 243.2h51.2c14.131 0 25.6 11.469 25.6 25.6s-11.469 25.6-25.6 25.6h-51.2c-14.080 0-25.6-11.469-25.6-25.6s11.52-25.6 25.6-25.6zM640 243.2h51.2c14.131 0 25.6 11.469 25.6 25.6s-11.469 25.6-25.6 25.6h-51.2c-14.131 0-25.6-11.469-25.6-25.6s11.469-25.6 25.6-25.6zM793.6 243.2h51.2c14.131 0 25.6 11.469 25.6 25.6s-11.469 25.6-25.6 25.6h-51.2c-14.131 0-25.6-11.469-25.6-25.6s11.469-25.6 25.6-25.6zM179.2 140.8h51.2c14.080 0 25.6 11.469 25.6 25.6s-11.52 25.6-25.6 25.6h-51.2c-14.080 0-25.6-11.469-25.6-25.6s11.52-25.6 25.6-25.6zM332.8 140.8h51.2c14.080 0 25.6 11.469 25.6 25.6s-11.52 25.6-25.6 25.6h-51.2c-14.080 0-25.6-11.469-25.6-25.6s11.52-25.6 25.6-25.6zM486.4 140.8h51.2c14.131 0 25.6 11.469 25.6 25.6s-11.469 25.6-25.6 25.6h-51.2c-14.080 0-25.6-11.469-25.6-25.6s11.52-25.6 25.6-25.6zM640 140.8h51.2c14.131 0 25.6 11.469 25.6 25.6s-11.469 25.6-25.6 25.6h-51.2c-14.131 0-25.6-11.469-25.6-25.6s11.469-25.6 25.6-25.6zM793.6 140.8h51.2c14.131 0 25.6 11.469 25.6 25.6s-11.469 25.6-25.6 25.6h-51.2c-14.131 0-25.6-11.469-25.6-25.6s11.469-25.6 25.6-25.6z" />
<glyph unicode="&#xe926;" glyph-name="type-number" d="M256 294.4h-76.8v332.8c0 14.131-11.469 25.6-25.6 25.6h-76.8c-14.131 0-25.6-11.469-25.6-25.6s11.469-25.6 25.6-25.6h51.2v-307.2h-76.8c-14.131 0-25.6-11.469-25.6-25.6s11.469-25.6 25.6-25.6h204.8c14.131 0 25.6 11.469 25.6 25.6s-11.469 25.6-25.6 25.6zM614.4 652.8h-204.8c-14.131 0-25.6-11.469-25.6-25.6s11.469-25.6 25.6-25.6h179.2v-128h-179.2c-14.131 0-25.6-11.469-25.6-25.6v-179.2c0-14.131 11.469-25.6 25.6-25.6h204.8c14.131 0 25.6 11.469 25.6 25.6s-11.469 25.6-25.6 25.6h-179.2v128h179.2c14.131 0 25.6 11.469 25.6 25.6v179.2c0 14.131-11.469 25.6-25.6 25.6zM972.8 652.8h-204.8c-14.131 0-25.6-11.469-25.6-25.6s11.469-25.6 25.6-25.6h179.2v-128h-179.2c-14.131 0-25.6-11.469-25.6-25.6s11.469-25.6 25.6-25.6h179.2v-128h-179.2c-14.131 0-25.6-11.469-25.6-25.6s11.469-25.6 25.6-25.6h204.8c14.131 0 25.6 11.469 25.6 25.6v358.4c0 14.131-11.469 25.6-25.6 25.6z" />
<glyph unicode="&#xe927;" glyph-name="type-string" d="M870.4 38.4h-716.8c-14.131 0-25.6-11.443-25.6-25.6s11.469-25.6 25.6-25.6h716.8c14.157 0 25.6 11.443 25.6 25.6s-11.443 25.6-25.6 25.6zM194.688 142.848c13.030-5.555 28.083 0.461 33.613 13.44l125.030 291.712h317.338l125.005-291.712c4.173-9.677 13.568-15.488 23.526-15.488 3.405 0 6.81 0.64 10.112 2.048 13.005 5.606 18.995 20.659 13.44 33.638l-131.61 306.944c-0.051 0.051-0.051 0.154-0.102 0.205l-175.488 409.6c-4.045 9.472-13.312 15.565-23.552 15.565s-19.507-6.093-23.552-15.514l-175.488-409.6c-0.051-0.051-0.051-0.154-0.102-0.205l-131.61-306.97c-5.53-13.005 0.461-28.058 13.44-33.664zM512 818.227l136.704-319.027h-273.408l136.704 319.027z" />
<glyph unicode="&#xe928;" glyph-name="user" d="M955.221 112c0 0.109 10.752 0 0 0-52.751 161.392-240.461 224-443.178 224-202.269 0-389.979-63.392-443.066-224-11.2 0.109 0 1.232 0 0 0-61.936 49.615-112 110.654-112h664.823c61.151 0 110.766 50.064 110.766 112zM290.399 672c0-123.648 99.231-336 221.645-336s221.645 212.352 221.645 336c0 123.648-99.231 224-221.645 224s-221.645-100.352-221.645-224z" />
@ -60,4 +60,5 @@
<glyph unicode="&#xe932;" glyph-name="user-o" d="M512 886.857c-131.696 0-239.125-107.4-239.125-239 0-65.8 24.831-146.717 65.375-215.25 19.653-33.221 43.902-63.853 71.75-87.125-59.423-7.524-122.009-9.415-172.125-32-79.809-35.967-144.343-94.74-172.375-178.625-1.5-9.499 0 0-1.5-9v-0.499c0-73.995 60.563-134.501 134.375-134.501h627.125c73.888 0 134.5 60.506 134.5 134.5l-1.5 9.375c-27.845 84.263-92.273 143.119-172.125 179-50.17 22.544-112.844 24.421-172.375 31.875 27.792 23.26 52.002 53.831 71.625 87 40.544 68.533 65.375 149.45 65.375 215.25 0 131.6-107.304 239-239 239zM512 826.857c99.241 0 179-79.875 179-179 0-49.562-21.877-125.381-57-184.75s-81.435-98.75-122-98.75c-40.565 0-86.877 39.381-122 98.75s-57.125 135.188-57.125 184.75c0 99.125 79.884 179 179.125 179zM512 304.357c92.551 0 180.829-14.406 249.75-45.375 66.784-30.009 113.649-74.724 136.5-137.75-2.447-39.259-32.9-70.375-72.75-70.375h-627.125c-39.678 0-70.116 31.051-72.625 70.25 22.978 62.705 69.953 107.523 136.75 137.625 68.937 31.067 157.205 45.625 249.5 45.625z" />
<glyph unicode="&#xe933;" glyph-name="unlocked" d="M768 896c105.87 0 192-86.13 192-192v-192h-128v192c0 35.29-28.71 64-64 64h-128c-35.29 0-64-28.71-64-64v-192h16c26.4 0 48-21.6 48-48v-480c0-26.4-21.6-48-48-48h-544c-26.4 0-48 21.6-48 48v480c0 26.4 21.6 48 48 48h400v192c0 105.87 86.13 192 192 192h128z" />
<glyph unicode="&#xe934;" glyph-name="lock" d="M592 512h-16v192c0 105.87-86.13 192-192 192h-128c-105.87 0-192-86.13-192-192v-192h-16c-26.4 0-48-21.6-48-48v-480c0-26.4 21.6-48 48-48h544c26.4 0 48 21.6 48 48v480c0 26.4-21.6 48-48 48zM192 704c0 35.29 28.71 64 64 64h128c35.29 0 64-28.71 64-64v-192h-256v192z" />
<glyph unicode="&#xe935;" glyph-name="browser" horiz-adv-x="1344" d="M1328 640c-8.832 0-16-7.168-16-16v-640c0-8.832-7.168-16-16-16h-1248c-8.832 0-16 7.168-16 16v640c0 8.832-7.168 16-16 16s-16-7.168-16-16v-640c0-26.464 21.536-48 48-48h1248c26.464 0 48 21.536 48 48v640c0 8.832-7.168 16-16 16zM1296 960h-1248c-26.464 0-48-21.536-48-48v-192c0-8.832 7.168-16 16-16h1312c8.832 0 16 7.168 16 16v192c0 26.464-21.536 48-48 48zM1312 736h-1280v176c0 8.832 7.168 16 16 16h1248c8.832 0 16-7.168 16-16v-176zM560 64c8.832 0 16 7.168 16 16v512c0 8.832-7.168 16-16 16h-416c-8.832 0-16-7.168-16-16v-512c0-8.832 7.168-16 16-16h416zM160 576h384v-480h-384v480zM720 480h480c8.832 0 16 7.168 16 16s-7.168 16-16 16h-480c-8.832 0-16-7.168-16-16s7.168-16 16-16zM720 320h480c8.832 0 16 7.168 16 16s-7.168 16-16 16h-480c-8.832 0-16-7.168-16-16s7.168-16 16-16zM720 160h480c8.832 0 16 7.168 16 16s-7.168 16-16 16h-480c-8.832 0-16-7.168-16-16s7.168-16 16-16zM96 832c0-17.673 14.327-32 32-32s32 14.327 32 32c0 17.673-14.327 32-32 32s-32-14.327-32-32zM224 832c0-17.673 14.327-32 32-32s32 14.327 32 32c0 17.673-14.327 32-32 32s-32-14.327-32-32zM352 832c0-17.673 14.327-32 32-32s32 14.327 32 32c0 17.673-14.327 32-32 32s-32-14.327-32-32z" />
</font></defs></svg>

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 44 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.

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

@ -1,6 +1,39 @@
{
"IcoMoonType": "selection",
"icons": [
{
"icon": {
"paths": [
"M1328 320c-8.832 0-16 7.168-16 16v640c0 8.832-7.168 16-16 16h-1248c-8.832 0-16-7.168-16-16v-640c0-8.832-7.168-16-16-16s-16 7.168-16 16v640c0 26.464 21.536 48 48 48h1248c26.464 0 48-21.536 48-48v-640c0-8.832-7.168-16-16-16zM1296 0h-1248c-26.464 0-48 21.536-48 48v192c0 8.832 7.168 16 16 16h1312c8.832 0 16-7.168 16-16v-192c0-26.464-21.536-48-48-48zM1312 224h-1280v-176c0-8.832 7.168-16 16-16h1248c8.832 0 16 7.168 16 16v176zM560 896c8.832 0 16-7.168 16-16v-512c0-8.832-7.168-16-16-16h-416c-8.832 0-16 7.168-16 16v512c0 8.832 7.168 16 16 16h416zM160 384h384v480h-384v-480zM720 480h480c8.832 0 16-7.168 16-16s-7.168-16-16-16h-480c-8.832 0-16 7.168-16 16s7.168 16 16 16zM720 640h480c8.832 0 16-7.168 16-16s-7.168-16-16-16h-480c-8.832 0-16 7.168-16 16s7.168 16 16 16zM720 800h480c8.832 0 16-7.168 16-16s-7.168-16-16-16h-480c-8.832 0-16 7.168-16 16s7.168 16 16 16zM96 128c0 17.673 14.327 32 32 32s32-14.327 32-32c0-17.673-14.327-32-32-32s-32 14.327-32 32zM224 128c0 17.673 14.327 32 32 32s32-14.327 32-32c0-17.673-14.327-32-32-32s-32 14.327-32 32zM352 128c0 17.673 14.327 32 32 32s32-14.327 32-32c0-17.673-14.327-32-32-32s-32 14.327-32 32z"
],
"attrs": [
{}
],
"width": 1344,
"isMulticolor": false,
"isMulticolor2": false,
"tags": [
"browser",
"window",
"software",
"program"
],
"grid": 32
},
"attrs": [
{}
],
"properties": {
"order": 1,
"id": 0,
"prevSize": 32,
"code": 59701,
"name": "browser"
},
"setIdx": 0,
"setId": 3,
"iconIdx": 0
},
{
"icon": {
"paths": [
@ -27,7 +60,7 @@
"code": 59699,
"name": "unlocked"
},
"setIdx": 0,
"setIdx": 1,
"setId": 2,
"iconIdx": 0
},
@ -59,7 +92,7 @@
"code": 59700,
"name": "lock"
},
"setIdx": 0,
"setIdx": 1,
"setId": 2,
"iconIdx": 1
},
@ -98,7 +131,7 @@
"code": 59694,
"name": "reset"
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 9
},
@ -128,7 +161,7 @@
"code": 59695,
"name": "pause"
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 10
},
@ -158,7 +191,7 @@
"code": 59696,
"name": "play"
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 11
},
@ -193,7 +226,7 @@
"code": 59693,
"name": "settings2"
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 12
},
@ -230,7 +263,7 @@
"prevSize": 32,
"code": 59650
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 13
},
@ -260,7 +293,7 @@
"code": 59697,
"name": "angle-right"
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 0
},
@ -289,7 +322,7 @@
"prevSize": 28,
"code": 59698
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 1
},
@ -319,7 +352,7 @@
"code": 59689,
"name": "caret-right"
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 2
},
@ -349,7 +382,7 @@
"code": 59690,
"name": "caret-left"
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 3
},
@ -379,7 +412,7 @@
"code": 59691,
"name": "caret-up"
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 4
},
@ -409,7 +442,7 @@
"code": 59692,
"name": "caret-down"
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 5
},
@ -439,7 +472,7 @@
"code": 59651,
"name": "angle-up"
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 6
},
@ -469,7 +502,7 @@
"code": 59648,
"name": "angle-down"
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 7
},
@ -499,7 +532,7 @@
"code": 59649,
"name": "angle-left"
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 8
},
@ -528,7 +561,7 @@
"prevSize": 32,
"code": 59652
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 14
},
@ -557,7 +590,7 @@
"prevSize": 32,
"code": 59653
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 15
},
@ -586,7 +619,7 @@
"prevSize": 32,
"code": 59654
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 16
},
@ -615,7 +648,7 @@
"prevSize": 32,
"code": 59655
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 17
},
@ -644,7 +677,7 @@
"prevSize": 32,
"code": 59656
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 18
},
@ -673,7 +706,7 @@
"prevSize": 32,
"code": 59657
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 19
},
@ -702,7 +735,7 @@
"prevSize": 32,
"code": 59658
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 20
},
@ -731,7 +764,7 @@
"prevSize": 32,
"code": 59659
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 21
},
@ -760,7 +793,7 @@
"prevSize": 32,
"code": 59660
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 22
},
@ -789,7 +822,7 @@
"prevSize": 32,
"code": 59661
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 23
},
@ -818,7 +851,7 @@
"prevSize": 32,
"code": 59662
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 24
},
@ -847,7 +880,7 @@
"prevSize": 32,
"code": 59663
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 25
},
@ -876,7 +909,7 @@
"prevSize": 32,
"code": 59664
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 26
},
@ -905,7 +938,7 @@
"prevSize": 32,
"code": 59665
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 27
},
@ -934,7 +967,7 @@
"prevSize": 32,
"code": 59666
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 28
},
@ -963,7 +996,7 @@
"prevSize": 32,
"code": 59667
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 29
},
@ -992,7 +1025,7 @@
"prevSize": 32,
"code": 59668
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 30
},
@ -1021,7 +1054,7 @@
"prevSize": 32,
"code": 59669
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 31
},
@ -1050,7 +1083,7 @@
"prevSize": 32,
"code": 59670
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 32
},
@ -1079,7 +1112,7 @@
"prevSize": 32,
"code": 59671
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 33
},
@ -1108,7 +1141,7 @@
"prevSize": 32,
"code": 59672
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 34
},
@ -1137,7 +1170,7 @@
"prevSize": 32,
"code": 59673
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 35
},
@ -1166,7 +1199,7 @@
"prevSize": 32,
"code": 59674
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 36
},
@ -1195,7 +1228,7 @@
"prevSize": 32,
"code": 59675
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 37
},
@ -1224,7 +1257,7 @@
"prevSize": 32,
"code": 59676
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 38
},
@ -1253,7 +1286,7 @@
"prevSize": 32,
"code": 59677
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 39
},
@ -1282,7 +1315,7 @@
"prevSize": 32,
"code": 59678
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 40
},
@ -1311,7 +1344,7 @@
"prevSize": 32,
"code": 59679
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 41
},
@ -1340,7 +1373,7 @@
"prevSize": 32,
"code": 59680
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 42
},
@ -1369,7 +1402,7 @@
"prevSize": 32,
"code": 59681
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 43
},
@ -1398,7 +1431,7 @@
"prevSize": 32,
"code": 59682
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 44
},
@ -1427,7 +1460,7 @@
"prevSize": 32,
"code": 59683
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 45
},
@ -1456,7 +1489,7 @@
"prevSize": 32,
"code": 59684
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 46
},
@ -1481,11 +1514,11 @@
"properties": {
"order": 24,
"id": 3,
"name": "type-datetime",
"name": "type-datetime, type-date-time, type-dateTime",
"prevSize": 32,
"code": 59685
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 47
},
@ -1514,7 +1547,7 @@
"prevSize": 32,
"code": 59686
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 48
},
@ -1543,7 +1576,7 @@
"prevSize": 32,
"code": 59687
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 49
},
@ -1572,7 +1605,7 @@
"prevSize": 32,
"code": 59688
},
"setIdx": 1,
"setIdx": 2,
"setId": 1,
"iconIdx": 50
}

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

@ -1,10 +1,10 @@
@font-face {
font-family: 'icomoon';
src: url('fonts/icomoon.eot?1qun2u');
src: url('fonts/icomoon.eot?1qun2u#iefix') format('embedded-opentype'),
url('fonts/icomoon.ttf?1qun2u') format('truetype'),
url('fonts/icomoon.woff?1qun2u') format('woff'),
url('fonts/icomoon.svg?1qun2u#icomoon') format('svg');
src: url('fonts/icomoon.eot?7ja4lm');
src: url('fonts/icomoon.eot?7ja4lm#iefix') format('embedded-opentype'),
url('fonts/icomoon.ttf?7ja4lm') format('truetype'),
url('fonts/icomoon.woff?7ja4lm') format('woff'),
url('fonts/icomoon.svg?7ja4lm#icomoon') format('svg');
font-weight: normal;
font-style: normal;
}
@ -24,6 +24,9 @@
-moz-osx-font-smoothing: grayscale;
}
.icon-browser:before {
content: "\e935";
}
.icon-unlocked:before {
content: "\e933";
}
@ -189,6 +192,12 @@
.icon-type-datetime:before {
content: "\e925";
}
.icon-type-date-time:before {
content: "\e925";
}
.icon-type-dateTime:before {
content: "\e925";
}
.icon-type-number:before {
content: "\e926";
}

1
tests/Squidex.Core.Tests/Schemas/DateTimeFieldTests.cs

@ -6,7 +6,6 @@
// All rights reserved.
// ==========================================================================
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using FluentAssertions;

24
tests/Squidex.Core.Tests/Schemas/SchemaTests.cs

@ -270,20 +270,24 @@ namespace Squidex.Core.Schemas
Assert.NotNull(edmModel);
}
private Schema BuildMixedSchema()
private static Schema BuildMixedSchema()
{
var allowedValues = new[] { "1", "2" }.ToImmutableList();
var schema =
Schema.Create("user", new SchemaProperties { Hints = "The User" })
.AddOrUpdateField(new StringField(1, "firstName",
new StringFieldProperties { Label = "FirstName", IsLocalizable = true, IsRequired = true, AllowedValues = new[] { "1", "2" }.ToImmutableList() }))
.AddOrUpdateField(new StringField(2, "lastName",
new StringFieldProperties { Hints = "Last Name" }))
.AddOrUpdateField(new BooleanField(3, "admin",
.AddOrUpdateField(new StringField(1, "my-string1",
new StringFieldProperties { Label = "My String1", IsLocalizable = true, IsRequired = true, AllowedValues = allowedValues }))
.AddOrUpdateField(new StringField(2, "my-string2",
new StringFieldProperties { Hints = "My String1" }))
.AddOrUpdateField(new NumberField(3, "my-number",
new NumberFieldProperties { MinValue = 1, MaxValue = 10 }))
.AddOrUpdateField(new BooleanField(4, "my-boolean",
new BooleanFieldProperties()))
.AddOrUpdateField(new DateTimeField(4, "birtday",
new DateTimeFieldProperties()))
.AddOrUpdateField(new NumberField(5, "age",
new NumberFieldProperties { MinValue = 1, MaxValue = 10 }));
.AddOrUpdateField(new DateTimeField(5, "my-datetime",
new DateTimeFieldProperties { Editor = DateTimeFieldEditor.DateTime }))
.AddOrUpdateField(new DateTimeField(6, "my-date",
new DateTimeFieldProperties { Editor = DateTimeFieldEditor.Date }));
return schema;
}

5
tests/Squidex.Core.Tests/Schemas/SchemaValidationTests.cs

@ -6,7 +6,6 @@
// All rights reserved.
// ==========================================================================
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using FluentAssertions;
@ -297,9 +296,9 @@ namespace Squidex.Core.Schemas
.AddOrUpdateField(
new StringField(1, "my-string", new StringFieldProperties { DefaultValue = "EN-String", IsLocalizable = true }))
.AddOrUpdateField(
new BooleanField(2, "my-boolean", new BooleanFieldProperties { DefaultValue = true }))
new NumberField(2, "my-number", new NumberFieldProperties { DefaultValue = 123 }))
.AddOrUpdateField(
new NumberField(3, "my-number", new NumberFieldProperties { DefaultValue = 123 }))
new BooleanField(3, "my-boolean", new BooleanFieldProperties { DefaultValue = true }))
.AddOrUpdateField(
new DateTimeField(4, "my-datetime", new DateTimeFieldProperties { DefaultValue = now }));

32
tests/Squidex.Infrastructure.Tests/CQRS/Commands/EnrichWithTimestampHandlerTests.cs

@ -6,8 +6,9 @@
// All rights reserved.
// ==========================================================================
using System;
using System.Threading.Tasks;
using Moq;
using NodaTime;
using Xunit;
namespace Squidex.Infrastructure.CQRS.Commands
@ -20,46 +21,37 @@ namespace Squidex.Infrastructure.CQRS.Commands
private sealed class MyTimestampCommand : ITimestampCommand
{
public DateTime Timestamp { get; set; }
public Instant Timestamp { get; set; }
}
private readonly Mock<IClock> clock = new Mock<IClock>();
[Fact]
public async Task Should_set_timestamp_for_timestamp_command()
{
var utc = DateTime.Today;
var sut = new EnrichWithTimestampHandler(() => utc);
var command = new MyTimestampCommand();
var utc = Instant.FromUnixTimeSeconds(1000);
var sut = new EnrichWithTimestampHandler(clock.Object);
var result = await sut.HandleAsync(new CommandContext(command));
Assert.False(result);
Assert.Equal(utc, command.Timestamp);
}
[Fact]
public async Task Should_set_with_now_datetime_for_timestamp_command()
{
var now = DateTime.UtcNow;
var sut = new EnrichWithTimestampHandler();
clock.Setup(x => x.GetCurrentInstant()).Returns(utc);
var command = new MyTimestampCommand();
var result = await sut.HandleAsync(new CommandContext(command));
Assert.False(result);
Assert.True(command.Timestamp >= now && command.Timestamp <= DateTime.UtcNow);
Assert.Equal(utc, command.Timestamp);
}
[Fact]
public async Task Should_do_nothing_for_normal_command()
{
var utc = DateTime.Today;
var sut = new EnrichWithTimestampHandler(() => utc);
var sut = new EnrichWithTimestampHandler(clock.Object);
var result = await sut.HandleAsync(new CommandContext(new MyNormalCommand()));
Assert.False(result);
clock.Verify(x => x.GetCurrentInstant(), Times.Never());
}
}
}

9
tests/Squidex.Infrastructure.Tests/Reflection/SimpleMapperTests.cs

@ -7,6 +7,7 @@
// ==========================================================================
using System;
using NodaTime;
using Xunit;
// ReSharper disable UnusedParameter.Local
@ -17,14 +18,14 @@ namespace Squidex.Infrastructure.Reflection
{
public class MyClass1Base
{
public Guid MappedGuid { get; set; }
public string MappedString { get; set; }
public string MappedNull { get; set; }
public long MappedNumber { get; set; }
public Guid MappedGuid { get; set; }
public long WrongType1 { get; set; }
public long WrongType2 { get; set; }
@ -53,9 +54,9 @@ namespace Squidex.Infrastructure.Reflection
get { return "Value"; }
}
public DateTime WrongType1 { get; set; }
public Instant WrongType1 { get; set; }
public TimeSpan WrongType2 { get; set; }
public Duration WrongType2 { get; set; }
}
[Fact]

4
tests/Squidex.Write.Tests/Apps/AppCommandHandlerTests.cs

@ -139,9 +139,7 @@ namespace Squidex.Write.Apps
CreateApp();
var timestamp = DateTime.Today;
var context = CreateContextForCommand(new AttachClient { Id = clientName, Timestamp = timestamp });
var context = CreateContextForCommand(new AttachClient { Id = clientName });
await TestUpdate(app, async _ =>
{

4
tests/Squidex.Write.Tests/Apps/AppDomainObjectTests.cs

@ -218,11 +218,9 @@ namespace Squidex.Write.Apps
[Fact]
public void AttachClient_should_create_events()
{
var now = DateTime.Today;
CreateApp();
sut.AttachClient(CreateCommand(new AttachClient { Id = clientId, Timestamp = now }), clientSecret);
sut.AttachClient(CreateCommand(new AttachClient { Id = clientId }), clientSecret);
sut.GetUncomittedEvents()
.ShouldHaveSameEvents(

2
tools/GenerateLanguages/Program.cs

@ -24,7 +24,7 @@ namespace GenerateLanguages
var writer = new StringWriter();
writer.WriteLine("// ==========================================================================");
writer.WriteLine("// Langauges.cs");
writer.WriteLine("// Languages.cs");
writer.WriteLine("// Squidex Headless CMS");
writer.WriteLine("// ==========================================================================");
writer.WriteLine("// Copyright (c) Squidex Group");

Loading…
Cancel
Save