Skip to content

Commit

Permalink
Actually working error reporting.
Browse files Browse the repository at this point in the history
  • Loading branch information
sarahelsaig committed Mar 17, 2024
1 parent bbb5ac3 commit a466db7
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 44 deletions.
55 changes: 31 additions & 24 deletions Lombiq.ContentEditors/Assets/Scripts/async-editor/async-editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,37 +11,44 @@ class AsyncEditorApiClient {
this.contentType = parameters.contentType;
}

loadEditor(contentId, editorGroup, callback) {
return fetch(this.createUrl(contentId, editorGroup))
.then((response) => response.json())
.then((data) => callback(true, data))
.catch((error) => callback(false, error));
}

async submitEditor(contentId, editorGroup, nextEditorGroup, formData, callback) {
async fetchEditor(callback, contentId, editorGroup, nextEditorGroup, requestOptions, raiseEvent) {
try {
const response = await fetch(this.createUrl(contentId, editorGroup, nextEditorGroup), {
method: 'post',
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
},
body: new URLSearchParams(formData),
});

callback(true, await response.json());

const submittedEditorEvent = new CustomEvent('asyncEditorSubmittedEditor', {
bubbles: true,
cancelable: true,
detail: { asyncEditor: window.asyncEditor },
});
document.dispatchEvent(submittedEditorEvent);
const response = await fetch(this.createUrl(contentId, editorGroup, nextEditorGroup), requestOptions);
const data = await response.json();
const success = data.type !== 'Error';

callback(success, data);
if (!success) return;

if (raiseEvent) {
const submittedEditorEvent = new CustomEvent('asyncEditorSubmittedEditor', {
bubbles: true,
cancelable: true,
detail: { asyncEditor: window.asyncEditor },
});
document.dispatchEvent(submittedEditorEvent);
}
}
catch (error) {
callback(false, error);
}
}

loadEditor(contentId, editorGroup, callback) {
return this.fetchEditor(callback, contentId, editorGroup);
}

submitEditor(contentId, editorGroup, nextEditorGroup, formData, callback) {
const requestOptions = {
method: 'post',
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
},
body: new URLSearchParams(formData),
};
return this.fetchEditor(callback, contentId, editorGroup, nextEditorGroup, requestOptions, true);
}

createUrl(contentId, editorGroup, nextEditorGroup) {
const url = new URL(this.apiUrl, document.baseURI);
const query = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
using Lombiq.ContentEditors.Constants;
using Lombiq.ContentEditors.Models;
using Lombiq.ContentEditors.Services;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using OrchardCore.ContentManagement;
using OrchardCore.Modules;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
Expand Down Expand Up @@ -44,32 +46,42 @@ public async Task<ActionResult<RenderedAsyncEditorGroupRequest>> Get([FromQuery]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Post([FromQuery] SubmitAsyncEditorRequest request)
{
var provider = GetProvider(request.ProviderName);
if (provider == null) return NotFound();
try
{
var provider = GetProvider(request.ProviderName);
if (provider == null) return Fail($"Couldn't get the provider \"{request.ProviderName}\".");

var item = await _contentManager.GetOrCreateAsync(request.ContentId, request.ContentType, VersionOptions.Latest);
if (item == null) return NotFound();
var item = await _contentManager.GetOrCreateAsync(request.ContentId, request.ContentType, VersionOptions.Latest);
if (item == null) return Fail($"Couldn't find the content item \"{request.ContentId}\".");

var context = PopulateContext(request, item);
if (!await provider.CanRenderEditorGroupAsync(context)) return NotFound();
var context = PopulateContext(request, item);
if (!await provider.CanRenderEditorGroupAsync(context))
{
return Fail($"The editor group of provider \"{request.ProviderName}\" can't be rendered.");
}

var result = await provider.UpdateEditorAsync(context);
if (!result.ModelState.IsValid ||
string.IsNullOrEmpty(request.NextEditorGroup) ||
request.NextEditorGroup == request.EditorGroup)
{
var result = await provider.UpdateEditorAsync(context);
if (!result.ModelState.IsValid ||
string.IsNullOrEmpty(request.NextEditorGroup) ||
request.NextEditorGroup == request.EditorGroup)
{
return await AsyncEditorResultAsync(
context,
provider,
renderedEditor: await result.RenderedEditorShapeFactory(),
message: result.Message);
}

var nextEditorContext = PopulateContext(request, item, request.NextEditorGroup);
return await AsyncEditorResultAsync(
context,
!await provider.CanRenderEditorGroupAsync(nextEditorContext) ? context : nextEditorContext,
provider,
renderedEditor: await result.RenderedEditorShapeFactory(),
message: result.Message);
}

var nextEditorContext = PopulateContext(request, item, request.NextEditorGroup);
return await AsyncEditorResultAsync(
!await provider.CanRenderEditorGroupAsync(nextEditorContext) ? context : nextEditorContext,
provider,
message: result.Message);
catch (Exception exception)
{
return Fail(exception);
}
}

private IAsyncEditorProvider<ContentItem> GetProvider(string name) =>
Expand Down Expand Up @@ -114,4 +126,14 @@ private async Task<ViewResult> AsyncEditorResultAsync(
Message = message,
});
}

/// <summary>
/// Provides serialized JSON information during local development, but ony a generic error message in production.
/// It's useful to always return JSON, regardless whether the request succeeded or failed.
/// </summary>
private JsonResult Fail(object data) => Json(new
{
Type = "Error",
Content = HttpContext.IsDevelopmentAndLocalhost() ? data : "Something went wrong.",
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
</div>
<div class="asyncEditor__messages">
<div class="asyncEditor__error p-3 rounded bg-danger text-light mb-3" v-if="errorText" :data-error-json="errorJson">{{ errorText }}</div>
<div class="asyncEditor__message p-3 rounded bg-success text-light mb-3" v-if="message">{{ message }}</div>
<div class="asyncEditor__message p-3 rounded bg-success text-light mb-3" v-else-if="message">{{ message }}</div>
<div class="asyncEditor__validationSummary p-3 rounded bg-danger text-light mb-3" v-if="validationSummaryHtml" v-html="validationSummaryHtml"></div>
</div>
</div>
Expand Down

0 comments on commit a466db7

Please sign in to comment.