diff --git a/Squidex.sln b/Squidex.sln index bbe10118b..9353d4689 100644 --- a/Squidex.sln +++ b/Squidex.sln @@ -361,7 +361,7 @@ Global {6A811927-3C37-430A-90F4-503E37123956} = {8CF53B92-5EB1-461D-98F8-70DA9B603FBF} {D7166C56-178A-4457-B56A-C615C7450DEE} = {8CF53B92-5EB1-461D-98F8-70DA9B603FBF} {C1E5BBB6-6B6A-4DE5-B19D-0538304DE343} = {8CF53B92-5EB1-461D-98F8-70DA9B603FBF} - {945871B1-77B8-43FB-B53C-27CF385AB756} = {4C6B06C2-6D77-4E0E-AE32-D7050236433A} + {945871B1-77B8-43FB-B53C-27CF385AB756} = {8CF53B92-5EB1-461D-98F8-70DA9B603FBF} {B51126A8-0D75-4A79-867D-10724EC6AC84} = {94207AA6-4923-4183-A558-E0F8196B8CA3} {5E75AB7D-6F01-4313-AFF1-7F7128FFD71F} = {8CF53B92-5EB1-461D-98F8-70DA9B603FBF} {F7771E22-47BD-45C4-A133-FD7F1DE27CA0} = {7EDE8CF1-B1E4-4005-B154-834B944E0D7A} diff --git a/src/Squidex.Domain.Apps.Entities/Apps/Templates/CreateProfileCommandMiddleware.cs b/src/Squidex.Domain.Apps.Entities/Apps/Templates/CreateProfileCommandMiddleware.cs index 6cea0df6c..344a27d97 100644 --- a/src/Squidex.Domain.Apps.Entities/Apps/Templates/CreateProfileCommandMiddleware.cs +++ b/src/Squidex.Domain.Apps.Entities/Apps/Templates/CreateProfileCommandMiddleware.cs @@ -78,7 +78,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Templates private static async Task> CreateBasicsSchemaAsync(Func publish) { var command = - SchemaBuilder.Create("basics") + SchemaBuilder.Create("Basics") .AddString("First Name", f => f .Required() .ShowInList() @@ -120,7 +120,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Templates private static async Task> CreateProjectsSchemaAsync(Func publish) { var schema = - SchemaBuilder.Create("projects") + SchemaBuilder.Create("Projects") .AddString("Name", f => f .Required() .ShowInList() diff --git a/src/Squidex.Domain.Apps.Entities/Contents/ContentGrain.cs b/src/Squidex.Domain.Apps.Entities/Contents/ContentGrain.cs index 60f425b5e..63f7022e6 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/ContentGrain.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/ContentGrain.cs @@ -239,7 +239,7 @@ namespace Squidex.Domain.Apps.Entities.Contents if (command.Publish) { - RaiseEvent(SimpleMapper.Map(command, new ContentStatusChanged { Status = Status.Published })); + RaiseEvent(SimpleMapper.Map(command, new ContentStatusChanged { Status = Status.Published, Change = StatusChange.Published })); } } diff --git a/src/Squidex.Infrastructure/Orleans/IBackgroundGrain.cs b/src/Squidex.Infrastructure/Orleans/IBackgroundGrain.cs index e30295b8a..b23313685 100644 --- a/src/Squidex.Infrastructure/Orleans/IBackgroundGrain.cs +++ b/src/Squidex.Infrastructure/Orleans/IBackgroundGrain.cs @@ -7,11 +7,13 @@ using System.Threading.Tasks; using Orleans; +using Orleans.Concurrency; namespace Squidex.Infrastructure.Orleans { public interface IBackgroundGrain : IGrainWithStringKey { + [OneWay] Task ActivateAsync(); } } diff --git a/src/Squidex.Web/ApiExceptionFilterAttribute.cs b/src/Squidex.Web/ApiExceptionFilterAttribute.cs index ce1b22b55..76ab8a7d9 100644 --- a/src/Squidex.Web/ApiExceptionFilterAttribute.cs +++ b/src/Squidex.Web/ApiExceptionFilterAttribute.cs @@ -9,6 +9,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Security; +using System.Text; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; using Squidex.Infrastructure; @@ -27,6 +28,7 @@ namespace Squidex.Web static ApiExceptionFilterAttribute() { AddHandler(OnValidationException); + AddHandler(OnDecoderException); AddHandler(OnDomainObjectNotFoundException); AddHandler(OnDomainObjectVersionException); AddHandler(OnDomainForbiddenException); @@ -34,6 +36,11 @@ namespace Squidex.Web AddHandler(OnSecurityException); } + private static IActionResult OnDecoderException(DecoderFallbackException ex) + { + return ErrorResult(400, new ErrorDto { Message = ex.Message }); + } + private static IActionResult OnDomainObjectNotFoundException(DomainObjectNotFoundException ex) { return new NotFoundResult(); diff --git a/src/Squidex/Config/Orleans/OrleansServices.cs b/src/Squidex/Config/Orleans/OrleansServices.cs index ace29d8ee..3bffa3f49 100644 --- a/src/Squidex/Config/Orleans/OrleansServices.cs +++ b/src/Squidex/Config/Orleans/OrleansServices.cs @@ -28,11 +28,6 @@ namespace Squidex.Config.Orleans { services.AddOrleans(config, environment, builder => { - builder.ConfigureLogging(logging => - { - logging.AddFilters(); - }); - builder.ConfigureServices(siloServices => { siloServices.AddSingleton(); diff --git a/src/Squidex/app/features/content/shared/due-time-selector.component.html b/src/Squidex/app/features/content/shared/due-time-selector.component.html index 933b331a9..cbd859267 100644 --- a/src/Squidex/app/features/content/shared/due-time-selector.component.html +++ b/src/Squidex/app/features/content/shared/due-time-selector.component.html @@ -1,21 +1,21 @@ - + - {{dueTimeAction}} content item(s) + Change content item(s) to {{dueTimeAction}}
@@ -27,5 +27,4 @@
-
diff --git a/src/Squidex/app/framework/angular/forms/autocomplete.component.html b/src/Squidex/app/framework/angular/forms/autocomplete.component.html index 5b62c0310..5f6ee92fa 100644 --- a/src/Squidex/app/framework/angular/forms/autocomplete.component.html +++ b/src/Squidex/app/framework/angular/forms/autocomplete.component.html @@ -6,7 +6,7 @@ autocapitalize="off"> -
+
implements OnInit, AfterViewInit { private picker: any; - private timeValue: any | null = null; - private dateValue: any | null = null; + private timeValue: moment.Moment | null = null; + private dateValue: moment.Moment | null = null; private suppressEvents = false; @Input() @@ -65,10 +65,10 @@ export class DateTimeEditorComponent extends StatefulControlComponent<{}, string if (!value || value.length === 0) { this.timeValue = null; } else { - this.timeValue = moment(value, 'HH:mm:ss'); + this.timeValue = moment.utc(value, 'HH:mm:ss'); } - this.updateValue(); + this.callChangeFormatted(); })); this.own( @@ -76,10 +76,10 @@ export class DateTimeEditorComponent extends StatefulControlComponent<{}, string if (!value || value.length === 0) { this.dateValue = null; } else { - this.dateValue = moment(value, 'YYYY-MM-DD'); + this.dateValue = moment.utc(value, 'YYYY-MM-DD'); } - this.updateValue(); + this.callChangeFormatted(); })); } @@ -87,10 +87,10 @@ export class DateTimeEditorComponent extends StatefulControlComponent<{}, string if (Types.isString(obj) && obj.length > 0) { const parsed = moment.parseZone(obj); - this.dateValue = moment(parsed); + this.dateValue = parsed; if (this.showTime) { - this.timeValue = moment(parsed); + this.timeValue = parsed; } } else { this.timeValue = null; @@ -128,7 +128,7 @@ export class DateTimeEditorComponent extends StatefulControlComponent<{}, string } this.dateValue = this.picker.getMoment(); - this.updateValue(); + this.callChangeFormatted(); this.callTouched(); } }); @@ -140,7 +140,7 @@ export class DateTimeEditorComponent extends StatefulControlComponent<{}, string this.writeValue(new Date().toUTCString()); this.updateControls(); - this.updateValue(); + this.callChangeFormatted(); this.callTouched(); return false; @@ -158,26 +158,30 @@ export class DateTimeEditorComponent extends StatefulControlComponent<{}, string return false; } - private updateValue() { - let result: string | null; + private callChangeFormatted() { + this.callChange(this.getValue()); + } - if ((this.dateValue && !this.dateValue.isValid()) || (this.timeValue && !this.timeValue.isValid())) { - result = null; - } else if (!this.dateValue && !this.timeValue) { - result = null; - } else { - result = this.dateValue.format('YYYY-MM-DD'); - - if (this.showTime && this.timeValue) { - result += 'T'; - result += this.timeValue.format('HH:mm:ss'); - result += 'Z'; - } else if (this.enforceTime) { - result += 'T00:00:00Z'; - } + private getValue(): string | null { + if (!this.dateValue || !this.dateValue.isValid()) { + return null; + } + + if (this.timeValue && !this.timeValue.isValid()) { + return null; } - this.callChange(result); + let result = this.dateValue.format('YYYY-MM-DD'); + + if (this.showTime && this.timeValue) { + result += 'T'; + result += this.timeValue.format('HH:mm:ss'); + result += 'Z'; + } else if (this.enforceTime) { + result += 'T00:00:00Z'; + } + + return result; } private updateControls() { @@ -190,13 +194,16 @@ export class DateTimeEditorComponent extends StatefulControlComponent<{}, string } if (this.dateValue && this.dateValue.isValid() && this.picker) { - this.dateControl.setValue(this.dateValue.format('YYYY-MM-DD'), { emitEvent: false }); + const dateString = this.dateValue.format('YYYY-MM-DD'); + const dateLocal = moment(dateString); + + this.dateControl.setValue(dateString, { emitEvent: false }); - this.picker.setMoment(this.dateValue); + this.picker.setMoment(dateLocal); } else { this.dateControl.setValue(null, { emitEvent: false }); } this.suppressEvents = false; } -} +} \ No newline at end of file diff --git a/src/Squidex/app/framework/angular/modals/onboarding-tooltip.component.html b/src/Squidex/app/framework/angular/modals/onboarding-tooltip.component.html index 510e462f3..04d8088f6 100644 --- a/src/Squidex/app/framework/angular/modals/onboarding-tooltip.component.html +++ b/src/Squidex/app/framework/angular/modals/onboarding-tooltip.component.html @@ -1,6 +1,6 @@ -
-
+
+
diff --git a/src/Squidex/app/framework/angular/modals/onboarding-tooltip.component.ts b/src/Squidex/app/framework/angular/modals/onboarding-tooltip.component.ts index dac338b4c..cc1e55afa 100644 --- a/src/Squidex/app/framework/angular/modals/onboarding-tooltip.component.ts +++ b/src/Squidex/app/framework/angular/modals/onboarding-tooltip.component.ts @@ -58,7 +58,7 @@ export class OnboardingTooltipComponent extends StatefulComponent implements OnD if (this.for && this.helpId && Types.isFunction(this.for.addEventListener)) { this.own( timer(this.after).subscribe(() => { - if (true || this.onboardingService.shouldShow(this.helpId)) { + if (this.onboardingService.shouldShow(this.helpId)) { const forRect = this.for.getBoundingClientRect(); const x = forRect.left + 0.5 * forRect.width; diff --git a/src/Squidex/app/shared/components/markdown-editor.component.ts b/src/Squidex/app/shared/components/markdown-editor.component.ts index 370952907..a549e34ed 100644 --- a/src/Squidex/app/shared/components/markdown-editor.component.ts +++ b/src/Squidex/app/shared/components/markdown-editor.component.ts @@ -9,6 +9,7 @@ import { AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, E import { NG_VALUE_ACCESSOR } from '@angular/forms'; import { + ApiUrlConfig, AssetDto, AssetUploaderState, DialogModel, @@ -52,6 +53,7 @@ export class MarkdownEditorComponent extends StatefulControlComponent 0) { @@ -252,7 +254,7 @@ export class MarkdownEditorComponent extends StatefulControlComponent { if (Types.is(asset, AssetDto)) { - replaceText(`![${asset.fileName}](${asset.contentUrl} '${asset.fileName}')`); + replaceText(`![${asset.fileName}](${asset.fullUrl(this.apiUrl)} '${asset.fileName}')`); } }, error => { if (!Types.is(error, UploadCanceled)) { diff --git a/src/Squidex/app/shared/components/pipes.ts b/src/Squidex/app/shared/components/pipes.ts index 11abdf943..7c59cd5b0 100644 --- a/src/Squidex/app/shared/components/pipes.ts +++ b/src/Squidex/app/shared/components/pipes.ts @@ -216,8 +216,13 @@ export class UserPictureRefPipe extends UserAsyncPipe implements PipeTransform { pure: true }) export class AssetUrlPipe implements PipeTransform { + constructor( + private readonly apiUrl: ApiUrlConfig + ) { + } + public transform(asset: AssetDto): string { - return `${asset.contentUrl}&sq=${MathHelper.guid()}`; + return `${asset.fullUrl(this.apiUrl)}&sq=${MathHelper.guid()}`; } } @@ -226,8 +231,13 @@ export class AssetUrlPipe implements PipeTransform { pure: true }) export class AssetPreviewUrlPipe implements PipeTransform { + constructor( + private readonly apiUrl: ApiUrlConfig + ) { + } + public transform(asset: AssetDto): string { - return asset.contentUrl; + return asset.fullUrl(this.apiUrl); } } diff --git a/src/Squidex/app/shared/components/rich-editor.component.ts b/src/Squidex/app/shared/components/rich-editor.component.ts index 807b8ae0a..4e73c1c65 100644 --- a/src/Squidex/app/shared/components/rich-editor.component.ts +++ b/src/Squidex/app/shared/components/rich-editor.component.ts @@ -11,6 +11,7 @@ import { AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, E import { NG_VALUE_ACCESSOR } from '@angular/forms'; import { + ApiUrlConfig, AssetDto, AssetUploaderState, DialogModel, @@ -55,6 +56,7 @@ export class RichEditorComponent extends StatefulControlComponent { if (Types.is(asset, AssetDto)) { - success(asset.contentUrl); + success(asset.fullUrl(this.apiUrl)); } }, error => { if (!Types.is(error, UploadCanceled)) { @@ -190,7 +192,7 @@ export class RichEditorComponent extends StatefulControlComponent`; + content += `${asset.fileName}`; } if (content.length > 0) { @@ -220,7 +222,7 @@ export class RichEditorComponent extends StatefulControlComponent { if (Types.is(asset, AssetDto)) { - replaceText(`${asset.fileName}`); + replaceText(`${asset.fileName}`); } }, error => { if (!Types.is(error, UploadCanceled)) { diff --git a/src/Squidex/app/shared/services/assets.service.ts b/src/Squidex/app/shared/services/assets.service.ts index b058e8a2d..b7bcc8ded 100644 --- a/src/Squidex/app/shared/services/assets.service.ts +++ b/src/Squidex/app/shared/services/assets.service.ts @@ -80,6 +80,10 @@ export class AssetDto { this._meta = meta; } + + public fullUrl(apiUrl: ApiUrlConfig) { + return apiUrl.buildUrl(this.contentUrl); + } } export interface AnnotateAssetDto { diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentGrainTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentGrainTests.cs index 197f88146..c68392509 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentGrainTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentGrainTests.cs @@ -153,7 +153,7 @@ namespace Squidex.Domain.Apps.Entities.Contents LastEvents .ShouldHaveSameEvents( CreateContentEvent(new ContentCreated { Data = data, Status = Status.Draft }), - CreateContentEvent(new ContentStatusChanged { Status = Status.Published }) + CreateContentEvent(new ContentStatusChanged { Status = Status.Published, Change = StatusChange.Published }) ); A.CallTo(() => scriptEngine.ExecuteAndTransform(A.Ignored, ""))