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

30
.config/dotnet-tools.json Normal file
View File

@@ -0,0 +1,30 @@
{
"version": 1,
"isRoot": true,
"tools": {
"fsdgencsharp": {
"version": "2.27.0",
"commands": [
"fsdgencsharp"
]
},
"fsdgenmd": {
"version": "2.8.0",
"commands": [
"fsdgenmd"
]
},
"fsdgenaspnet": {
"version": "3.9.0",
"commands": [
"fsdgenaspnet"
]
},
"fsdgenswagger": {
"version": "2.5.0",
"commands": [
"fsdgenswagger"
]
}
}
}

View File

@@ -20,7 +20,11 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Themes", "Themes", "{C5891B
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Modules", "Modules", "{3DA05917-02EA-4B04-9C48-B86C77A73584}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Modules", "Modules", "{3DA05917-02EA-4B04-9C48-B86C77A73584}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TailwindTheme", "src\Themes\TailwindTheme\TailwindTheme.csproj", "{4BB167BD-2BC4-4DFB-B1E2-813EC2E2D8FF}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OapTheme", "src\Themes\OapTheme\OapTheme.csproj", "{4BB167BD-2BC4-4DFB-B1E2-813EC2E2D8FF}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OapApi.v1.Client", "src\OapApi.v1.Client\OapApi.v1.Client.csproj", "{5C30AB89-B3D4-468F-A029-3D26FECD0083}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OapApi.v1", "src\Modules\OapApi.v1\OapApi.v1.csproj", "{D414342C-EA8D-4115-BF22-DC8B62FB3CBF}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -48,6 +52,14 @@ Global
{4BB167BD-2BC4-4DFB-B1E2-813EC2E2D8FF}.Debug|Any CPU.Build.0 = Debug|Any CPU {4BB167BD-2BC4-4DFB-B1E2-813EC2E2D8FF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4BB167BD-2BC4-4DFB-B1E2-813EC2E2D8FF}.Release|Any CPU.ActiveCfg = Release|Any CPU {4BB167BD-2BC4-4DFB-B1E2-813EC2E2D8FF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4BB167BD-2BC4-4DFB-B1E2-813EC2E2D8FF}.Release|Any CPU.Build.0 = Release|Any CPU {4BB167BD-2BC4-4DFB-B1E2-813EC2E2D8FF}.Release|Any CPU.Build.0 = Release|Any CPU
{5C30AB89-B3D4-468F-A029-3D26FECD0083}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5C30AB89-B3D4-468F-A029-3D26FECD0083}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5C30AB89-B3D4-468F-A029-3D26FECD0083}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5C30AB89-B3D4-468F-A029-3D26FECD0083}.Release|Any CPU.Build.0 = Release|Any CPU
{D414342C-EA8D-4115-BF22-DC8B62FB3CBF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D414342C-EA8D-4115-BF22-DC8B62FB3CBF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D414342C-EA8D-4115-BF22-DC8B62FB3CBF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D414342C-EA8D-4115-BF22-DC8B62FB3CBF}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@@ -57,6 +69,7 @@ Global
{7B0477DA-BCD5-47ED-8B88-76D046524434} = {3DA05917-02EA-4B04-9C48-B86C77A73584} {7B0477DA-BCD5-47ED-8B88-76D046524434} = {3DA05917-02EA-4B04-9C48-B86C77A73584}
{A7498019-5941-479B-ADB2-56B6C984C608} = {C5891B30-F830-4094-A4D5-E2DB8D9ED819} {A7498019-5941-479B-ADB2-56B6C984C608} = {C5891B30-F830-4094-A4D5-E2DB8D9ED819}
{4BB167BD-2BC4-4DFB-B1E2-813EC2E2D8FF} = {C5891B30-F830-4094-A4D5-E2DB8D9ED819} {4BB167BD-2BC4-4DFB-B1E2-813EC2E2D8FF} = {C5891B30-F830-4094-A4D5-E2DB8D9ED819}
{D414342C-EA8D-4115-BF22-DC8B62FB3CBF} = {3DA05917-02EA-4B04-9C48-B86C77A73584}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {0F7F9D4C-DF95-43AF-9E9A-DA09B5EE03C7} SolutionGuid = {0F7F9D4C-DF95-43AF-9E9A-DA09B5EE03C7}

30
docs/api/OapApiV1.md Normal file
View File

@@ -0,0 +1,30 @@
# OapApiV1
URL: [`https://oaprotection.org/api/v1`](https://oaprotection.org/api/v1)
| method | path | description |
| --- | --- | --- |
| [getApplications](OapApiV1/getApplications.md) | `GET /applications` | Gets applications for the current user. |
| [createApplication](OapApiV1/createApplication.md) | `POST /applications/` | Creates a new application for the current user. |
| [getApplication](OapApiV1/getApplication.md) | `GET /applications/{id}` | Gets the specified application for the current user. |
| [updateApplication](OapApiV1/updateApplication.md) | `PATCH /applications/{id}` | Updates the application. |
| data | description |
| --- | --- |
| [Application](OapApiV1/Application.md) | An application. |
| [ApplicationCreateSet](OapApiV1/ApplicationCreateSet.md) | |
| [ApplicationChangeSet](OapApiV1/ApplicationChangeSet.md) | |
| [ApplicationTermsCreateSet](OapApiV1/ApplicationTermsCreateSet.md) | |
| [ApplicationTerms](OapApiV1/ApplicationTerms.md) | |
| enum | description |
| --- | --- |
| [ApplicationStatus](OapApiV1/ApplicationStatus.md) | |
API providing OAP functionality for the application form, calculator and more.
## Heading
Use a primary heading to indicate the member name.
<!-- DO NOT EDIT: generated by fsdgenmd -->

View File

@@ -0,0 +1,21 @@
# Application
An application.
```
{
"id": "(string)",
"status": "(InProgress|Submitted)",
"terms": { "hasReadInstructions": ... }
}
```
| field | type | description |
| --- | --- | --- |
| id | string | A unique identifier for the application. |
| status | [ApplicationStatus](ApplicationStatus.md) | The current status of this application. |
| terms | [ApplicationTerms](ApplicationTerms.md) | Terms the user must accept to start, continue an accept an application. |
Represents a user's application, whether in progress or submitted.
<!-- DO NOT EDIT: generated by fsdgenmd -->

View File

@@ -0,0 +1,8 @@
# ApplicationChangeSet
```
{
}
```
<!-- DO NOT EDIT: generated by fsdgenmd -->

View File

@@ -0,0 +1,13 @@
# ApplicationCreateSet
```
{
"terms": { "hasReadInstructions": ... }
}
```
| field | type | description |
| --- | --- | --- |
| terms | [ApplicationTermsCreateSet](ApplicationTermsCreateSet.md) | Terms a user must accept to start an application. |
<!-- DO NOT EDIT: generated by fsdgenmd -->

View File

@@ -0,0 +1,8 @@
# ApplicationStatus
| name | description |
| --- | --- |
| InProgress | |
| Submitted | |
<!-- DO NOT EDIT: generated by fsdgenmd -->

View File

@@ -0,0 +1,13 @@
# ApplicationTerms
```
{
"hasReadInstructions": (true|false)
}
```
| field | type | description |
| --- | --- | --- |
| hasReadInstructions | boolean | |
<!-- DO NOT EDIT: generated by fsdgenmd -->

View File

@@ -0,0 +1,13 @@
# ApplicationTermsCreateSet
```
{
"hasReadInstructions": (true|false)
}
```
| field | type | description |
| --- | --- | --- |
| hasReadInstructions | boolean | |
<!-- DO NOT EDIT: generated by fsdgenmd -->

View File

@@ -0,0 +1,23 @@
# createApplication
Creates a new application for the current user.
```
POST /applications/
(applicationCreateSet)
--- 200 OK
(application)
--- 201 Created
```
| request | type | description |
| --- | --- | --- |
| applicationCreateSet | [ApplicationCreateSet](ApplicationCreateSet.md) | The application to create. |
| response | type | description |
| --- | --- | --- |
| application | [Application](Application.md) | The created application. |
Creates a new application for the current user.
<!-- DO NOT EDIT: generated by fsdgenmd -->

View File

@@ -0,0 +1,25 @@
# getApplication
Gets the specified application for the current user.
```
GET /applications/{id}
--- response
eTag: (eTag)
--- 200 OK
(application)
--- 304 Not Modified
(if notModified)
```
| request | type | description |
| --- | --- | --- |
| id | string | The widget ID. |
| response | type | description |
| --- | --- | --- |
| application | [Application](Application.md) | The requested widget. |
| eTag | string | |
| notModified | boolean | |
<!-- DO NOT EDIT: generated by fsdgenmd -->

View File

@@ -0,0 +1,34 @@
# getApplications
Gets applications for the current user.
```
GET /applications
?status={status}
&limit={limit}
&nextToken={nextToken}
--- 200 OK
{
"applications": [ { "id": ... }, ... ],
"total": (integer),
"nextToken": "(string)",
"isLastPage": (true|false)
}
```
| request | type | description |
| --- | --- | --- |
| status | [ApplicationStatus](ApplicationStatus.md) | Filter applications by the given status. |
| limit | int32 | The limit of returned results. |
| nextToken | string | The token presenting the next page of applications to get. |
| response | type | description |
| --- | --- | --- |
| applications | [Application](Application.md)[] | The applications. |
| total | int64 | The total number of applications. |
| nextToken | string | The token representing the next page of results. |
| isLastPage | boolean | True if this is the last page of results, false otherwise. |
Gets the current user's applications in pages.
<!-- DO NOT EDIT: generated by fsdgenmd -->

View File

@@ -0,0 +1,23 @@
# updateApplication
Updates the application.
```
PATCH /applications/{id}
(applicationChangeSet)
--- 200 OK
(application)
```
| request | type | description |
| --- | --- | --- |
| id | string | The application ID. |
| applicationChangeSet | [ApplicationChangeSet](ApplicationChangeSet.md) | The application update set. |
| response | type | description |
| --- | --- | --- |
| application | [Application](Application.md) | The updated Application. |
Updates an application for the current user, given the ID of the application to update.
<!-- DO NOT EDIT: generated by fsdgenmd -->

View File

@@ -0,0 +1,30 @@
# OverseasAutoProtectionApi
URL: [`https://oaprotection.org/api/v1`](https://oaprotection.org/api/v1)
| method | path | description |
| --- | --- | --- |
| [getApplications](OverseasAutoProtectionApi/getApplications.md) | `GET /applications` | Gets applications for the current user. |
| [createApplication](OverseasAutoProtectionApi/createApplication.md) | `POST /applications/` | Creates a new application for the current user. |
| [getApplication](OverseasAutoProtectionApi/getApplication.md) | `GET /applications/{id}` | Gets the specified application for the current user. |
| [updateApplication](OverseasAutoProtectionApi/updateApplication.md) | `PATCH /applications/{id}` | Updates the application. |
| data | description |
| --- | --- |
| [Application](OverseasAutoProtectionApi/Application.md) | An application. |
| [ApplicationCreateSet](OverseasAutoProtectionApi/ApplicationCreateSet.md) | |
| [ApplicationChangeSet](OverseasAutoProtectionApi/ApplicationChangeSet.md) | |
| [ApplicationTermsCreateSet](OverseasAutoProtectionApi/ApplicationTermsCreateSet.md) | |
| [ApplicationTerms](OverseasAutoProtectionApi/ApplicationTerms.md) | |
| enum | description |
| --- | --- |
| [ApplicationStatus](OverseasAutoProtectionApi/ApplicationStatus.md) | |
API providing OAP functionality for the application form, calculator and more.
## Heading
Use a primary heading to indicate the member name.
<!-- DO NOT EDIT: generated by fsdgenmd -->

View File

@@ -0,0 +1,21 @@
# Application
An application.
```
{
"id": "(string)",
"status": "(InProgress|Submitted)",
"terms": { "hasReadInstructions": ... }
}
```
| field | type | description |
| --- | --- | --- |
| id | string | A unique identifier for the application. |
| status | [ApplicationStatus](ApplicationStatus.md) | The current status of this application. |
| terms | [ApplicationTerms](ApplicationTerms.md) | Terms the user must accept to start, continue an accept an application. |
Represents a user's application, whether in progress or submitted.
<!-- DO NOT EDIT: generated by fsdgenmd -->

View File

@@ -0,0 +1,8 @@
# ApplicationChangeSet
```
{
}
```
<!-- DO NOT EDIT: generated by fsdgenmd -->

View File

@@ -0,0 +1,13 @@
# ApplicationCreateSet
```
{
"terms": { "hasReadInstructions": ... }
}
```
| field | type | description |
| --- | --- | --- |
| terms | [ApplicationTermsCreateSet](ApplicationTermsCreateSet.md) | Terms a user must accept to start an application. |
<!-- DO NOT EDIT: generated by fsdgenmd -->

View File

@@ -0,0 +1,8 @@
# ApplicationStatus
| name | description |
| --- | --- |
| InProgress | |
| Submitted | |
<!-- DO NOT EDIT: generated by fsdgenmd -->

View File

@@ -0,0 +1,13 @@
# ApplicationTerms
```
{
"hasReadInstructions": (true|false)
}
```
| field | type | description |
| --- | --- | --- |
| hasReadInstructions | boolean | |
<!-- DO NOT EDIT: generated by fsdgenmd -->

View File

@@ -0,0 +1,13 @@
# ApplicationTermsCreateSet
```
{
"hasReadInstructions": (true|false)
}
```
| field | type | description |
| --- | --- | --- |
| hasReadInstructions | boolean | |
<!-- DO NOT EDIT: generated by fsdgenmd -->

View File

@@ -0,0 +1,23 @@
# createApplication
Creates a new application for the current user.
```
POST /applications/
(applicationCreateSet)
--- 200 OK
(application)
--- 201 Created
```
| request | type | description |
| --- | --- | --- |
| applicationCreateSet | [ApplicationCreateSet](ApplicationCreateSet.md) | The application to create. |
| response | type | description |
| --- | --- | --- |
| application | [Application](Application.md) | The created application. |
Creates a new application for the current user.
<!-- DO NOT EDIT: generated by fsdgenmd -->

View File

@@ -0,0 +1,25 @@
# getApplication
Gets the specified application for the current user.
```
GET /applications/{id}
--- response
eTag: (eTag)
--- 200 OK
(application)
--- 304 Not Modified
(if notModified)
```
| request | type | description |
| --- | --- | --- |
| id | string | The widget ID. |
| response | type | description |
| --- | --- | --- |
| application | [Application](Application.md) | The requested widget. |
| eTag | string | |
| notModified | boolean | |
<!-- DO NOT EDIT: generated by fsdgenmd -->

View File

@@ -0,0 +1,34 @@
# getApplications
Gets applications for the current user.
```
GET /applications
?status={status}
&limit={limit}
&nextToken={nextToken}
--- 200 OK
{
"applications": [ { "id": ... }, ... ],
"total": (integer),
"nextToken": "(string)",
"isLastPage": (true|false)
}
```
| request | type | description |
| --- | --- | --- |
| status | [ApplicationStatus](ApplicationStatus.md) | Filter applications by the given status. |
| limit | int32 | The limit of returned results. |
| nextToken | string | The token presenting the next page of applications to get. |
| response | type | description |
| --- | --- | --- |
| applications | [Application](Application.md)[] | The applications. |
| total | int64 | The total number of applications. |
| nextToken | string | The token representing the next page of results. |
| isLastPage | boolean | True if this is the last page of results, false otherwise. |
Gets the current user's applications in pages.
<!-- DO NOT EDIT: generated by fsdgenmd -->

View File

@@ -0,0 +1,23 @@
# updateApplication
Updates the application.
```
PATCH /applications/{id}
(applicationChangeSet)
--- 200 OK
(application)
```
| request | type | description |
| --- | --- | --- |
| id | string | The application ID. |
| applicationChangeSet | [ApplicationChangeSet](ApplicationChangeSet.md) | The application update set. |
| response | type | description |
| --- | --- | --- |
| application | [Application](Application.md) | The updated Application. |
Updates an application for the current user, given the ID of the application to update.
<!-- DO NOT EDIT: generated by fsdgenmd -->

147
fsd/OapApi.v1.fsd Normal file
View File

@@ -0,0 +1,147 @@
[http(url: "https://oaprotection.org/api/v1")]
[csharp(namespace: OapApi.v1)]
service OapApiV1
{
/// Gets applications for the current user.
[http(method: GET, path: "/applications")]
[tag(name:"bob")]
method getApplications
{
/// Filter applications by the given status.
status: ApplicationStatus;
/// The limit of returned results.
limit: int32;
/// The token presenting the next page of applications to get.
nextToken: string;
}:
{
/// The applications.
applications: Application[];
/// The total number of applications.
total: int64;
/// The token representing the next page of results.
nextToken: string;
/// True if this is the last page of results, false otherwise.
isLastPage: boolean;
}
/// Creates a new application for the current user.
[http(method: POST, path: "/applications/", code: 201)]
method createApplication
{
/// The application to create.
[http(from: body)]
applicationCreateSet: ApplicationCreateSet;
}:
{
/// The created application.
[http(from: body)]
application: Application;
}
/// Gets the specified application for the current user.
[http(method: GET, path: "/applications/{id}")]
method getApplication
{
/// The widget ID.
id: string;
}:
{
/// The requested widget.
[http(from: body)]
application: Application;
[http(from: header)]
eTag: string;
[http(from: body, code: 304)]
notModified: boolean;
}
/// Updates the application.
[http(method: PATCH, path: "/applications/{id}")]
method updateApplication
{
/// The application ID.
id: string;
/// The application update set.
[http(from: body)]
applicationChangeSet: ApplicationChangeSet;
}:
{
/// The updated Application.
[http(from: body, code: 200)]
application: Application;
}
/// An application.
data Application
{
/// A unique identifier for the application.
id: string;
/// The current status of this application.
status: ApplicationStatus;
/// Terms the user must accept to start, continue an accept an application.
terms: ApplicationTerms;
}
data ApplicationCreateSet
{
/// Terms a user must accept to start an application.
terms: ApplicationTermsCreateSet!;
}
data ApplicationChangeSet
{
}
data ApplicationTermsCreateSet
{
hasReadInstructions: boolean!;
}
data ApplicationTerms
{
hasReadInstructions: boolean;
}
enum ApplicationStatus
{
InProgress,
Submitted
}
}
# OapApiV1
API providing OAP functionality for the application form, calculator and more.
## Heading
Use a primary heading to indicate the member name.
# getApplications
Gets the current user's applications in pages.
# createApplication
Creates a new application for the current user.
# updateApplication
Updates an application for the current user, given the ID of the application to update.
# Application
Represents a user's application, whether in progress or submitted.

2
fsdgen.bat Normal file
View File

@@ -0,0 +1,2 @@
fsdgencsharp .\fsd\OapApi.v1.fsd ./src/OapApi.v1.Client --namespace OapApi.v1.Client
fsdgenaspnet .\fsd\OapApi.v1.fsd ./src/Modules/OapApi.v1 --target core --namespace OapApi.v1 --apinamespace OapApi.v1.Client

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>
<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.Theme.Targets" Version="1.8.2" />
<PackageReference Include="OrchardCore.ContentManagement" Version="1.8.2" /> <PackageReference Include="OrchardCore.ContentManagement" Version="1.8.2" />
<PackageReference Include="OrchardCore.DisplayManagement" Version="1.8.2" /> <PackageReference Include="OrchardCore.DisplayManagement" Version="1.8.2" />
@@ -19,6 +24,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Folder Include="Models\" />
<Folder Include="wwwroot\" /> <Folder Include="wwwroot\" />
</ItemGroup> </ItemGroup>

View File

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

View File

@@ -1,14 +1,16 @@
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using OrchardCore.Data.Migration;
using OrchardCore.Modules; using OrchardCore.Modules;
using OrchardCore.ResourceManagement; using OrchardCore.ResourceManagement;
namespace TailwindTheme; namespace OapTheme;
public class Startup : StartupBase 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" %} {% 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: "HeadLink" %}
{% resources type: "Stylesheet" %} {% resources type: "Stylesheet" %}

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> <ItemGroup>
<ProjectReference Include="..\Modules\MarkdownImport\MarkdownImport.csproj" /> <ProjectReference Include="..\Modules\MarkdownImport\MarkdownImport.csproj" />
<ProjectReference Include="..\Modules\OapApi.v1\OapApi.v1.csproj" />
<ProjectReference Include="..\Themes\BenRameyTheme\BenRameyTheme.csproj" /> <ProjectReference Include="..\Themes\BenRameyTheme\BenRameyTheme.csproj" />
<ProjectReference Include="..\Themes\TailwindTheme\TailwindTheme.csproj" /> <ProjectReference Include="..\Themes\OapTheme\OapTheme.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

71
tools/Build/Build.cs Normal file
View File

@@ -0,0 +1,71 @@
using Faithlife.Build;
using NuGet.Configuration;
using NuGet.Versioning;
using static Faithlife.Build.DotNetRunner;
internal static class Build
{
public static int Main(string[] args) => BuildRunner.Execute(args, build =>
{
var artifactDirOption = build.AddOption("--artifact-dir <directory>", "Artifact directory", defaultValue: "artifacts");
var dotNetSettings = new DotNetBuildSettings();
build.AddDotNetTargets(dotNetSettings);
build.Target("deployment-package")
.DependsOn("test")
.Describe("Creates the deployment package")
.Does(() =>
{
var projectPath = Path.Combine("src", "Twain.Web", "Twain.Web.csproj");
if (artifactDirOption.Value != null)
DeleteDirectory(artifactDirOption.Value);
RunDotNet(new[]
{
"publish", projectPath,
"-c", dotNetSettings.GetConfiguration(),
"-o", artifactDirOption.Value,
dotNetSettings.GetPlatformArg(),
"--no-build",
dotNetSettings.GetVerbosityArg(),
dotNetSettings.GetMaxCpuCountArg()
});
});
build.Target("codegen")
.DependsOn("restore")
.Describe("Generates code from the FSD")
.Does(() => CodeGen(verify: false));
build.Target("verify-codegen")
.DependsOn("restore")
.Describe("Ensures that the generated code is up-to-date")
.Does(() => CodeGen(verify: true));
build.Target("build")
.DependsOn("verify-codegen");
void CodeGen(bool verify)
{
const string slash = "/";
const string fsdFilePath = "fsd/OapApi.v1.fsd";
const string clientProject = "OapApi.v1.Client";
const string webApiProject = "OapApi.v1";
var csharpCodeGenerator = DotNetLocalTool.Create("fsdgencsharp");
var aspnetCodeGenerator = DotNetLocalTool.Create("fsdgenaspnet");
var mdCodeGenerator = DotNetLocalTool.Create("fsdgenmd");
var swaggerCodeGenerator = DotNetLocalTool.Create("fsdgenswagger");
var verifyOption = verify ? "--verify" : null;
csharpCodeGenerator.Run(fsdFilePath, Path.Combine("src", clientProject) + slash, "--namespace", clientProject, "--clean", "--newline", "lf", verifyOption);
aspnetCodeGenerator.Run(fsdFilePath, Path.Combine("src", "Modules", webApiProject, "Controllers"), "--namespace", $"{webApiProject}.Controllers", "--newline", "lf", verifyOption, "--target", "core");
mdCodeGenerator.Run(fsdFilePath, Path.Combine("docs", "api") + slash, "--clean", "--newline", "lf", verifyOption);
swaggerCodeGenerator.Run(fsdFilePath, Path.Combine("src", "Modules", webApiProject, "swagger.json"), "--json", "--newline", "lf", verifyOption);
}
});
}

View File

@@ -1,36 +0,0 @@
using Faithlife.Build;
using static Faithlife.Build.DotNetRunner;
internal static class Build
{
public static int Main(string[] args) => BuildRunner.Execute(args, build =>
{
var artifactDirOption = build.AddOption("--artifact-dir <directory>", "Artifact directory", defaultValue: "artifacts");
var dotNetSettings = new DotNetBuildSettings();
build.AddDotNetTargets(dotNetSettings);
build.Target("deployment-package")
.DependsOn("test")
.Describe("Creates the deployment package")
.Does(() =>
{
var projectPath = Path.Combine("src", "Twain.Web", "Twain.Web.csproj");
if (artifactDirOption.Value != null)
DeleteDirectory(artifactDirOption.Value);
RunDotNet(new[]
{
"publish", projectPath,
"-c", dotNetSettings.GetConfiguration(),
"-o", artifactDirOption.Value,
dotNetSettings.GetPlatformArg(),
"--no-build",
dotNetSettings.GetVerbosityArg(),
dotNetSettings.GetMaxCpuCountArg()
});
});
});
}