Add OapApi.v1 module

This commit is contained in:
2024-03-28 22:10:26 -05:00
parent 67f488c5bd
commit 440ccba5d2
79 changed files with 3004 additions and 142 deletions

View File

@@ -0,0 +1,11 @@
using OrchardCore.Modules.Manifest;
[assembly: Module(
Name = "Overseas Auto Protection API",
Author = "Overseas Auto Protection",
Website = "https://oaprotection.org/api/v1/",
Version = "0.0.1",
Description = "API for OAP services",
Category = "Content Management"
)]

View File

@@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<InvariantGlobalization>true</InvariantGlobalization>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Facility.AspNetCore" Version="3.9.0" />
<PackageReference Include="Facility.Core" Version="2.27.0" />
<PackageReference Include="OrchardCore.Module.Targets" Version="1.8.2" />
<PackageReference Include="OrchardCore.ContentManagement" Version="1.8.2" />
<PackageReference Include="OrchardCore.ContentTypes.Abstractions" Version="1.8.2" />
<PackageReference Include="OrchardCore.DisplayManagement" Version="1.8.2" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\OapApi.v1.Client\OapApi.v1.Client.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,30 @@
using Facility.Core;
using Microsoft.AspNetCore.Mvc;
using OapApi.v1.Client;
namespace OapApi.v1;
public sealed class OapApiV1 : IOapApiV1
{
public Task<ServiceResult<CreateApplicationResponseDto>> CreateApplicationAsync(CreateApplicationRequestDto request, CancellationToken cancellationToken = default) => throw new NotImplementedException();
public Task<ServiceResult<GetApplicationResponseDto>> GetApplicationAsync(GetApplicationRequestDto request, CancellationToken cancellationToken = default)
{
return Task.FromResult(ServiceResult.Success(new GetApplicationResponseDto
{
Application = new ApplicationDto
{
Id = "1",
Status = ApplicationStatus.InProgress,
Terms = new ApplicationTermsDto
{
HasReadInstructions = true,
}
}
}));
}
public Task<ServiceResult<GetApplicationsResponseDto>> GetApplicationsAsync(GetApplicationsRequestDto request, CancellationToken cancellationToken = default) => throw new NotImplementedException();
public Task<ServiceResult<UpdateApplicationResponseDto>> UpdateApplicationAsync(UpdateApplicationRequestDto request, CancellationToken cancellationToken = default) => throw new NotImplementedException();
}

View File

@@ -0,0 +1,34 @@
using Facility.AspNetCore;
using Facility.Core.Http;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
using OapApi.v1.Client;
using OapApi.v1.Client.Http;
namespace OapApi.v1
{
public class Startup : OrchardCore.Modules.StartupBase
{
public override void ConfigureServices(IServiceCollection services)
{
services.AddScoped<IOapApiV1, OapApiV1>();
services.AddScoped(sp =>
{
return new OapApiV1HttpHandler(
sp.GetRequiredService<IOapApiV1>(),
new ServiceHttpHandlerSettings
{
RootPath = "/oap/api/v1",
});
});
}
public override void Configure(IApplicationBuilder builder, IEndpointRouteBuilder routes, IServiceProvider serviceProvider)
{
builder.UseFacilityExceptionHandler();
builder.UseFacilityHttpHandler<OapApiV1HttpHandler>();
}
}
}

View File

@@ -0,0 +1,248 @@
{
"swagger": "2.0",
"info": {
"title": "OapApiV1",
"description": "API providing OAP functionality for the application form, calculator and more.\n\n## Heading\n\nUse a primary heading to indicate the member name.",
"version": "0.0.0",
"x-identifier": "OapApiV1",
"x-codegen": "DO NOT EDIT: generated by fsdgenswagger"
},
"host": "oaprotection.org",
"basePath": "/api/v1",
"schemes": [
"https"
],
"paths": {
"/applications": {
"get": {
"tags": [
"bob"
],
"summary": "Gets applications for the current user.",
"description": "Gets the current user's applications in pages.",
"operationId": "getApplications",
"produces": [
"application/json"
],
"parameters": [
{
"in": "query",
"name": "status",
"description": "Filter applications by the given status.",
"type": "string",
"enum": [
"InProgress",
"Submitted"
]
},
{
"in": "query",
"name": "limit",
"description": "The limit of returned results.",
"type": "integer",
"format": "int32"
},
{
"in": "query",
"name": "nextToken",
"description": "The token presenting the next page of applications to get.",
"type": "string"
}
],
"responses": {
"200": {
"description": "",
"schema": {
"$ref": "#/definitions/GetApplicationsResponse"
}
}
}
}
},
"/applications/": {
"post": {
"summary": "Creates a new application for the current user.",
"description": "Creates a new application for the current user.",
"operationId": "createApplication",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"parameters": [
{
"in": "body",
"name": "request",
"description": "The application to create.",
"required": true,
"schema": {
"$ref": "#/definitions/ApplicationCreateSet"
}
}
],
"responses": {
"200": {
"description": "The created application.",
"schema": {
"$ref": "#/definitions/Application"
},
"x-identifier": "application"
},
"201": {
"description": ""
}
}
}
},
"/applications/{id}": {
"get": {
"summary": "Gets the specified application for the current user.",
"operationId": "getApplication",
"produces": [
"application/json"
],
"parameters": [
{
"in": "path",
"name": "id",
"description": "The widget ID.",
"required": true,
"type": "string"
}
],
"responses": {
"200": {
"description": "The requested widget.",
"schema": {
"$ref": "#/definitions/Application"
},
"x-identifier": "application"
},
"304": {
"description": "",
"x-identifier": "notModified"
}
}
},
"patch": {
"summary": "Updates the application.",
"description": "Updates an application for the current user, given the ID of the application to update.",
"operationId": "updateApplication",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"parameters": [
{
"in": "path",
"name": "id",
"description": "The application ID.",
"required": true,
"type": "string"
},
{
"in": "body",
"name": "request",
"description": "The application update set.",
"required": true,
"schema": {
"$ref": "#/definitions/ApplicationChangeSet"
}
}
],
"responses": {
"200": {
"description": "The updated Application.",
"schema": {
"$ref": "#/definitions/Application"
},
"x-identifier": "application"
}
}
}
}
},
"definitions": {
"GetApplicationsResponse": {
"type": "object",
"properties": {
"applications": {
"description": "The applications.",
"type": "array",
"items": {
"$ref": "#/definitions/Application"
}
},
"total": {
"description": "The total number of applications.",
"type": "integer",
"format": "int64"
},
"nextToken": {
"description": "The token representing the next page of results.",
"type": "string"
},
"isLastPage": {
"description": "True if this is the last page of results, false otherwise.",
"type": "boolean"
}
}
},
"ApplicationCreateSet": {
"type": "object",
"properties": {
"terms": {
"$ref": "#/definitions/ApplicationTermsCreateSet"
}
}
},
"Application": {
"description": "An application.",
"type": "object",
"properties": {
"id": {
"description": "A unique identifier for the application.",
"type": "string"
},
"status": {
"description": "The current status of this application.",
"type": "string",
"enum": [
"InProgress",
"Submitted"
]
},
"terms": {
"$ref": "#/definitions/ApplicationTerms"
}
},
"x-remarks": "Represents a user's application, whether in progress or submitted."
},
"ApplicationChangeSet": {
"type": "object",
"properties": {}
},
"ApplicationTermsCreateSet": {
"required": [
"hasReadInstructions"
],
"type": "object",
"properties": {
"hasReadInstructions": {
"type": "boolean"
}
}
},
"ApplicationTerms": {
"type": "object",
"properties": {
"hasReadInstructions": {
"type": "boolean"
}
}
}
}
}

View File

@@ -0,0 +1,33 @@
// <auto-generated>
// DO NOT EDIT: generated by fsdgencsharp
// </auto-generated>
using System;
using System.Collections.Generic;
using Facility.Core;
namespace OapApi.v1.Client
{
[System.CodeDom.Compiler.GeneratedCode("fsdgencsharp", "")]
public sealed partial class ApplicationChangeSetDto : ServiceDto<ApplicationChangeSetDto>
{
/// <summary>
/// Creates an instance.
/// </summary>
public ApplicationChangeSetDto()
{
}
/// <summary>
/// The JSON serializer.
/// </summary>
protected override JsonServiceSerializer JsonSerializer => SystemTextJsonServiceSerializer.Instance;
/// <summary>
/// Determines if two DTOs are equivalent.
/// </summary>
public override bool IsEquivalentTo(ApplicationChangeSetDto other)
{
return other != null;
}
}
}

View File

@@ -0,0 +1,60 @@
// <auto-generated>
// DO NOT EDIT: generated by fsdgencsharp
// </auto-generated>
using System;
using System.Collections.Generic;
using Facility.Core;
namespace OapApi.v1.Client
{
[System.CodeDom.Compiler.GeneratedCode("fsdgencsharp", "")]
public sealed partial class ApplicationCreateSetDto : ServiceDto<ApplicationCreateSetDto>
{
/// <summary>
/// Creates an instance.
/// </summary>
public ApplicationCreateSetDto()
{
}
/// <summary>
/// Terms a user must accept to start an application.
/// </summary>
public ApplicationTermsCreateSetDto Terms { get; set; }
/// <summary>
/// The JSON serializer.
/// </summary>
protected override JsonServiceSerializer JsonSerializer => SystemTextJsonServiceSerializer.Instance;
/// <summary>
/// Determines if two DTOs are equivalent.
/// </summary>
public override bool IsEquivalentTo(ApplicationCreateSetDto other)
{
return other != null &&
ServiceDataUtility.AreEquivalentDtos(Terms, other.Terms);
}
/// <summary>
/// Validates the DTO.
/// </summary>
public override bool Validate(out string errorMessage)
{
errorMessage = GetValidationErrorMessage();
return errorMessage == null;
}
private string GetValidationErrorMessage()
{
if (Terms == null)
return ServiceDataUtility.GetRequiredFieldErrorMessage("terms");
string errorMessage;
if (!ServiceDataUtility.ValidateFieldValue(Terms, "terms", out errorMessage))
return errorMessage;
return null;
}
}
}

View File

@@ -0,0 +1,54 @@
// <auto-generated>
// DO NOT EDIT: generated by fsdgencsharp
// </auto-generated>
using System;
using System.Collections.Generic;
using Facility.Core;
namespace OapApi.v1.Client
{
/// <summary>
/// An application.
/// </summary>
[System.CodeDom.Compiler.GeneratedCode("fsdgencsharp", "")]
public sealed partial class ApplicationDto : ServiceDto<ApplicationDto>
{
/// <summary>
/// Creates an instance.
/// </summary>
public ApplicationDto()
{
}
/// <summary>
/// A unique identifier for the application.
/// </summary>
public string Id { get; set; }
/// <summary>
/// The current status of this application.
/// </summary>
public ApplicationStatus? Status { get; set; }
/// <summary>
/// Terms the user must accept to start, continue an accept an application.
/// </summary>
public ApplicationTermsDto Terms { get; set; }
/// <summary>
/// The JSON serializer.
/// </summary>
protected override JsonServiceSerializer JsonSerializer => SystemTextJsonServiceSerializer.Instance;
/// <summary>
/// Determines if two DTOs are equivalent.
/// </summary>
public override bool IsEquivalentTo(ApplicationDto other)
{
return other != null &&
Id == other.Id &&
Status == other.Status &&
ServiceDataUtility.AreEquivalentDtos(Terms, other.Terms);
}
}
}

View File

@@ -0,0 +1,112 @@
// <auto-generated>
// DO NOT EDIT: generated by fsdgencsharp
// </auto-generated>
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Facility.Core;
namespace OapApi.v1.Client
{
[System.CodeDom.Compiler.GeneratedCode("fsdgencsharp", "")]
[Newtonsoft.Json.JsonConverter(typeof(ApplicationStatusJsonConverter))]
[System.Text.Json.Serialization.JsonConverter(typeof(ApplicationStatusSystemTextJsonConverter))]
public partial struct ApplicationStatus : IEquatable<ApplicationStatus>
{
public static readonly ApplicationStatus InProgress = new ApplicationStatus(Strings.InProgress);
public static readonly ApplicationStatus Submitted = new ApplicationStatus(Strings.Submitted);
/// <summary>
/// Creates an instance.
/// </summary>
public ApplicationStatus(string value) => m_value = value;
/// <summary>
/// Converts the instance to a string.
/// </summary>
public override string ToString() => m_value != null && s_valueCache.TryGetValue(m_value, out var cachedValue) ? cachedValue : m_value ?? "";
/// <summary>
/// Checks for equality.
/// </summary>
public bool Equals(ApplicationStatus other) => StringComparer.OrdinalIgnoreCase.Equals(m_value ?? "", other.m_value ?? "");
/// <summary>
/// Checks for equality.
/// </summary>
public override bool Equals(object obj) => obj is ApplicationStatus && Equals((ApplicationStatus) obj);
/// <summary>
/// Gets the hash code.
/// </summary>
public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(m_value ?? "");
/// <summary>
/// Checks for equality.
/// </summary>
public static bool operator ==(ApplicationStatus left, ApplicationStatus right) => left.Equals(right);
/// <summary>
/// Checks for inequality.
/// </summary>
public static bool operator !=(ApplicationStatus left, ApplicationStatus right) => !left.Equals(right);
/// <summary>
/// Returns true if the instance is equal to one of the defined values.
/// </summary>
public bool IsDefined() => m_value != null && s_valueCache.ContainsKey(m_value);
/// <summary>
/// Returns all of the defined values.
/// </summary>
public static IReadOnlyList<ApplicationStatus> GetValues() => s_values;
/// <summary>
/// Provides string constants for defined values.
/// </summary>
public static class Strings
{
public const string InProgress = "InProgress";
public const string Submitted = "Submitted";
}
/// <summary>
/// Used for serialization.
/// </summary>
public sealed class ApplicationStatusJsonConverter : ServiceEnumJsonConverter<ApplicationStatus>
{
/// <summary>
/// Creates the value from a string.
/// </summary>
protected override ApplicationStatus CreateCore(string value) => new ApplicationStatus(value);
}
/// <summary>
/// Used for serialization.
/// </summary>
public sealed class ApplicationStatusSystemTextJsonConverter : ServiceEnumSystemTextJsonConverter<ApplicationStatus>
{
/// <summary>
/// Creates the value from a string.
/// </summary>
protected override ApplicationStatus CreateCore(string value) => new ApplicationStatus(value);
}
private static readonly ReadOnlyCollection<ApplicationStatus> s_values = new ReadOnlyCollection<ApplicationStatus>(
new[]
{
InProgress,
Submitted,
});
private static readonly IReadOnlyDictionary<string, string> s_valueCache = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
{ Strings.InProgress, Strings.InProgress },
{ Strings.Submitted, Strings.Submitted },
};
private readonly string m_value;
}
}

View File

@@ -0,0 +1,53 @@
// <auto-generated>
// DO NOT EDIT: generated by fsdgencsharp
// </auto-generated>
using System;
using System.Collections.Generic;
using Facility.Core;
namespace OapApi.v1.Client
{
[System.CodeDom.Compiler.GeneratedCode("fsdgencsharp", "")]
public sealed partial class ApplicationTermsCreateSetDto : ServiceDto<ApplicationTermsCreateSetDto>
{
/// <summary>
/// Creates an instance.
/// </summary>
public ApplicationTermsCreateSetDto()
{
}
public bool? HasReadInstructions { get; set; }
/// <summary>
/// The JSON serializer.
/// </summary>
protected override JsonServiceSerializer JsonSerializer => SystemTextJsonServiceSerializer.Instance;
/// <summary>
/// Determines if two DTOs are equivalent.
/// </summary>
public override bool IsEquivalentTo(ApplicationTermsCreateSetDto other)
{
return other != null &&
HasReadInstructions == other.HasReadInstructions;
}
/// <summary>
/// Validates the DTO.
/// </summary>
public override bool Validate(out string errorMessage)
{
errorMessage = GetValidationErrorMessage();
return errorMessage == null;
}
private string GetValidationErrorMessage()
{
if (HasReadInstructions == null)
return ServiceDataUtility.GetRequiredFieldErrorMessage("hasReadInstructions");
return null;
}
}
}

View File

@@ -0,0 +1,36 @@
// <auto-generated>
// DO NOT EDIT: generated by fsdgencsharp
// </auto-generated>
using System;
using System.Collections.Generic;
using Facility.Core;
namespace OapApi.v1.Client
{
[System.CodeDom.Compiler.GeneratedCode("fsdgencsharp", "")]
public sealed partial class ApplicationTermsDto : ServiceDto<ApplicationTermsDto>
{
/// <summary>
/// Creates an instance.
/// </summary>
public ApplicationTermsDto()
{
}
public bool? HasReadInstructions { get; set; }
/// <summary>
/// The JSON serializer.
/// </summary>
protected override JsonServiceSerializer JsonSerializer => SystemTextJsonServiceSerializer.Instance;
/// <summary>
/// Determines if two DTOs are equivalent.
/// </summary>
public override bool IsEquivalentTo(ApplicationTermsDto other)
{
return other != null &&
HasReadInstructions == other.HasReadInstructions;
}
}
}

View File

@@ -0,0 +1,60 @@
// <auto-generated>
// DO NOT EDIT: generated by fsdgencsharp
// </auto-generated>
using System;
using System.Collections.Generic;
using Facility.Core;
namespace OapApi.v1.Client
{
/// <summary>
/// Request for CreateApplication.
/// </summary>
[System.CodeDom.Compiler.GeneratedCode("fsdgencsharp", "")]
public sealed partial class CreateApplicationRequestDto : ServiceDto<CreateApplicationRequestDto>
{
/// <summary>
/// Creates an instance.
/// </summary>
public CreateApplicationRequestDto()
{
}
/// <summary>
/// The application to create.
/// </summary>
public ApplicationCreateSetDto ApplicationCreateSet { get; set; }
/// <summary>
/// The JSON serializer.
/// </summary>
protected override JsonServiceSerializer JsonSerializer => SystemTextJsonServiceSerializer.Instance;
/// <summary>
/// Determines if two DTOs are equivalent.
/// </summary>
public override bool IsEquivalentTo(CreateApplicationRequestDto other)
{
return other != null &&
ServiceDataUtility.AreEquivalentDtos(ApplicationCreateSet, other.ApplicationCreateSet);
}
/// <summary>
/// Validates the DTO.
/// </summary>
public override bool Validate(out string errorMessage)
{
errorMessage = GetValidationErrorMessage();
return errorMessage == null;
}
private string GetValidationErrorMessage()
{
string errorMessage;
if (!ServiceDataUtility.ValidateFieldValue(ApplicationCreateSet, "applicationCreateSet", out errorMessage))
return errorMessage;
return null;
}
}
}

View File

@@ -0,0 +1,42 @@
// <auto-generated>
// DO NOT EDIT: generated by fsdgencsharp
// </auto-generated>
using System;
using System.Collections.Generic;
using Facility.Core;
namespace OapApi.v1.Client
{
/// <summary>
/// Response for CreateApplication.
/// </summary>
[System.CodeDom.Compiler.GeneratedCode("fsdgencsharp", "")]
public sealed partial class CreateApplicationResponseDto : ServiceDto<CreateApplicationResponseDto>
{
/// <summary>
/// Creates an instance.
/// </summary>
public CreateApplicationResponseDto()
{
}
/// <summary>
/// The created application.
/// </summary>
public ApplicationDto Application { get; set; }
/// <summary>
/// The JSON serializer.
/// </summary>
protected override JsonServiceSerializer JsonSerializer => SystemTextJsonServiceSerializer.Instance;
/// <summary>
/// Determines if two DTOs are equivalent.
/// </summary>
public override bool IsEquivalentTo(CreateApplicationResponseDto other)
{
return other != null &&
ServiceDataUtility.AreEquivalentDtos(Application, other.Application);
}
}
}

View File

@@ -0,0 +1,49 @@
// <auto-generated>
// DO NOT EDIT: generated by fsdgencsharp
// </auto-generated>
using System;
using System.Threading;
using System.Threading.Tasks;
using Facility.Core;
namespace OapApi.v1.Client
{
/// <summary>
/// A delegating implementation of OapApiV1.
/// </summary>
[System.CodeDom.Compiler.GeneratedCode("fsdgencsharp", "")]
public partial class DelegatingOapApiV1 : IOapApiV1
{
/// <summary>
/// Creates an instance with the specified delegator.
/// </summary>
public DelegatingOapApiV1(ServiceDelegator delegator) =>
m_delegator = delegator ?? throw new ArgumentNullException(nameof(delegator));
/// <summary>
/// Gets applications for the current user.
/// </summary>
public virtual async Task<ServiceResult<GetApplicationsResponseDto>> GetApplicationsAsync(GetApplicationsRequestDto request, CancellationToken cancellationToken = default) =>
(await m_delegator(OapApiV1Methods.GetApplications, request, cancellationToken).ConfigureAwait(false)).Cast<GetApplicationsResponseDto>();
/// <summary>
/// Creates a new application for the current user.
/// </summary>
public virtual async Task<ServiceResult<CreateApplicationResponseDto>> CreateApplicationAsync(CreateApplicationRequestDto request, CancellationToken cancellationToken = default) =>
(await m_delegator(OapApiV1Methods.CreateApplication, request, cancellationToken).ConfigureAwait(false)).Cast<CreateApplicationResponseDto>();
/// <summary>
/// Gets the specified application for the current user.
/// </summary>
public virtual async Task<ServiceResult<GetApplicationResponseDto>> GetApplicationAsync(GetApplicationRequestDto request, CancellationToken cancellationToken = default) =>
(await m_delegator(OapApiV1Methods.GetApplication, request, cancellationToken).ConfigureAwait(false)).Cast<GetApplicationResponseDto>();
/// <summary>
/// Updates the application.
/// </summary>
public virtual async Task<ServiceResult<UpdateApplicationResponseDto>> UpdateApplicationAsync(UpdateApplicationRequestDto request, CancellationToken cancellationToken = default) =>
(await m_delegator(OapApiV1Methods.UpdateApplication, request, cancellationToken).ConfigureAwait(false)).Cast<UpdateApplicationResponseDto>();
private readonly ServiceDelegator m_delegator;
}
}

View File

@@ -0,0 +1,42 @@
// <auto-generated>
// DO NOT EDIT: generated by fsdgencsharp
// </auto-generated>
using System;
using System.Collections.Generic;
using Facility.Core;
namespace OapApi.v1.Client
{
/// <summary>
/// Request for GetApplication.
/// </summary>
[System.CodeDom.Compiler.GeneratedCode("fsdgencsharp", "")]
public sealed partial class GetApplicationRequestDto : ServiceDto<GetApplicationRequestDto>
{
/// <summary>
/// Creates an instance.
/// </summary>
public GetApplicationRequestDto()
{
}
/// <summary>
/// The widget ID.
/// </summary>
public string Id { get; set; }
/// <summary>
/// The JSON serializer.
/// </summary>
protected override JsonServiceSerializer JsonSerializer => SystemTextJsonServiceSerializer.Instance;
/// <summary>
/// Determines if two DTOs are equivalent.
/// </summary>
public override bool IsEquivalentTo(GetApplicationRequestDto other)
{
return other != null &&
Id == other.Id;
}
}
}

View File

@@ -0,0 +1,48 @@
// <auto-generated>
// DO NOT EDIT: generated by fsdgencsharp
// </auto-generated>
using System;
using System.Collections.Generic;
using Facility.Core;
namespace OapApi.v1.Client
{
/// <summary>
/// Response for GetApplication.
/// </summary>
[System.CodeDom.Compiler.GeneratedCode("fsdgencsharp", "")]
public sealed partial class GetApplicationResponseDto : ServiceDto<GetApplicationResponseDto>
{
/// <summary>
/// Creates an instance.
/// </summary>
public GetApplicationResponseDto()
{
}
/// <summary>
/// The requested widget.
/// </summary>
public ApplicationDto Application { get; set; }
public string ETag { get; set; }
public bool? NotModified { get; set; }
/// <summary>
/// The JSON serializer.
/// </summary>
protected override JsonServiceSerializer JsonSerializer => SystemTextJsonServiceSerializer.Instance;
/// <summary>
/// Determines if two DTOs are equivalent.
/// </summary>
public override bool IsEquivalentTo(GetApplicationResponseDto other)
{
return other != null &&
ServiceDataUtility.AreEquivalentDtos(Application, other.Application) &&
ETag == other.ETag &&
NotModified == other.NotModified;
}
}
}

View File

@@ -0,0 +1,54 @@
// <auto-generated>
// DO NOT EDIT: generated by fsdgencsharp
// </auto-generated>
using System;
using System.Collections.Generic;
using Facility.Core;
namespace OapApi.v1.Client
{
/// <summary>
/// Request for GetApplications.
/// </summary>
[System.CodeDom.Compiler.GeneratedCode("fsdgencsharp", "")]
public sealed partial class GetApplicationsRequestDto : ServiceDto<GetApplicationsRequestDto>
{
/// <summary>
/// Creates an instance.
/// </summary>
public GetApplicationsRequestDto()
{
}
/// <summary>
/// Filter applications by the given status.
/// </summary>
public ApplicationStatus? Status { get; set; }
/// <summary>
/// The limit of returned results.
/// </summary>
public int? Limit { get; set; }
/// <summary>
/// The token presenting the next page of applications to get.
/// </summary>
public string NextToken { get; set; }
/// <summary>
/// The JSON serializer.
/// </summary>
protected override JsonServiceSerializer JsonSerializer => SystemTextJsonServiceSerializer.Instance;
/// <summary>
/// Determines if two DTOs are equivalent.
/// </summary>
public override bool IsEquivalentTo(GetApplicationsRequestDto other)
{
return other != null &&
Status == other.Status &&
Limit == other.Limit &&
NextToken == other.NextToken;
}
}
}

View File

@@ -0,0 +1,60 @@
// <auto-generated>
// DO NOT EDIT: generated by fsdgencsharp
// </auto-generated>
using System;
using System.Collections.Generic;
using Facility.Core;
namespace OapApi.v1.Client
{
/// <summary>
/// Response for GetApplications.
/// </summary>
[System.CodeDom.Compiler.GeneratedCode("fsdgencsharp", "")]
public sealed partial class GetApplicationsResponseDto : ServiceDto<GetApplicationsResponseDto>
{
/// <summary>
/// Creates an instance.
/// </summary>
public GetApplicationsResponseDto()
{
}
/// <summary>
/// The applications.
/// </summary>
public IReadOnlyList<ApplicationDto> Applications { get; set; }
/// <summary>
/// The total number of applications.
/// </summary>
public long? Total { get; set; }
/// <summary>
/// The token representing the next page of results.
/// </summary>
public string NextToken { get; set; }
/// <summary>
/// True if this is the last page of results, false otherwise.
/// </summary>
public bool? IsLastPage { get; set; }
/// <summary>
/// The JSON serializer.
/// </summary>
protected override JsonServiceSerializer JsonSerializer => SystemTextJsonServiceSerializer.Instance;
/// <summary>
/// Determines if two DTOs are equivalent.
/// </summary>
public override bool IsEquivalentTo(GetApplicationsResponseDto other)
{
return other != null &&
ServiceDataUtility.AreEquivalentFieldValues(Applications, other.Applications) &&
Total == other.Total &&
NextToken == other.NextToken &&
IsLastPage == other.IsLastPage;
}
}
}

View File

@@ -0,0 +1,53 @@
// <auto-generated>
// DO NOT EDIT: generated by fsdgencsharp
// </auto-generated>
using System;
using System.Threading;
using System.Threading.Tasks;
using Facility.Core;
using Facility.Core.Http;
namespace OapApi.v1.Client.Http
{
[System.CodeDom.Compiler.GeneratedCode("fsdgencsharp", "")]
public sealed partial class HttpClientOapApiV1 : HttpClientService, IOapApiV1
{
/// <summary>
/// Creates the service.
/// </summary>
public HttpClientOapApiV1(HttpClientServiceSettings settings = null)
: base(settings, s_defaults)
{
}
/// <summary>
/// Gets applications for the current user.
/// </summary>
public Task<ServiceResult<GetApplicationsResponseDto>> GetApplicationsAsync(GetApplicationsRequestDto request, CancellationToken cancellationToken = default) =>
TrySendRequestAsync(OapApiV1HttpMapping.GetApplicationsMapping, request, cancellationToken);
/// <summary>
/// Creates a new application for the current user.
/// </summary>
public Task<ServiceResult<CreateApplicationResponseDto>> CreateApplicationAsync(CreateApplicationRequestDto request, CancellationToken cancellationToken = default) =>
TrySendRequestAsync(OapApiV1HttpMapping.CreateApplicationMapping, request, cancellationToken);
/// <summary>
/// Gets the specified application for the current user.
/// </summary>
public Task<ServiceResult<GetApplicationResponseDto>> GetApplicationAsync(GetApplicationRequestDto request, CancellationToken cancellationToken = default) =>
TrySendRequestAsync(OapApiV1HttpMapping.GetApplicationMapping, request, cancellationToken);
/// <summary>
/// Updates the application.
/// </summary>
public Task<ServiceResult<UpdateApplicationResponseDto>> UpdateApplicationAsync(UpdateApplicationRequestDto request, CancellationToken cancellationToken = default) =>
TrySendRequestAsync(OapApiV1HttpMapping.UpdateApplicationMapping, request, cancellationToken);
private static readonly HttpClientServiceDefaults s_defaults = new HttpClientServiceDefaults
{
BaseUri = new Uri("https://oaprotection.org/api/v1"),
ContentSerializer = HttpContentSerializer.Create(SystemTextJsonServiceSerializer.Instance),
};
}
}

View File

@@ -0,0 +1,80 @@
// <auto-generated>
// DO NOT EDIT: generated by fsdgencsharp
// </auto-generated>
using System;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Facility.Core;
using Facility.Core.Http;
namespace OapApi.v1.Client.Http
{
[System.CodeDom.Compiler.GeneratedCode("fsdgencsharp", "")]
public sealed partial class OapApiV1HttpHandler : ServiceHttpHandler
{
/// <summary>
/// Creates the handler.
/// </summary>
public OapApiV1HttpHandler(IOapApiV1 service, ServiceHttpHandlerSettings settings = null)
: base(settings, s_defaults)
{
m_service = service ?? throw new ArgumentNullException(nameof(service));
}
/// <summary>
/// Creates the handler.
/// </summary>
public OapApiV1HttpHandler(Func<HttpRequestMessage, IOapApiV1> getService, ServiceHttpHandlerSettings settings = null)
: base(settings, s_defaults)
{
m_getService = getService ?? throw new ArgumentNullException(nameof(getService));
}
/// <summary>
/// Attempts to handle the HTTP request.
/// </summary>
public override async Task<HttpResponseMessage> TryHandleHttpRequestAsync(HttpRequestMessage httpRequest, CancellationToken cancellationToken = default)
{
return await AdaptTask(TryHandleGetApplicationsAsync(httpRequest, cancellationToken)).ConfigureAwait(true) ??
await AdaptTask(TryHandleCreateApplicationAsync(httpRequest, cancellationToken)).ConfigureAwait(true) ??
await AdaptTask(TryHandleGetApplicationAsync(httpRequest, cancellationToken)).ConfigureAwait(true) ??
await AdaptTask(TryHandleUpdateApplicationAsync(httpRequest, cancellationToken)).ConfigureAwait(true);
}
/// <summary>
/// Gets applications for the current user.
/// </summary>
public Task<HttpResponseMessage> TryHandleGetApplicationsAsync(HttpRequestMessage httpRequest, CancellationToken cancellationToken = default) =>
TryHandleServiceMethodAsync(OapApiV1HttpMapping.GetApplicationsMapping, httpRequest, GetService(httpRequest).GetApplicationsAsync, cancellationToken);
/// <summary>
/// Creates a new application for the current user.
/// </summary>
public Task<HttpResponseMessage> TryHandleCreateApplicationAsync(HttpRequestMessage httpRequest, CancellationToken cancellationToken = default) =>
TryHandleServiceMethodAsync(OapApiV1HttpMapping.CreateApplicationMapping, httpRequest, GetService(httpRequest).CreateApplicationAsync, cancellationToken);
/// <summary>
/// Gets the specified application for the current user.
/// </summary>
public Task<HttpResponseMessage> TryHandleGetApplicationAsync(HttpRequestMessage httpRequest, CancellationToken cancellationToken = default) =>
TryHandleServiceMethodAsync(OapApiV1HttpMapping.GetApplicationMapping, httpRequest, GetService(httpRequest).GetApplicationAsync, cancellationToken);
/// <summary>
/// Updates the application.
/// </summary>
public Task<HttpResponseMessage> TryHandleUpdateApplicationAsync(HttpRequestMessage httpRequest, CancellationToken cancellationToken = default) =>
TryHandleServiceMethodAsync(OapApiV1HttpMapping.UpdateApplicationMapping, httpRequest, GetService(httpRequest).UpdateApplicationAsync, cancellationToken);
private IOapApiV1 GetService(HttpRequestMessage httpRequest) => m_service ?? m_getService(httpRequest);
private static readonly ServiceHttpHandlerDefaults s_defaults = new ServiceHttpHandlerDefaults
{
ContentSerializer = HttpContentSerializer.Create(SystemTextJsonServiceSerializer.Instance),
};
private readonly IOapApiV1 m_service;
private readonly Func<HttpRequestMessage, IOapApiV1> m_getService;
}
}

View File

@@ -0,0 +1,186 @@
// <auto-generated>
// DO NOT EDIT: generated by fsdgencsharp
// </auto-generated>
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Net;
using System.Net.Http;
using Facility.Core;
using Facility.Core.Http;
#pragma warning disable 612, 618 // member is obsolete
namespace OapApi.v1.Client.Http
{
[System.CodeDom.Compiler.GeneratedCode("fsdgencsharp", "")]
public static partial class OapApiV1HttpMapping
{
/// <summary>
/// Gets applications for the current user.
/// </summary>
public static readonly HttpMethodMapping<GetApplicationsRequestDto, GetApplicationsResponseDto> GetApplicationsMapping =
new HttpMethodMapping<GetApplicationsRequestDto, GetApplicationsResponseDto>.Builder
{
HttpMethod = HttpMethod.Get,
Path = "/applications",
GetUriParameters = request =>
new Dictionary<string, string>
{
{ "status", request.Status == null ? null : request.Status.Value.ToString() },
{ "limit", request.Limit == null ? null : request.Limit.Value.ToString(CultureInfo.InvariantCulture) },
{ "nextToken", request.NextToken },
},
SetUriParameters = (request, parameters) =>
{
parameters.TryGetValue("status", out var queryParameterStatus);
request.Status = queryParameterStatus == null ? default(ApplicationStatus?) : new ApplicationStatus(queryParameterStatus);
parameters.TryGetValue("limit", out var queryParameterLimit);
request.Limit = ServiceDataUtility.TryParseInt32(queryParameterLimit);
parameters.TryGetValue("nextToken", out var queryParameterNextToken);
request.NextToken = queryParameterNextToken;
return request;
},
ResponseMappings =
{
new HttpResponseMapping<GetApplicationsResponseDto>.Builder
{
StatusCode = (HttpStatusCode) 200,
ResponseBodyType = typeof(GetApplicationsResponseDto),
}.Build(),
},
}.Build();
/// <summary>
/// Creates a new application for the current user.
/// </summary>
public static readonly HttpMethodMapping<CreateApplicationRequestDto, CreateApplicationResponseDto> CreateApplicationMapping =
new HttpMethodMapping<CreateApplicationRequestDto, CreateApplicationResponseDto>.Builder
{
HttpMethod = HttpMethod.Post,
Path = "/applications/",
ValidateRequest = request =>
{
if (request.ApplicationCreateSet == null)
return ServiceResult.Failure(ServiceErrors.CreateRequestFieldRequired("applicationCreateSet"));
return ServiceResult.Success();
},
RequestBodyType = typeof(ApplicationCreateSetDto),
GetRequestBody = request => request.ApplicationCreateSet,
CreateRequest = body => new CreateApplicationRequestDto { ApplicationCreateSet = (ApplicationCreateSetDto) body },
ResponseMappings =
{
new HttpResponseMapping<CreateApplicationResponseDto>.Builder
{
StatusCode = (HttpStatusCode) 200,
ResponseBodyType = typeof(ApplicationDto),
MatchesResponse = response => response.Application != null,
GetResponseBody = response => response.Application,
CreateResponse = body => new CreateApplicationResponseDto { Application = (ApplicationDto) body },
}.Build(),
new HttpResponseMapping<CreateApplicationResponseDto>.Builder
{
StatusCode = (HttpStatusCode) 201,
}.Build(),
},
}.Build();
/// <summary>
/// Gets the specified application for the current user.
/// </summary>
public static readonly HttpMethodMapping<GetApplicationRequestDto, GetApplicationResponseDto> GetApplicationMapping =
new HttpMethodMapping<GetApplicationRequestDto, GetApplicationResponseDto>.Builder
{
HttpMethod = HttpMethod.Get,
Path = "/applications/{id}",
ValidateRequest = request =>
{
if (string.IsNullOrEmpty(request.Id))
return ServiceResult.Failure(ServiceErrors.CreateRequestFieldRequired("id"));
return ServiceResult.Success();
},
GetUriParameters = request =>
new Dictionary<string, string>
{
{ "id", request.Id },
},
SetUriParameters = (request, parameters) =>
{
parameters.TryGetValue("id", out var queryParameterId);
request.Id = queryParameterId;
return request;
},
ResponseMappings =
{
new HttpResponseMapping<GetApplicationResponseDto>.Builder
{
StatusCode = (HttpStatusCode) 200,
ResponseBodyType = typeof(ApplicationDto),
MatchesResponse = response => response.Application != null,
GetResponseBody = response => response.Application,
CreateResponse = body => new GetApplicationResponseDto { Application = (ApplicationDto) body },
}.Build(),
new HttpResponseMapping<GetApplicationResponseDto>.Builder
{
StatusCode = (HttpStatusCode) 304,
MatchesResponse = response => response.NotModified.GetValueOrDefault(),
CreateResponse = body => new GetApplicationResponseDto { NotModified = true },
}.Build(),
},
GetResponseHeaders = response =>
new Dictionary<string, string>
{
["eTag"] = response.ETag,
},
SetResponseHeaders = (response, headers) =>
{
headers.TryGetValue("eTag", out var headerETag);
response.ETag = headerETag;
return response;
},
}.Build();
/// <summary>
/// Updates the application.
/// </summary>
public static readonly HttpMethodMapping<UpdateApplicationRequestDto, UpdateApplicationResponseDto> UpdateApplicationMapping =
new HttpMethodMapping<UpdateApplicationRequestDto, UpdateApplicationResponseDto>.Builder
{
HttpMethod = new HttpMethod("PATCH"),
Path = "/applications/{id}",
ValidateRequest = request =>
{
if (string.IsNullOrEmpty(request.Id))
return ServiceResult.Failure(ServiceErrors.CreateRequestFieldRequired("id"));
if (request.ApplicationChangeSet == null)
return ServiceResult.Failure(ServiceErrors.CreateRequestFieldRequired("applicationChangeSet"));
return ServiceResult.Success();
},
GetUriParameters = request =>
new Dictionary<string, string>
{
{ "id", request.Id },
},
SetUriParameters = (request, parameters) =>
{
parameters.TryGetValue("id", out var queryParameterId);
request.Id = queryParameterId;
return request;
},
RequestBodyType = typeof(ApplicationChangeSetDto),
GetRequestBody = request => request.ApplicationChangeSet,
CreateRequest = body => new UpdateApplicationRequestDto { ApplicationChangeSet = (ApplicationChangeSetDto) body },
ResponseMappings =
{
new HttpResponseMapping<UpdateApplicationResponseDto>.Builder
{
StatusCode = (HttpStatusCode) 200,
ResponseBodyType = typeof(ApplicationDto),
MatchesResponse = response => response.Application != null,
GetResponseBody = response => response.Application,
CreateResponse = body => new UpdateApplicationResponseDto { Application = (ApplicationDto) body },
}.Build(),
},
}.Build();
}
}

View File

@@ -0,0 +1,34 @@
// <auto-generated>
// DO NOT EDIT: generated by fsdgencsharp
// </auto-generated>
using System;
using System.Threading;
using System.Threading.Tasks;
using Facility.Core;
namespace OapApi.v1.Client
{
[System.CodeDom.Compiler.GeneratedCode("fsdgencsharp", "")]
public partial interface IOapApiV1
{
/// <summary>
/// Gets applications for the current user.
/// </summary>
Task<ServiceResult<GetApplicationsResponseDto>> GetApplicationsAsync(GetApplicationsRequestDto request, CancellationToken cancellationToken = default);
/// <summary>
/// Creates a new application for the current user.
/// </summary>
Task<ServiceResult<CreateApplicationResponseDto>> CreateApplicationAsync(CreateApplicationRequestDto request, CancellationToken cancellationToken = default);
/// <summary>
/// Gets the specified application for the current user.
/// </summary>
Task<ServiceResult<GetApplicationResponseDto>> GetApplicationAsync(GetApplicationRequestDto request, CancellationToken cancellationToken = default);
/// <summary>
/// Updates the application.
/// </summary>
Task<ServiceResult<UpdateApplicationResponseDto>> UpdateApplicationAsync(UpdateApplicationRequestDto request, CancellationToken cancellationToken = default);
}
}

View File

@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Facility.Core" Version="2.27.0" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,28 @@
// <auto-generated>
// DO NOT EDIT: generated by fsdgencsharp
// </auto-generated>
using System;
using Facility.Core;
namespace OapApi.v1.Client
{
[System.CodeDom.Compiler.GeneratedCode("fsdgencsharp", "")]
internal static class OapApiV1Methods
{
public static readonly IServiceMethodInfo GetApplications =
ServiceMethodInfo.Create<IOapApiV1, GetApplicationsRequestDto, GetApplicationsResponseDto>(
"getApplications", "OapApiV1", x => x.GetApplicationsAsync);
public static readonly IServiceMethodInfo CreateApplication =
ServiceMethodInfo.Create<IOapApiV1, CreateApplicationRequestDto, CreateApplicationResponseDto>(
"createApplication", "OapApiV1", x => x.CreateApplicationAsync);
public static readonly IServiceMethodInfo GetApplication =
ServiceMethodInfo.Create<IOapApiV1, GetApplicationRequestDto, GetApplicationResponseDto>(
"getApplication", "OapApiV1", x => x.GetApplicationAsync);
public static readonly IServiceMethodInfo UpdateApplication =
ServiceMethodInfo.Create<IOapApiV1, UpdateApplicationRequestDto, UpdateApplicationResponseDto>(
"updateApplication", "OapApiV1", x => x.UpdateApplicationAsync);
}
}

View File

@@ -0,0 +1,48 @@
// <auto-generated>
// DO NOT EDIT: generated by fsdgencsharp
// </auto-generated>
using System;
using System.Collections.Generic;
using Facility.Core;
namespace OapApi.v1.Client
{
/// <summary>
/// Request for UpdateApplication.
/// </summary>
[System.CodeDom.Compiler.GeneratedCode("fsdgencsharp", "")]
public sealed partial class UpdateApplicationRequestDto : ServiceDto<UpdateApplicationRequestDto>
{
/// <summary>
/// Creates an instance.
/// </summary>
public UpdateApplicationRequestDto()
{
}
/// <summary>
/// The application ID.
/// </summary>
public string Id { get; set; }
/// <summary>
/// The application update set.
/// </summary>
public ApplicationChangeSetDto ApplicationChangeSet { get; set; }
/// <summary>
/// The JSON serializer.
/// </summary>
protected override JsonServiceSerializer JsonSerializer => SystemTextJsonServiceSerializer.Instance;
/// <summary>
/// Determines if two DTOs are equivalent.
/// </summary>
public override bool IsEquivalentTo(UpdateApplicationRequestDto other)
{
return other != null &&
Id == other.Id &&
ServiceDataUtility.AreEquivalentDtos(ApplicationChangeSet, other.ApplicationChangeSet);
}
}
}

View File

@@ -0,0 +1,42 @@
// <auto-generated>
// DO NOT EDIT: generated by fsdgencsharp
// </auto-generated>
using System;
using System.Collections.Generic;
using Facility.Core;
namespace OapApi.v1.Client
{
/// <summary>
/// Response for UpdateApplication.
/// </summary>
[System.CodeDom.Compiler.GeneratedCode("fsdgencsharp", "")]
public sealed partial class UpdateApplicationResponseDto : ServiceDto<UpdateApplicationResponseDto>
{
/// <summary>
/// Creates an instance.
/// </summary>
public UpdateApplicationResponseDto()
{
}
/// <summary>
/// The updated Application.
/// </summary>
public ApplicationDto Application { get; set; }
/// <summary>
/// The JSON serializer.
/// </summary>
protected override JsonServiceSerializer JsonSerializer => SystemTextJsonServiceSerializer.Instance;
/// <summary>
/// Determines if two DTOs are equivalent.
/// </summary>
public override bool IsEquivalentTo(UpdateApplicationResponseDto other)
{
return other != null &&
ServiceDataUtility.AreEquivalentDtos(Application, other.Application);
}
}
}

View File

@@ -0,0 +1,18 @@
using Microsoft.AspNetCore.Mvc;
using OrchardCore.Data;
namespace OapTheme.Controllers;
public class ApplicationFormController : Controller
{
public ApplicationFormController(IDbConnectionAccessor dbConnectionAccessor)
{
m_dbConnectionAccessor = dbConnectionAccessor;
}
public IActionResult Index()
{
return View();
}
private readonly IDbConnectionAccessor m_dbConnectionAccessor;
}

View File

@@ -0,0 +1,9 @@
using OrchardCore.DisplayManagement.Manifest;
[assembly: Theme(
Name = "OAP Theme",
Author = "Ben Ramey",
Website = "https://oaprotection.org/",
Version = "0.0.1",
Description = "Overseas Auto Protection site theme."
)]

View File

@@ -0,0 +1,88 @@
using OrchardCore.Autoroute.Models;
using OrchardCore.ContentFields.Fields;
using OrchardCore.ContentFields.Settings;
using OrchardCore.ContentManagement.Metadata;
using OrchardCore.ContentManagement.Metadata.Settings;
using OrchardCore.Data.Migration;
using OrchardCore.Flows.Models;
using OrchardCore.Lists.Models;
namespace OapTheme;
public sealed class Migrations : DataMigration
{
public Migrations(IContentDefinitionManager contentDefinitionManager)
{
m_contentDefinitionManager = contentDefinitionManager;
}
public async Task<int> Create()
{
await m_contentDefinitionManager.AlterTypeDefinitionAsync("ApplicationFormStep", type => type
.Draftable()
.Versionable()
.WithPart("ApplicationFormStep", part => part
.WithPosition("1"))
.WithPart<AutoroutePart>("Autoroute", part => part
.WithPosition("2")
.WithSettings(new AutoroutePartSettings
{
AllowCustomPath = true,
AllowUpdatePath = true,
}))
.WithPart<FlowPart>("Form", part => part
.WithPosition("3")
.WithSettings(new FlowPartSettings
{
ContainedContentTypes = new[]
{
"Form",
}
})));
await m_contentDefinitionManager.AlterPartDefinitionAsync("ApplicationFormStep", part => part
.WithField<TextField>("Heading", field => field
.WithPosition("1")
.WithSettings(new TextFieldSettings
{
Hint = "Text to display at the top of the form step, above the instructions.",
Required = true,
}))
.WithField<HtmlField>("Instructions", field => field
.WithPosition("2")
.WithEditor("Wysiwyg")
.WithSettings(new HtmlFieldSettings
{
SanitizeHtml = true,
})));
await m_contentDefinitionManager.AlterTypeDefinitionAsync("ApplicationForm", type => type
.DisplayedAs("Application Form")
.Draftable()
.Versionable()
.Securable()
.Listable()
.Creatable()
.WithPart<AutoroutePart>("Autoroute", part => part
.WithPosition("2")
.WithSettings(new AutoroutePartSettings
{
AllowCustomPath = true,
AllowUpdatePath = true,
}))
.WithPart<ListPart>("Form Steps", part => part
.WithPosition("3")
.WithSettings(new ListPartSettings
{
PageSize = 10,
EnableOrdering = true,
ContainedContentTypes = new[]
{
"ApplicationFormStep",
}
})));
return 1;
}
private readonly IContentDefinitionManager m_contentDefinitionManager;
}

View File

@@ -12,6 +12,11 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="OrchardCore.Autoroute" Version="1.8.2" />
<PackageReference Include="OrchardCore.ContentFields" Version="1.8.2" />
<PackageReference Include="OrchardCore.Flows" Version="1.8.2" />
<PackageReference Include="OrchardCore.Forms" Version="1.8.2" />
<PackageReference Include="OrchardCore.Lists" Version="1.8.2" />
<PackageReference Include="OrchardCore.Theme.Targets" Version="1.8.2" />
<PackageReference Include="OrchardCore.ContentManagement" Version="1.8.2" />
<PackageReference Include="OrchardCore.DisplayManagement" Version="1.8.2" />
@@ -19,6 +24,7 @@
</ItemGroup>
<ItemGroup>
<Folder Include="Models\" />
<Folder Include="wwwroot\" />
</ItemGroup>

View File

@@ -1,7 +1,7 @@
using Microsoft.Extensions.Options;
using OrchardCore.ResourceManagement;
namespace TailwindTheme;
namespace OapTheme;
public class ResourceManagementOptionsConfiguration : IConfigureOptions<ResourceManagementOptions>
{
@@ -10,8 +10,8 @@ public class ResourceManagementOptionsConfiguration : IConfigureOptions<Resource
m_manifest = new ResourceManifest();
m_manifest
.DefineStyle("TailwindTheme-styles")
.SetUrl("~/TailwindTheme/site.css")
.DefineStyle("OapTheme-styles")
.SetUrl("~/OapTheme/site.css")
.SetVersion("1.0.0");
}

View File

@@ -1,14 +1,16 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using OrchardCore.Data.Migration;
using OrchardCore.Modules;
using OrchardCore.ResourceManagement;
namespace TailwindTheme;
namespace OapTheme;
public class Startup : StartupBase
{
public override void ConfigureServices(IServiceCollection serviceCollection)
public override void ConfigureServices(IServiceCollection services)
{
serviceCollection.AddTransient<IConfigureOptions<ResourceManagementOptions>, ResourceManagementOptionsConfiguration>();
services.AddTransient<IConfigureOptions<ResourceManagementOptions>, ResourceManagementOptionsConfiguration>();
services.AddDataMigration<Migrations>();
}
}

View File

@@ -0,0 +1,3 @@
<div class="richtext">
{{ Model.Html | sanitize_html | raw }}
</div>

View File

@@ -9,9 +9,9 @@
{% resources type: "Meta" %}
{% link type: "image/x-icon", rel: "shortcut icon", href: "~/TailwindTheme/assets/favicon.ico" %}
{% link type: "image/x-icon", rel: "shortcut icon", href: "~/OapTheme/assets/favicon.ico" %}
{% style name: "tailwindtheme-styles" %}
{% style name: "oaptheme-styles" %}
{% resources type: "HeadLink" %}
{% resources type: "Stylesheet" %}
@@ -28,4 +28,4 @@
{% resources type: "FootScript" %}
</body>
</html>
</html>

View File

@@ -0,0 +1,528 @@
/*!*************************************************************************************************************!*\
!*** css ./node_modules/css-loader/dist/cjs.js!./node_modules/postcss-loader/dist/cjs.js!./Styles/site.css ***!
\*************************************************************************************************************/
/*
! tailwindcss v3.3.5 | MIT License | https://tailwindcss.com
*//*
1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4)
2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116)
*/
*,
::before,
::after {
box-sizing: border-box; /* 1 */
border-width: 0; /* 2 */
border-style: solid; /* 2 */
border-color: #e5e7eb; /* 2 */
}
::before,
::after {
--tw-content: '';
}
/*
1. Use a consistent sensible line-height in all browsers.
2. Prevent adjustments of font size after orientation changes in iOS.
3. Use a more readable tab size.
4. Use the user's configured `sans` font-family by default.
5. Use the user's configured `sans` font-feature-settings by default.
6. Use the user's configured `sans` font-variation-settings by default.
*/
html {
line-height: 1.5; /* 1 */
-webkit-text-size-adjust: 100%; /* 2 */ /* 3 */
tab-size: 4; /* 3 */
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; /* 4 */
font-feature-settings: normal; /* 5 */
font-variation-settings: normal; /* 6 */
}
/*
1. Remove the margin in all browsers.
2. Inherit line-height from `html` so users can set them as a class directly on the `html` element.
*/
body {
margin: 0; /* 1 */
line-height: inherit; /* 2 */
}
/*
1. Add the correct height in Firefox.
2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655)
3. Ensure horizontal rules are visible by default.
*/
hr {
height: 0; /* 1 */
color: inherit; /* 2 */
border-top-width: 1px; /* 3 */
}
/*
Add the correct text decoration in Chrome, Edge, and Safari.
*/
abbr:where([title]) {
text-decoration: underline dotted;
}
/*
Remove the default font size and weight for headings.
*/
h1,
h2,
h3,
h4,
h5,
h6 {
font-size: inherit;
font-weight: inherit;
}
/*
Reset links to optimize for opt-in styling instead of opt-out.
*/
a {
color: inherit;
text-decoration: inherit;
}
/*
Add the correct font weight in Edge and Safari.
*/
b,
strong {
font-weight: bolder;
}
/*
1. Use the user's configured `mono` font family by default.
2. Correct the odd `em` font sizing in all browsers.
*/
code,
kbd,
samp,
pre {
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; /* 1 */
font-size: 1em; /* 2 */
}
/*
Add the correct font size in all browsers.
*/
small {
font-size: 80%;
}
/*
Prevent `sub` and `sup` elements from affecting the line height in all browsers.
*/
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
/*
1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297)
2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016)
3. Remove gaps between table borders by default.
*/
table {
text-indent: 0; /* 1 */
border-color: inherit; /* 2 */
border-collapse: collapse; /* 3 */
}
/*
1. Change the font styles in all browsers.
2. Remove the margin in Firefox and Safari.
3. Remove default padding in all browsers.
*/
button,
input,
optgroup,
select,
textarea {
font-family: inherit; /* 1 */
font-feature-settings: inherit; /* 1 */
font-variation-settings: inherit; /* 1 */
font-size: 100%; /* 1 */
font-weight: inherit; /* 1 */
line-height: inherit; /* 1 */
color: inherit; /* 1 */
margin: 0; /* 2 */
padding: 0; /* 3 */
}
/*
Remove the inheritance of text transform in Edge and Firefox.
*/
button,
select {
text-transform: none;
}
/*
1. Correct the inability to style clickable types in iOS and Safari.
2. Remove default button styles.
*/
button,
[type='button'],
[type='reset'],
[type='submit'] {
-webkit-appearance: button; /* 1 */
background-color: transparent; /* 2 */
background-image: none; /* 2 */
}
/*
Use the modern Firefox focus style for all focusable elements.
*/
:-moz-focusring {
outline: auto;
}
/*
Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737)
*/
:-moz-ui-invalid {
box-shadow: none;
}
/*
Add the correct vertical alignment in Chrome and Firefox.
*/
progress {
vertical-align: baseline;
}
/*
Correct the cursor style of increment and decrement buttons in Safari.
*/
::-webkit-inner-spin-button,
::-webkit-outer-spin-button {
height: auto;
}
/*
1. Correct the odd appearance in Chrome and Safari.
2. Correct the outline style in Safari.
*/
[type='search'] {
-webkit-appearance: textfield; /* 1 */
outline-offset: -2px; /* 2 */
}
/*
Remove the inner padding in Chrome and Safari on macOS.
*/
::-webkit-search-decoration {
-webkit-appearance: none;
}
/*
1. Correct the inability to style clickable types in iOS and Safari.
2. Change font properties to `inherit` in Safari.
*/
::-webkit-file-upload-button {
-webkit-appearance: button; /* 1 */
font: inherit; /* 2 */
}
/*
Add the correct display in Chrome and Safari.
*/
summary {
display: list-item;
}
/*
Removes the default spacing and border for appropriate elements.
*/
blockquote,
dl,
dd,
h1,
h2,
h3,
h4,
h5,
h6,
hr,
figure,
p,
pre {
margin: 0;
}
fieldset {
margin: 0;
padding: 0;
}
legend {
padding: 0;
}
ol,
ul,
menu {
list-style: none;
margin: 0;
padding: 0;
}
/*
Reset default styling for dialogs.
*/
dialog {
padding: 0;
}
/*
Prevent resizing textareas horizontally by default.
*/
textarea {
resize: vertical;
}
/*
1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300)
2. Set the default placeholder color to the user's configured gray 400 color.
*/
input::placeholder,
textarea::placeholder {
opacity: 1; /* 1 */
color: #9ca3af; /* 2 */
}
/*
Set the default cursor for buttons.
*/
button,
[role="button"] {
cursor: pointer;
}
/*
Make sure disabled buttons don't get the pointer cursor.
*/
:disabled {
cursor: default;
}
/*
1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14)
2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210)
This can trigger a poorly considered lint error in some tools but is included by design.
*/
img,
svg,
video,
canvas,
audio,
iframe,
embed,
object {
display: block; /* 1 */
vertical-align: middle; /* 2 */
}
/*
Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14)
*/
img,
video {
max-width: 100%;
height: auto;
}
/* Make elements with the HTML hidden attribute stay hidden by default */
[hidden] {
display: none;
}
*, ::before, ::after {
--tw-border-spacing-x: 0;
--tw-border-spacing-y: 0;
--tw-translate-x: 0;
--tw-translate-y: 0;
--tw-rotate: 0;
--tw-skew-x: 0;
--tw-skew-y: 0;
--tw-scale-x: 1;
--tw-scale-y: 1;
--tw-pan-x: ;
--tw-pan-y: ;
--tw-pinch-zoom: ;
--tw-scroll-snap-strictness: proximity;
--tw-gradient-from-position: ;
--tw-gradient-via-position: ;
--tw-gradient-to-position: ;
--tw-ordinal: ;
--tw-slashed-zero: ;
--tw-numeric-figure: ;
--tw-numeric-spacing: ;
--tw-numeric-fraction: ;
--tw-ring-inset: ;
--tw-ring-offset-width: 0px;
--tw-ring-offset-color: #fff;
--tw-ring-color: rgb(59 130 246 / 0.5);
--tw-ring-offset-shadow: 0 0 #0000;
--tw-ring-shadow: 0 0 #0000;
--tw-shadow: 0 0 #0000;
--tw-shadow-colored: 0 0 #0000;
--tw-blur: ;
--tw-brightness: ;
--tw-contrast: ;
--tw-grayscale: ;
--tw-hue-rotate: ;
--tw-invert: ;
--tw-saturate: ;
--tw-sepia: ;
--tw-drop-shadow: ;
--tw-backdrop-blur: ;
--tw-backdrop-brightness: ;
--tw-backdrop-contrast: ;
--tw-backdrop-grayscale: ;
--tw-backdrop-hue-rotate: ;
--tw-backdrop-invert: ;
--tw-backdrop-opacity: ;
--tw-backdrop-saturate: ;
--tw-backdrop-sepia: ;
}
::backdrop {
--tw-border-spacing-x: 0;
--tw-border-spacing-y: 0;
--tw-translate-x: 0;
--tw-translate-y: 0;
--tw-rotate: 0;
--tw-skew-x: 0;
--tw-skew-y: 0;
--tw-scale-x: 1;
--tw-scale-y: 1;
--tw-pan-x: ;
--tw-pan-y: ;
--tw-pinch-zoom: ;
--tw-scroll-snap-strictness: proximity;
--tw-gradient-from-position: ;
--tw-gradient-via-position: ;
--tw-gradient-to-position: ;
--tw-ordinal: ;
--tw-slashed-zero: ;
--tw-numeric-figure: ;
--tw-numeric-spacing: ;
--tw-numeric-fraction: ;
--tw-ring-inset: ;
--tw-ring-offset-width: 0px;
--tw-ring-offset-color: #fff;
--tw-ring-color: rgb(59 130 246 / 0.5);
--tw-ring-offset-shadow: 0 0 #0000;
--tw-ring-shadow: 0 0 #0000;
--tw-shadow: 0 0 #0000;
--tw-shadow-colored: 0 0 #0000;
--tw-blur: ;
--tw-brightness: ;
--tw-contrast: ;
--tw-grayscale: ;
--tw-hue-rotate: ;
--tw-invert: ;
--tw-saturate: ;
--tw-sepia: ;
--tw-drop-shadow: ;
--tw-backdrop-blur: ;
--tw-backdrop-brightness: ;
--tw-backdrop-contrast: ;
--tw-backdrop-grayscale: ;
--tw-backdrop-hue-rotate: ;
--tw-backdrop-invert: ;
--tw-backdrop-opacity: ;
--tw-backdrop-saturate: ;
--tw-backdrop-sepia: ;
}
div.richtext a {
--tw-text-opacity: 1;
color: rgb(29 78 216 / var(--tw-text-opacity));
text-decoration-line: underline;
}
div.richtext ol, div.richtext ul {
margin-top: 0.5rem;
margin-bottom: 0.5rem;
padding-left: 2rem;
}
div.richtext ol li {
margin-top: 0.25rem;
margin-bottom: 0.25rem;
list-style-type: decimal;
}
div.richtext ul li {
margin-top: 0.25rem;
margin-bottom: 0.25rem;
list-style-type: disc;
}
div.richtext p {
margin-top: 1rem;
margin-bottom: 1rem;
}
div.richtext .red {
--tw-text-opacity: 1;
color: rgb(239 68 68 / var(--tw-text-opacity));
}
span.field-validation-error {
font-size: 0.875rem;
line-height: 1.25rem;
--tw-text-opacity: 1;
color: rgb(220 38 38 / var(--tw-text-opacity));
}
.my-1 {
margin-top: 0.25rem;
margin-bottom: 0.25rem;
}
.table {
display: table;
}
.hidden {
display: none;
}

File diff suppressed because one or more lines are too long

View File

@@ -1,9 +0,0 @@
using OrchardCore.DisplayManagement.Manifest;
[assembly: Theme(
Name = "TailwindTheme",
Author = "Ben Ramey",
Website = "https://benramey.com",
Version = "0.0.1",
Description = "Tailwind Theme"
)]

View File

@@ -1,3 +0,0 @@
/*
! tailwindcss v3.3.5 | MIT License | https://tailwindcss.com
*/*,:after,:before{border:0 solid #e5e7eb;box-sizing:border-box}:after,:before{--tw-content:""}html{line-height:1.5;-webkit-text-size-adjust:100%;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;tab-size:4}body{line-height:inherit;margin:0}hr{border-top-width:1px;color:inherit;height:0}abbr:where([title]){text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sub{bottom:-.25em}sup{top:-.5em}table{border-collapse:collapse;border-color:inherit;text-indent:0}button,input,optgroup,select,textarea{color:inherit;font-family:inherit;font-feature-settings:inherit;font-size:100%;font-variation-settings:inherit;font-weight:inherit;line-height:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:initial;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:initial}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::placeholder,textarea::placeholder{color:#9ca3af;opacity:1}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{height:auto;max-width:100%}[hidden]{display:none}*,::backdrop,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }div.richtext a{--tw-text-opacity:1;color:rgb(29 78 216/var(--tw-text-opacity));text-decoration-line:underline}div.richtext ol,div.richtext ul{margin-bottom:.5rem;margin-top:.5rem;padding-left:2rem}div.richtext ol li{list-style-type:decimal}div.richtext ol li,div.richtext ul li{margin-bottom:.25rem;margin-top:.25rem}div.richtext ul li{list-style-type:disc}div.richtext p{margin-bottom:1rem;margin-top:1rem}div.richtext .red{--tw-text-opacity:1;color:rgb(239 68 68/var(--tw-text-opacity))}span.field-validation-error{font-size:.875rem;line-height:1.25rem;--tw-text-opacity:1;color:rgb(220 38 38/var(--tw-text-opacity))}.my-1{margin-bottom:.25rem;margin-top:.25rem}.table{display:table}.hidden{display:none}

File diff suppressed because one or more lines are too long

View File

@@ -25,8 +25,9 @@
<ItemGroup>
<ProjectReference Include="..\Modules\MarkdownImport\MarkdownImport.csproj" />
<ProjectReference Include="..\Modules\OapApi.v1\OapApi.v1.csproj" />
<ProjectReference Include="..\Themes\BenRameyTheme\BenRameyTheme.csproj" />
<ProjectReference Include="..\Themes\TailwindTheme\TailwindTheme.csproj" />
<ProjectReference Include="..\Themes\OapTheme\OapTheme.csproj" />
</ItemGroup>
</Project>