Skip to content

Commit

Permalink
feature: v14 server side
Browse files Browse the repository at this point in the history
  • Loading branch information
jcdcdev committed Jul 10, 2024
1 parent e42c5a3 commit 66f9ae7
Show file tree
Hide file tree
Showing 13 changed files with 332 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/jcdcdev.Umbraco.ExtendedDropdownEditor/Composer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ internal class Composer : IComposer
{
public void Compose(IUmbracoBuilder builder)
{
builder.AddExtendedDropdownEditor();
}
}
19 changes: 19 additions & 0 deletions src/jcdcdev.Umbraco.ExtendedDropdownEditor/Core/Constants.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
namespace jcdcdev.Umbraco.ExtendedDropdownEditor.Core;

public static class Constants
{
public const string PackageName = "Simple Workspace Views";

public class Api
{
public const string ApiName = "ExtendedDropdownEditor";
}

public class PropertyEditors
{
public class Aliases
{
public const string ExtendedDropdownEditor = "jcdcdev.Umbraco.ExtendedDropdownEditor";
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace jcdcdev.Umbraco.ExtendedDropdownEditor.Core;

public enum ExtendedDropdownType
{
Unknown = 0,
File = 1,
Url = 2,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using jcdcdev.Umbraco.Core.Extensions;
using jcdcdev.Umbraco.Core.Web.Models.Manifests;
using Umbraco.Cms.Core.Manifest;
using Umbraco.Cms.Infrastructure.Manifest;

namespace jcdcdev.Umbraco.ExtendedDropdownEditor.Core;
public class PackageManifestReader() : IPackageManifestReader
{
public async Task<IEnumerable<PackageManifest>> ReadPackageManifestsAsync()
{
var extensions = new List<IManifest>();
var packageManifest = new PackageManifest
{
Name = Constants.PackageName,
Version = EnvironmentExtensions.CurrentAssemblyVersion().ToSemVer()?.ToString() ?? "0.1.0",
AllowPublicAccess = false,
AllowTelemetry = true,
Extensions = []
};

extensions.Add(new EntryPointManifest
{
Name = "extended-dropdown-editor.entrypoint",
Alias = "extended-dropdown-editor.entrypoint",
Js = "/App_Plugins/jcdcdev.Umbraco.ExtendedDropdownEditor/dist/index.js"
});

packageManifest.Extensions = extensions.OfType<object>().ToArray();
return new[] { packageManifest };
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using jcdcdev.Umbraco.ExtendedDropdownEditor.Web;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.Extensions.DependencyInjection;
using Umbraco.Cms.Api.Management.Controllers.StaticFile.Tree;
using Umbraco.Cms.Core.DependencyInjection;
using Umbraco.Cms.Infrastructure.Manifest;

namespace jcdcdev.Umbraco.ExtendedDropdownEditor.Core;

public static class UmbracoBuilderExtensions
{
public static void AddExtendedDropdownEditor(this IUmbracoBuilder builder)
{
builder.Services.ConfigureOptions<ConfigApiSwaggerGenOptions>();
builder.Services.AddSingleton<IPackageManifestReader, PackageManifestReader>();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using System.Text.Json.Serialization;
using System.Web;
using jcdcdev.Umbraco.ExtendedDropdownEditor.Core;
using Umbraco.Cms.Core.PropertyEditors;
using Umbraco.Extensions;

namespace jcdcdev.Umbraco.ExtendedDropdownEditor.PropertyEditors;

public class ExtendedDropdownConfiguration : DropDownFlexibleConfiguration
{
[ConfigurationField("file")]
[JsonPropertyName("file")]
public List<string> File { get; set; } = [];

[ConfigurationField("filePathOverride")]
[JsonPropertyName("filePathOverride")]
public string FilePathOverride { get; set; }

[ConfigurationField("url")]
[JsonPropertyName("url")]
public string Url { get; set; }

[JsonIgnore] public ExtendedDropdownType DropdownType => GetDropdownType();
[JsonIgnore] public string? FilePath => HttpUtility.UrlDecode(FilePathOverride.IfNullOrWhiteSpace(File.FirstOrDefault()))?.Replace("%dot%", ".");

private ExtendedDropdownType GetDropdownType()
{
if (!FilePath.IsNullOrWhiteSpace())
{
return ExtendedDropdownType.File;
}

if (!Url.IsNullOrWhiteSpace())
{
return ExtendedDropdownType.Url;
}

return ExtendedDropdownType.Unknown;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using Umbraco.Cms.Core.IO;
using Umbraco.Cms.Core.PropertyEditors;

namespace jcdcdev.Umbraco.ExtendedDropdownEditor.PropertyEditors;

// Or should it be: ExtendedDropdownConfigurationConfigurationEditor? :D
internal class ExtendedDropdownConfigurationEditor : ConfigurationEditor<ExtendedDropdownConfiguration>
{
public ExtendedDropdownConfigurationEditor(IIOHelper ioHelper) : base(ioHelper)
{
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using Umbraco.Cms.Core.Models.PublishedContent;
using Umbraco.Cms.Core.PropertyEditors.ValueConverters;
using Umbraco.Cms.Core.Serialization;
using jcdcdev.Umbraco.ExtendedDropdownEditor.Core;

namespace jcdcdev.Umbraco.ExtendedDropdownEditor.PropertyEditors;

public class ExtendedDropdownEditorValueConverter : FlexibleDropdownPropertyValueConverter
{
public override bool IsConverter(IPublishedPropertyType propertyType) =>
propertyType.EditorAlias.Equals(Constants.PropertyEditors.Aliases.ExtendedDropdownEditor);

public ExtendedDropdownEditorValueConverter(IJsonSerializer jsonSerializer) : base(jsonSerializer)
{
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using Umbraco.Cms.Core.IO;
using Umbraco.Cms.Core.PropertyEditors;
using Umbraco.Cms.Core.Serialization;
using jcdcdev.Umbraco.ExtendedDropdownEditor.Core;

namespace jcdcdev.Umbraco.ExtendedDropdownEditor.PropertyEditors;

[DataEditor(
Constants.PropertyEditors.Aliases.ExtendedDropdownEditor,
ValueType = ValueTypes.Text,
ValueEditorIsReusable = true)]
public class ExtendedDropdownPropertyEditor : DropDownFlexiblePropertyEditor
{
private readonly IIOHelper _ioHelper;

protected override IConfigurationEditor CreateConfigurationEditor()
{
var config = new ExtendedDropdownConfigurationEditor(_ioHelper);
return config;
}


public ExtendedDropdownPropertyEditor(
IDataValueEditorFactory dataValueEditorFactory,
IIOHelper ioHelper,
IConfigurationEditorJsonSerializer configurationEditorJsonSerializer) : base(dataValueEditorFactory, ioHelper, configurationEditorJsonSerializer)
{
_ioHelper = ioHelper;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using jcdcdev.Umbraco.ExtendedDropdownEditor.Core;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;

namespace jcdcdev.Umbraco.ExtendedDropdownEditor.Web;

public class ConfigApiSwaggerGenOptions : IConfigureOptions<SwaggerGenOptions>
{
public void Configure(SwaggerGenOptions options)
{
options.SwaggerDoc(
Constants.Api.ApiName,
new OpenApiInfo
{
Title = "Extended Dropdown Editor Api",
Version = "Latest",
Description = "API for Extended Dropdown Editor"
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
using System.Net.Http.Json;
using System.Text.Json;
using jcdcdev.Umbraco.ExtendedDropdownEditor.Core;
using jcdcdev.Umbraco.ExtendedDropdownEditor.PropertyEditors;
using jcdcdev.Umbraco.ExtendedDropdownEditor.Web.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Umbraco.Cms.Api.Common.Attributes;
using Umbraco.Cms.Api.Common.Filters;
using Umbraco.Cms.Api.Management.Filters;
using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.IO;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Web.Common.Authorization;
using Umbraco.Extensions;

namespace jcdcdev.Umbraco.ExtendedDropdownEditor.Web;

[ApiExplorerSettings(GroupName = "Extended Dropdown Editor")]
[ExtendedDropdownEditorsRoute("")]
[MapToApi(Constants.Api.ApiName)]
[JsonOptionsName(global::Umbraco.Cms.Core.Constants.JsonOptionsNames.BackOffice)]
[ApiController]
[Authorize(Policy = AuthorizationPolicies.BackOfficeAccess)]
[AppendEventMessages]
[Produces("application/json")]
public class ExtendedDropdownEditorController(IDataTypeService dataTypeService, IPhysicalFileSystem fileSystem, HttpClient client, ILogger<ExtendedDropdownEditorController> logger) : ControllerBase
{
private readonly ILogger _logger = logger;

[HttpGet("items/{dataTypeKey:guid}")]
[Produces<ExtendedDropdownEditorResponse>]
public async Task<IActionResult> Items(Guid dataTypeKey)
{
var dataType = await dataTypeService.GetAsync(dataTypeKey);
if (dataType == null)
{
return NotFound();
}

try
{
var model = await GetItems(dataType);
return Ok(model);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error getting items for data type {DataTypeKey}", dataTypeKey);
return BadRequest(ex.Message);
}
}

private async Task<ExtendedDropdownEditorResponse> GetItems(IDataType dataType)
{
var model = new ExtendedDropdownEditorResponse
{
DataTypeKey = dataType.Key
};

var configuration = dataType.ConfigurationAs<ExtendedDropdownConfiguration>();
if (configuration == null)
{
_logger.LogWarning("No configuration found for data type {DataTypeKey}", dataType.Key);
return model;
}

var items = configuration.DropdownType switch
{
ExtendedDropdownType.File => await GetItemsFromFile(configuration.FilePath),
ExtendedDropdownType.Url => await GetItemsFromUrl(configuration.Url),
_ => []
};

model.Items = items;
return model;
}

private async Task<List<string>> GetItemsFromUrl(string url)
{
try
{
if (url.StartsWith("/"))
{
var settings = HttpContext.RequestServices.GetRequiredService<IOptions<WebRoutingSettings>>();
var uri = HttpContext.Request.GetApplicationUri(settings.Value);
var builder = new UriBuilder(uri)
{
Path = url
};
url = builder.Uri.ToString();
}

var result = await client.GetFromJsonAsync<List<string>>(url) ?? [];
return result;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error getting items from url {Url}", url);
throw;
}
}

private async Task<List<string>> GetItemsFromFile(string? filePath)
{
if (filePath.IsNullOrWhiteSpace())
{
_logger.LogDebug("No file path specified");
return [];
}

if (!fileSystem.FileExists(filePath))
{
_logger.LogDebug("File {FilePath} does not exist", filePath);
return [];
}

await using var stream = fileSystem.OpenFile(filePath);
return await JsonSerializer.DeserializeAsync<List<string>>(stream) ?? [];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
using Umbraco.Cms.Web.Common.Routing;

namespace jcdcdev.Umbraco.ExtendedDropdownEditor.Web;

public class ExtendedDropdownEditorsRouteAttribute(string template) : BackOfficeRouteAttribute($"ExtendedDropdownEditor/api/v{{version:apiVersion}}/{template.TrimStart('/')}");
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace jcdcdev.Umbraco.ExtendedDropdownEditor.Web.Models;

public class ExtendedDropdownEditorResponse
{
public List<string> Items { get; set; }
public Guid DataTypeKey { get; set; }
}

0 comments on commit 66f9ae7

Please sign in to comment.