diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json new file mode 100644 index 0000000..cacac73 --- /dev/null +++ b/.config/dotnet-tools.json @@ -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" + ] + } + } +} \ No newline at end of file diff --git a/Twain.sln b/Twain.sln index 03bed73..791f2b7 100644 --- a/Twain.sln +++ b/Twain.sln @@ -20,7 +20,11 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Themes", "Themes", "{C5891B EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Modules", "Modules", "{3DA05917-02EA-4B04-9C48-B86C77A73584}" 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 Global 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}.Release|Any CPU.ActiveCfg = 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 GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -57,6 +69,7 @@ Global {7B0477DA-BCD5-47ED-8B88-76D046524434} = {3DA05917-02EA-4B04-9C48-B86C77A73584} {A7498019-5941-479B-ADB2-56B6C984C608} = {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 GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {0F7F9D4C-DF95-43AF-9E9A-DA09B5EE03C7} diff --git a/docs/api/OapApiV1.md b/docs/api/OapApiV1.md new file mode 100644 index 0000000..187b96e --- /dev/null +++ b/docs/api/OapApiV1.md @@ -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. + + diff --git a/docs/api/OapApiV1/Application.md b/docs/api/OapApiV1/Application.md new file mode 100644 index 0000000..6f3bafc --- /dev/null +++ b/docs/api/OapApiV1/Application.md @@ -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. + + diff --git a/docs/api/OapApiV1/ApplicationChangeSet.md b/docs/api/OapApiV1/ApplicationChangeSet.md new file mode 100644 index 0000000..3f54c93 --- /dev/null +++ b/docs/api/OapApiV1/ApplicationChangeSet.md @@ -0,0 +1,8 @@ +# ApplicationChangeSet + +``` +{ +} +``` + + diff --git a/docs/api/OapApiV1/ApplicationCreateSet.md b/docs/api/OapApiV1/ApplicationCreateSet.md new file mode 100644 index 0000000..07a38b3 --- /dev/null +++ b/docs/api/OapApiV1/ApplicationCreateSet.md @@ -0,0 +1,13 @@ +# ApplicationCreateSet + +``` +{ + "terms": { "hasReadInstructions": ... } +} +``` + +| field | type | description | +| --- | --- | --- | +| terms | [ApplicationTermsCreateSet](ApplicationTermsCreateSet.md) | Terms a user must accept to start an application. | + + diff --git a/docs/api/OapApiV1/ApplicationStatus.md b/docs/api/OapApiV1/ApplicationStatus.md new file mode 100644 index 0000000..9a7c0d6 --- /dev/null +++ b/docs/api/OapApiV1/ApplicationStatus.md @@ -0,0 +1,8 @@ +# ApplicationStatus + +| name | description | +| --- | --- | +| InProgress | | +| Submitted | | + + diff --git a/docs/api/OapApiV1/ApplicationTerms.md b/docs/api/OapApiV1/ApplicationTerms.md new file mode 100644 index 0000000..d101513 --- /dev/null +++ b/docs/api/OapApiV1/ApplicationTerms.md @@ -0,0 +1,13 @@ +# ApplicationTerms + +``` +{ + "hasReadInstructions": (true|false) +} +``` + +| field | type | description | +| --- | --- | --- | +| hasReadInstructions | boolean | | + + diff --git a/docs/api/OapApiV1/ApplicationTermsCreateSet.md b/docs/api/OapApiV1/ApplicationTermsCreateSet.md new file mode 100644 index 0000000..dde7333 --- /dev/null +++ b/docs/api/OapApiV1/ApplicationTermsCreateSet.md @@ -0,0 +1,13 @@ +# ApplicationTermsCreateSet + +``` +{ + "hasReadInstructions": (true|false) +} +``` + +| field | type | description | +| --- | --- | --- | +| hasReadInstructions | boolean | | + + diff --git a/docs/api/OapApiV1/createApplication.md b/docs/api/OapApiV1/createApplication.md new file mode 100644 index 0000000..8b9b91e --- /dev/null +++ b/docs/api/OapApiV1/createApplication.md @@ -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. + + diff --git a/docs/api/OapApiV1/getApplication.md b/docs/api/OapApiV1/getApplication.md new file mode 100644 index 0000000..954a1c8 --- /dev/null +++ b/docs/api/OapApiV1/getApplication.md @@ -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 | | + + diff --git a/docs/api/OapApiV1/getApplications.md b/docs/api/OapApiV1/getApplications.md new file mode 100644 index 0000000..a16339c --- /dev/null +++ b/docs/api/OapApiV1/getApplications.md @@ -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. + + diff --git a/docs/api/OapApiV1/updateApplication.md b/docs/api/OapApiV1/updateApplication.md new file mode 100644 index 0000000..9f9a96f --- /dev/null +++ b/docs/api/OapApiV1/updateApplication.md @@ -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. + + diff --git a/docs/api/OverseasAutoProtectionApi.md b/docs/api/OverseasAutoProtectionApi.md new file mode 100644 index 0000000..9d74635 --- /dev/null +++ b/docs/api/OverseasAutoProtectionApi.md @@ -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. + + diff --git a/docs/api/OverseasAutoProtectionApi/Application.md b/docs/api/OverseasAutoProtectionApi/Application.md new file mode 100644 index 0000000..6f3bafc --- /dev/null +++ b/docs/api/OverseasAutoProtectionApi/Application.md @@ -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. + + diff --git a/docs/api/OverseasAutoProtectionApi/ApplicationChangeSet.md b/docs/api/OverseasAutoProtectionApi/ApplicationChangeSet.md new file mode 100644 index 0000000..3f54c93 --- /dev/null +++ b/docs/api/OverseasAutoProtectionApi/ApplicationChangeSet.md @@ -0,0 +1,8 @@ +# ApplicationChangeSet + +``` +{ +} +``` + + diff --git a/docs/api/OverseasAutoProtectionApi/ApplicationCreateSet.md b/docs/api/OverseasAutoProtectionApi/ApplicationCreateSet.md new file mode 100644 index 0000000..07a38b3 --- /dev/null +++ b/docs/api/OverseasAutoProtectionApi/ApplicationCreateSet.md @@ -0,0 +1,13 @@ +# ApplicationCreateSet + +``` +{ + "terms": { "hasReadInstructions": ... } +} +``` + +| field | type | description | +| --- | --- | --- | +| terms | [ApplicationTermsCreateSet](ApplicationTermsCreateSet.md) | Terms a user must accept to start an application. | + + diff --git a/docs/api/OverseasAutoProtectionApi/ApplicationStatus.md b/docs/api/OverseasAutoProtectionApi/ApplicationStatus.md new file mode 100644 index 0000000..9a7c0d6 --- /dev/null +++ b/docs/api/OverseasAutoProtectionApi/ApplicationStatus.md @@ -0,0 +1,8 @@ +# ApplicationStatus + +| name | description | +| --- | --- | +| InProgress | | +| Submitted | | + + diff --git a/docs/api/OverseasAutoProtectionApi/ApplicationTerms.md b/docs/api/OverseasAutoProtectionApi/ApplicationTerms.md new file mode 100644 index 0000000..d101513 --- /dev/null +++ b/docs/api/OverseasAutoProtectionApi/ApplicationTerms.md @@ -0,0 +1,13 @@ +# ApplicationTerms + +``` +{ + "hasReadInstructions": (true|false) +} +``` + +| field | type | description | +| --- | --- | --- | +| hasReadInstructions | boolean | | + + diff --git a/docs/api/OverseasAutoProtectionApi/ApplicationTermsCreateSet.md b/docs/api/OverseasAutoProtectionApi/ApplicationTermsCreateSet.md new file mode 100644 index 0000000..dde7333 --- /dev/null +++ b/docs/api/OverseasAutoProtectionApi/ApplicationTermsCreateSet.md @@ -0,0 +1,13 @@ +# ApplicationTermsCreateSet + +``` +{ + "hasReadInstructions": (true|false) +} +``` + +| field | type | description | +| --- | --- | --- | +| hasReadInstructions | boolean | | + + diff --git a/docs/api/OverseasAutoProtectionApi/createApplication.md b/docs/api/OverseasAutoProtectionApi/createApplication.md new file mode 100644 index 0000000..8b9b91e --- /dev/null +++ b/docs/api/OverseasAutoProtectionApi/createApplication.md @@ -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. + + diff --git a/docs/api/OverseasAutoProtectionApi/getApplication.md b/docs/api/OverseasAutoProtectionApi/getApplication.md new file mode 100644 index 0000000..954a1c8 --- /dev/null +++ b/docs/api/OverseasAutoProtectionApi/getApplication.md @@ -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 | | + + diff --git a/docs/api/OverseasAutoProtectionApi/getApplications.md b/docs/api/OverseasAutoProtectionApi/getApplications.md new file mode 100644 index 0000000..a16339c --- /dev/null +++ b/docs/api/OverseasAutoProtectionApi/getApplications.md @@ -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. + + diff --git a/docs/api/OverseasAutoProtectionApi/updateApplication.md b/docs/api/OverseasAutoProtectionApi/updateApplication.md new file mode 100644 index 0000000..9f9a96f --- /dev/null +++ b/docs/api/OverseasAutoProtectionApi/updateApplication.md @@ -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. + + diff --git a/fsd/OapApi.v1.fsd b/fsd/OapApi.v1.fsd new file mode 100644 index 0000000..122409c --- /dev/null +++ b/fsd/OapApi.v1.fsd @@ -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. + + diff --git a/fsdgen.bat b/fsdgen.bat new file mode 100644 index 0000000..7a98bd8 --- /dev/null +++ b/fsdgen.bat @@ -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 \ No newline at end of file diff --git a/src/Modules/OapApi.v1/Manifest.cs b/src/Modules/OapApi.v1/Manifest.cs new file mode 100644 index 0000000..049eea5 --- /dev/null +++ b/src/Modules/OapApi.v1/Manifest.cs @@ -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" +)] + \ No newline at end of file diff --git a/src/Modules/OapApi.v1/OapApi.v1.csproj b/src/Modules/OapApi.v1/OapApi.v1.csproj new file mode 100644 index 0000000..d54a45c --- /dev/null +++ b/src/Modules/OapApi.v1/OapApi.v1.csproj @@ -0,0 +1,24 @@ + + + + net8.0 + enable + enable + true + + + + + + + + + + + + + + + + + diff --git a/src/Modules/OapApi.v1/OapApiV1.cs b/src/Modules/OapApi.v1/OapApiV1.cs new file mode 100644 index 0000000..f9123bf --- /dev/null +++ b/src/Modules/OapApi.v1/OapApiV1.cs @@ -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> CreateApplicationAsync(CreateApplicationRequestDto request, CancellationToken cancellationToken = default) => throw new NotImplementedException(); + + public Task> 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> GetApplicationsAsync(GetApplicationsRequestDto request, CancellationToken cancellationToken = default) => throw new NotImplementedException(); + + public Task> UpdateApplicationAsync(UpdateApplicationRequestDto request, CancellationToken cancellationToken = default) => throw new NotImplementedException(); +} diff --git a/src/Modules/OapApi.v1/Startup.cs b/src/Modules/OapApi.v1/Startup.cs new file mode 100644 index 0000000..1177aad --- /dev/null +++ b/src/Modules/OapApi.v1/Startup.cs @@ -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(); + + services.AddScoped(sp => + { + return new OapApiV1HttpHandler( + sp.GetRequiredService(), + new ServiceHttpHandlerSettings + { + RootPath = "/oap/api/v1", + }); + }); + } + + public override void Configure(IApplicationBuilder builder, IEndpointRouteBuilder routes, IServiceProvider serviceProvider) + { + builder.UseFacilityExceptionHandler(); + builder.UseFacilityHttpHandler(); + } + } +} diff --git a/src/Modules/OapApi.v1/swagger.json b/src/Modules/OapApi.v1/swagger.json new file mode 100644 index 0000000..854fafc --- /dev/null +++ b/src/Modules/OapApi.v1/swagger.json @@ -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" + } + } + } + } +} \ No newline at end of file diff --git a/src/OapApi.v1.Client/ApplicationChangeSetDto.g.cs b/src/OapApi.v1.Client/ApplicationChangeSetDto.g.cs new file mode 100644 index 0000000..fec4274 --- /dev/null +++ b/src/OapApi.v1.Client/ApplicationChangeSetDto.g.cs @@ -0,0 +1,33 @@ +// +// DO NOT EDIT: generated by fsdgencsharp +// +using System; +using System.Collections.Generic; +using Facility.Core; + +namespace OapApi.v1.Client +{ + [System.CodeDom.Compiler.GeneratedCode("fsdgencsharp", "")] + public sealed partial class ApplicationChangeSetDto : ServiceDto + { + /// + /// Creates an instance. + /// + public ApplicationChangeSetDto() + { + } + + /// + /// The JSON serializer. + /// + protected override JsonServiceSerializer JsonSerializer => SystemTextJsonServiceSerializer.Instance; + + /// + /// Determines if two DTOs are equivalent. + /// + public override bool IsEquivalentTo(ApplicationChangeSetDto other) + { + return other != null; + } + } +} diff --git a/src/OapApi.v1.Client/ApplicationCreateSetDto.g.cs b/src/OapApi.v1.Client/ApplicationCreateSetDto.g.cs new file mode 100644 index 0000000..158c184 --- /dev/null +++ b/src/OapApi.v1.Client/ApplicationCreateSetDto.g.cs @@ -0,0 +1,60 @@ +// +// DO NOT EDIT: generated by fsdgencsharp +// +using System; +using System.Collections.Generic; +using Facility.Core; + +namespace OapApi.v1.Client +{ + [System.CodeDom.Compiler.GeneratedCode("fsdgencsharp", "")] + public sealed partial class ApplicationCreateSetDto : ServiceDto + { + /// + /// Creates an instance. + /// + public ApplicationCreateSetDto() + { + } + + /// + /// Terms a user must accept to start an application. + /// + public ApplicationTermsCreateSetDto Terms { get; set; } + + /// + /// The JSON serializer. + /// + protected override JsonServiceSerializer JsonSerializer => SystemTextJsonServiceSerializer.Instance; + + /// + /// Determines if two DTOs are equivalent. + /// + public override bool IsEquivalentTo(ApplicationCreateSetDto other) + { + return other != null && + ServiceDataUtility.AreEquivalentDtos(Terms, other.Terms); + } + + /// + /// Validates the DTO. + /// + 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; + } + } +} diff --git a/src/OapApi.v1.Client/ApplicationDto.g.cs b/src/OapApi.v1.Client/ApplicationDto.g.cs new file mode 100644 index 0000000..70f15ed --- /dev/null +++ b/src/OapApi.v1.Client/ApplicationDto.g.cs @@ -0,0 +1,54 @@ +// +// DO NOT EDIT: generated by fsdgencsharp +// +using System; +using System.Collections.Generic; +using Facility.Core; + +namespace OapApi.v1.Client +{ + /// + /// An application. + /// + [System.CodeDom.Compiler.GeneratedCode("fsdgencsharp", "")] + public sealed partial class ApplicationDto : ServiceDto + { + /// + /// Creates an instance. + /// + public ApplicationDto() + { + } + + /// + /// A unique identifier for the application. + /// + public string Id { get; set; } + + /// + /// The current status of this application. + /// + public ApplicationStatus? Status { get; set; } + + /// + /// Terms the user must accept to start, continue an accept an application. + /// + public ApplicationTermsDto Terms { get; set; } + + /// + /// The JSON serializer. + /// + protected override JsonServiceSerializer JsonSerializer => SystemTextJsonServiceSerializer.Instance; + + /// + /// Determines if two DTOs are equivalent. + /// + public override bool IsEquivalentTo(ApplicationDto other) + { + return other != null && + Id == other.Id && + Status == other.Status && + ServiceDataUtility.AreEquivalentDtos(Terms, other.Terms); + } + } +} diff --git a/src/OapApi.v1.Client/ApplicationStatus.g.cs b/src/OapApi.v1.Client/ApplicationStatus.g.cs new file mode 100644 index 0000000..1e28627 --- /dev/null +++ b/src/OapApi.v1.Client/ApplicationStatus.g.cs @@ -0,0 +1,112 @@ +// +// DO NOT EDIT: generated by fsdgencsharp +// +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 + { + public static readonly ApplicationStatus InProgress = new ApplicationStatus(Strings.InProgress); + + public static readonly ApplicationStatus Submitted = new ApplicationStatus(Strings.Submitted); + + /// + /// Creates an instance. + /// + public ApplicationStatus(string value) => m_value = value; + + /// + /// Converts the instance to a string. + /// + public override string ToString() => m_value != null && s_valueCache.TryGetValue(m_value, out var cachedValue) ? cachedValue : m_value ?? ""; + + /// + /// Checks for equality. + /// + public bool Equals(ApplicationStatus other) => StringComparer.OrdinalIgnoreCase.Equals(m_value ?? "", other.m_value ?? ""); + + /// + /// Checks for equality. + /// + public override bool Equals(object obj) => obj is ApplicationStatus && Equals((ApplicationStatus) obj); + + /// + /// Gets the hash code. + /// + public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(m_value ?? ""); + + /// + /// Checks for equality. + /// + public static bool operator ==(ApplicationStatus left, ApplicationStatus right) => left.Equals(right); + + /// + /// Checks for inequality. + /// + public static bool operator !=(ApplicationStatus left, ApplicationStatus right) => !left.Equals(right); + + /// + /// Returns true if the instance is equal to one of the defined values. + /// + public bool IsDefined() => m_value != null && s_valueCache.ContainsKey(m_value); + + /// + /// Returns all of the defined values. + /// + public static IReadOnlyList GetValues() => s_values; + + /// + /// Provides string constants for defined values. + /// + public static class Strings + { + public const string InProgress = "InProgress"; + + public const string Submitted = "Submitted"; + } + + /// + /// Used for serialization. + /// + public sealed class ApplicationStatusJsonConverter : ServiceEnumJsonConverter + { + /// + /// Creates the value from a string. + /// + protected override ApplicationStatus CreateCore(string value) => new ApplicationStatus(value); + } + + /// + /// Used for serialization. + /// + public sealed class ApplicationStatusSystemTextJsonConverter : ServiceEnumSystemTextJsonConverter + { + /// + /// Creates the value from a string. + /// + protected override ApplicationStatus CreateCore(string value) => new ApplicationStatus(value); + } + + private static readonly ReadOnlyCollection s_values = new ReadOnlyCollection( + new[] + { + InProgress, + Submitted, + }); + + private static readonly IReadOnlyDictionary s_valueCache = new Dictionary(StringComparer.OrdinalIgnoreCase) + { + { Strings.InProgress, Strings.InProgress }, + { Strings.Submitted, Strings.Submitted }, + }; + + private readonly string m_value; + } +} diff --git a/src/OapApi.v1.Client/ApplicationTermsCreateSetDto.g.cs b/src/OapApi.v1.Client/ApplicationTermsCreateSetDto.g.cs new file mode 100644 index 0000000..6d557f9 --- /dev/null +++ b/src/OapApi.v1.Client/ApplicationTermsCreateSetDto.g.cs @@ -0,0 +1,53 @@ +// +// DO NOT EDIT: generated by fsdgencsharp +// +using System; +using System.Collections.Generic; +using Facility.Core; + +namespace OapApi.v1.Client +{ + [System.CodeDom.Compiler.GeneratedCode("fsdgencsharp", "")] + public sealed partial class ApplicationTermsCreateSetDto : ServiceDto + { + /// + /// Creates an instance. + /// + public ApplicationTermsCreateSetDto() + { + } + + public bool? HasReadInstructions { get; set; } + + /// + /// The JSON serializer. + /// + protected override JsonServiceSerializer JsonSerializer => SystemTextJsonServiceSerializer.Instance; + + /// + /// Determines if two DTOs are equivalent. + /// + public override bool IsEquivalentTo(ApplicationTermsCreateSetDto other) + { + return other != null && + HasReadInstructions == other.HasReadInstructions; + } + + /// + /// Validates the DTO. + /// + public override bool Validate(out string errorMessage) + { + errorMessage = GetValidationErrorMessage(); + return errorMessage == null; + } + + private string GetValidationErrorMessage() + { + if (HasReadInstructions == null) + return ServiceDataUtility.GetRequiredFieldErrorMessage("hasReadInstructions"); + + return null; + } + } +} diff --git a/src/OapApi.v1.Client/ApplicationTermsDto.g.cs b/src/OapApi.v1.Client/ApplicationTermsDto.g.cs new file mode 100644 index 0000000..6083908 --- /dev/null +++ b/src/OapApi.v1.Client/ApplicationTermsDto.g.cs @@ -0,0 +1,36 @@ +// +// DO NOT EDIT: generated by fsdgencsharp +// +using System; +using System.Collections.Generic; +using Facility.Core; + +namespace OapApi.v1.Client +{ + [System.CodeDom.Compiler.GeneratedCode("fsdgencsharp", "")] + public sealed partial class ApplicationTermsDto : ServiceDto + { + /// + /// Creates an instance. + /// + public ApplicationTermsDto() + { + } + + public bool? HasReadInstructions { get; set; } + + /// + /// The JSON serializer. + /// + protected override JsonServiceSerializer JsonSerializer => SystemTextJsonServiceSerializer.Instance; + + /// + /// Determines if two DTOs are equivalent. + /// + public override bool IsEquivalentTo(ApplicationTermsDto other) + { + return other != null && + HasReadInstructions == other.HasReadInstructions; + } + } +} diff --git a/src/OapApi.v1.Client/CreateApplicationRequestDto.g.cs b/src/OapApi.v1.Client/CreateApplicationRequestDto.g.cs new file mode 100644 index 0000000..bef903e --- /dev/null +++ b/src/OapApi.v1.Client/CreateApplicationRequestDto.g.cs @@ -0,0 +1,60 @@ +// +// DO NOT EDIT: generated by fsdgencsharp +// +using System; +using System.Collections.Generic; +using Facility.Core; + +namespace OapApi.v1.Client +{ + /// + /// Request for CreateApplication. + /// + [System.CodeDom.Compiler.GeneratedCode("fsdgencsharp", "")] + public sealed partial class CreateApplicationRequestDto : ServiceDto + { + /// + /// Creates an instance. + /// + public CreateApplicationRequestDto() + { + } + + /// + /// The application to create. + /// + public ApplicationCreateSetDto ApplicationCreateSet { get; set; } + + /// + /// The JSON serializer. + /// + protected override JsonServiceSerializer JsonSerializer => SystemTextJsonServiceSerializer.Instance; + + /// + /// Determines if two DTOs are equivalent. + /// + public override bool IsEquivalentTo(CreateApplicationRequestDto other) + { + return other != null && + ServiceDataUtility.AreEquivalentDtos(ApplicationCreateSet, other.ApplicationCreateSet); + } + + /// + /// Validates the DTO. + /// + 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; + } + } +} diff --git a/src/OapApi.v1.Client/CreateApplicationResponseDto.g.cs b/src/OapApi.v1.Client/CreateApplicationResponseDto.g.cs new file mode 100644 index 0000000..f67a50d --- /dev/null +++ b/src/OapApi.v1.Client/CreateApplicationResponseDto.g.cs @@ -0,0 +1,42 @@ +// +// DO NOT EDIT: generated by fsdgencsharp +// +using System; +using System.Collections.Generic; +using Facility.Core; + +namespace OapApi.v1.Client +{ + /// + /// Response for CreateApplication. + /// + [System.CodeDom.Compiler.GeneratedCode("fsdgencsharp", "")] + public sealed partial class CreateApplicationResponseDto : ServiceDto + { + /// + /// Creates an instance. + /// + public CreateApplicationResponseDto() + { + } + + /// + /// The created application. + /// + public ApplicationDto Application { get; set; } + + /// + /// The JSON serializer. + /// + protected override JsonServiceSerializer JsonSerializer => SystemTextJsonServiceSerializer.Instance; + + /// + /// Determines if two DTOs are equivalent. + /// + public override bool IsEquivalentTo(CreateApplicationResponseDto other) + { + return other != null && + ServiceDataUtility.AreEquivalentDtos(Application, other.Application); + } + } +} diff --git a/src/OapApi.v1.Client/DelegatingOapApiV1.g.cs b/src/OapApi.v1.Client/DelegatingOapApiV1.g.cs new file mode 100644 index 0000000..801f1cb --- /dev/null +++ b/src/OapApi.v1.Client/DelegatingOapApiV1.g.cs @@ -0,0 +1,49 @@ +// +// DO NOT EDIT: generated by fsdgencsharp +// +using System; +using System.Threading; +using System.Threading.Tasks; +using Facility.Core; + +namespace OapApi.v1.Client +{ + /// + /// A delegating implementation of OapApiV1. + /// + [System.CodeDom.Compiler.GeneratedCode("fsdgencsharp", "")] + public partial class DelegatingOapApiV1 : IOapApiV1 + { + /// + /// Creates an instance with the specified delegator. + /// + public DelegatingOapApiV1(ServiceDelegator delegator) => + m_delegator = delegator ?? throw new ArgumentNullException(nameof(delegator)); + + /// + /// Gets applications for the current user. + /// + public virtual async Task> GetApplicationsAsync(GetApplicationsRequestDto request, CancellationToken cancellationToken = default) => + (await m_delegator(OapApiV1Methods.GetApplications, request, cancellationToken).ConfigureAwait(false)).Cast(); + + /// + /// Creates a new application for the current user. + /// + public virtual async Task> CreateApplicationAsync(CreateApplicationRequestDto request, CancellationToken cancellationToken = default) => + (await m_delegator(OapApiV1Methods.CreateApplication, request, cancellationToken).ConfigureAwait(false)).Cast(); + + /// + /// Gets the specified application for the current user. + /// + public virtual async Task> GetApplicationAsync(GetApplicationRequestDto request, CancellationToken cancellationToken = default) => + (await m_delegator(OapApiV1Methods.GetApplication, request, cancellationToken).ConfigureAwait(false)).Cast(); + + /// + /// Updates the application. + /// + public virtual async Task> UpdateApplicationAsync(UpdateApplicationRequestDto request, CancellationToken cancellationToken = default) => + (await m_delegator(OapApiV1Methods.UpdateApplication, request, cancellationToken).ConfigureAwait(false)).Cast(); + + private readonly ServiceDelegator m_delegator; + } +} diff --git a/src/OapApi.v1.Client/GetApplicationRequestDto.g.cs b/src/OapApi.v1.Client/GetApplicationRequestDto.g.cs new file mode 100644 index 0000000..009a605 --- /dev/null +++ b/src/OapApi.v1.Client/GetApplicationRequestDto.g.cs @@ -0,0 +1,42 @@ +// +// DO NOT EDIT: generated by fsdgencsharp +// +using System; +using System.Collections.Generic; +using Facility.Core; + +namespace OapApi.v1.Client +{ + /// + /// Request for GetApplication. + /// + [System.CodeDom.Compiler.GeneratedCode("fsdgencsharp", "")] + public sealed partial class GetApplicationRequestDto : ServiceDto + { + /// + /// Creates an instance. + /// + public GetApplicationRequestDto() + { + } + + /// + /// The widget ID. + /// + public string Id { get; set; } + + /// + /// The JSON serializer. + /// + protected override JsonServiceSerializer JsonSerializer => SystemTextJsonServiceSerializer.Instance; + + /// + /// Determines if two DTOs are equivalent. + /// + public override bool IsEquivalentTo(GetApplicationRequestDto other) + { + return other != null && + Id == other.Id; + } + } +} diff --git a/src/OapApi.v1.Client/GetApplicationResponseDto.g.cs b/src/OapApi.v1.Client/GetApplicationResponseDto.g.cs new file mode 100644 index 0000000..2d7baac --- /dev/null +++ b/src/OapApi.v1.Client/GetApplicationResponseDto.g.cs @@ -0,0 +1,48 @@ +// +// DO NOT EDIT: generated by fsdgencsharp +// +using System; +using System.Collections.Generic; +using Facility.Core; + +namespace OapApi.v1.Client +{ + /// + /// Response for GetApplication. + /// + [System.CodeDom.Compiler.GeneratedCode("fsdgencsharp", "")] + public sealed partial class GetApplicationResponseDto : ServiceDto + { + /// + /// Creates an instance. + /// + public GetApplicationResponseDto() + { + } + + /// + /// The requested widget. + /// + public ApplicationDto Application { get; set; } + + public string ETag { get; set; } + + public bool? NotModified { get; set; } + + /// + /// The JSON serializer. + /// + protected override JsonServiceSerializer JsonSerializer => SystemTextJsonServiceSerializer.Instance; + + /// + /// Determines if two DTOs are equivalent. + /// + public override bool IsEquivalentTo(GetApplicationResponseDto other) + { + return other != null && + ServiceDataUtility.AreEquivalentDtos(Application, other.Application) && + ETag == other.ETag && + NotModified == other.NotModified; + } + } +} diff --git a/src/OapApi.v1.Client/GetApplicationsRequestDto.g.cs b/src/OapApi.v1.Client/GetApplicationsRequestDto.g.cs new file mode 100644 index 0000000..494b8d2 --- /dev/null +++ b/src/OapApi.v1.Client/GetApplicationsRequestDto.g.cs @@ -0,0 +1,54 @@ +// +// DO NOT EDIT: generated by fsdgencsharp +// +using System; +using System.Collections.Generic; +using Facility.Core; + +namespace OapApi.v1.Client +{ + /// + /// Request for GetApplications. + /// + [System.CodeDom.Compiler.GeneratedCode("fsdgencsharp", "")] + public sealed partial class GetApplicationsRequestDto : ServiceDto + { + /// + /// Creates an instance. + /// + public GetApplicationsRequestDto() + { + } + + /// + /// Filter applications by the given status. + /// + public ApplicationStatus? Status { get; set; } + + /// + /// The limit of returned results. + /// + public int? Limit { get; set; } + + /// + /// The token presenting the next page of applications to get. + /// + public string NextToken { get; set; } + + /// + /// The JSON serializer. + /// + protected override JsonServiceSerializer JsonSerializer => SystemTextJsonServiceSerializer.Instance; + + /// + /// Determines if two DTOs are equivalent. + /// + public override bool IsEquivalentTo(GetApplicationsRequestDto other) + { + return other != null && + Status == other.Status && + Limit == other.Limit && + NextToken == other.NextToken; + } + } +} diff --git a/src/OapApi.v1.Client/GetApplicationsResponseDto.g.cs b/src/OapApi.v1.Client/GetApplicationsResponseDto.g.cs new file mode 100644 index 0000000..b0076f9 --- /dev/null +++ b/src/OapApi.v1.Client/GetApplicationsResponseDto.g.cs @@ -0,0 +1,60 @@ +// +// DO NOT EDIT: generated by fsdgencsharp +// +using System; +using System.Collections.Generic; +using Facility.Core; + +namespace OapApi.v1.Client +{ + /// + /// Response for GetApplications. + /// + [System.CodeDom.Compiler.GeneratedCode("fsdgencsharp", "")] + public sealed partial class GetApplicationsResponseDto : ServiceDto + { + /// + /// Creates an instance. + /// + public GetApplicationsResponseDto() + { + } + + /// + /// The applications. + /// + public IReadOnlyList Applications { get; set; } + + /// + /// The total number of applications. + /// + public long? Total { get; set; } + + /// + /// The token representing the next page of results. + /// + public string NextToken { get; set; } + + /// + /// True if this is the last page of results, false otherwise. + /// + public bool? IsLastPage { get; set; } + + /// + /// The JSON serializer. + /// + protected override JsonServiceSerializer JsonSerializer => SystemTextJsonServiceSerializer.Instance; + + /// + /// Determines if two DTOs are equivalent. + /// + public override bool IsEquivalentTo(GetApplicationsResponseDto other) + { + return other != null && + ServiceDataUtility.AreEquivalentFieldValues(Applications, other.Applications) && + Total == other.Total && + NextToken == other.NextToken && + IsLastPage == other.IsLastPage; + } + } +} diff --git a/src/OapApi.v1.Client/Http/HttpClientOapApiV1.g.cs b/src/OapApi.v1.Client/Http/HttpClientOapApiV1.g.cs new file mode 100644 index 0000000..a19d514 --- /dev/null +++ b/src/OapApi.v1.Client/Http/HttpClientOapApiV1.g.cs @@ -0,0 +1,53 @@ +// +// DO NOT EDIT: generated by fsdgencsharp +// +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 + { + /// + /// Creates the service. + /// + public HttpClientOapApiV1(HttpClientServiceSettings settings = null) + : base(settings, s_defaults) + { + } + + /// + /// Gets applications for the current user. + /// + public Task> GetApplicationsAsync(GetApplicationsRequestDto request, CancellationToken cancellationToken = default) => + TrySendRequestAsync(OapApiV1HttpMapping.GetApplicationsMapping, request, cancellationToken); + + /// + /// Creates a new application for the current user. + /// + public Task> CreateApplicationAsync(CreateApplicationRequestDto request, CancellationToken cancellationToken = default) => + TrySendRequestAsync(OapApiV1HttpMapping.CreateApplicationMapping, request, cancellationToken); + + /// + /// Gets the specified application for the current user. + /// + public Task> GetApplicationAsync(GetApplicationRequestDto request, CancellationToken cancellationToken = default) => + TrySendRequestAsync(OapApiV1HttpMapping.GetApplicationMapping, request, cancellationToken); + + /// + /// Updates the application. + /// + public Task> 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), + }; + } +} diff --git a/src/OapApi.v1.Client/Http/OapApiV1HttpHandler.g.cs b/src/OapApi.v1.Client/Http/OapApiV1HttpHandler.g.cs new file mode 100644 index 0000000..2a7784b --- /dev/null +++ b/src/OapApi.v1.Client/Http/OapApiV1HttpHandler.g.cs @@ -0,0 +1,80 @@ +// +// DO NOT EDIT: generated by fsdgencsharp +// +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 + { + /// + /// Creates the handler. + /// + public OapApiV1HttpHandler(IOapApiV1 service, ServiceHttpHandlerSettings settings = null) + : base(settings, s_defaults) + { + m_service = service ?? throw new ArgumentNullException(nameof(service)); + } + + /// + /// Creates the handler. + /// + public OapApiV1HttpHandler(Func getService, ServiceHttpHandlerSettings settings = null) + : base(settings, s_defaults) + { + m_getService = getService ?? throw new ArgumentNullException(nameof(getService)); + } + + /// + /// Attempts to handle the HTTP request. + /// + public override async Task 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); + } + + /// + /// Gets applications for the current user. + /// + public Task TryHandleGetApplicationsAsync(HttpRequestMessage httpRequest, CancellationToken cancellationToken = default) => + TryHandleServiceMethodAsync(OapApiV1HttpMapping.GetApplicationsMapping, httpRequest, GetService(httpRequest).GetApplicationsAsync, cancellationToken); + + /// + /// Creates a new application for the current user. + /// + public Task TryHandleCreateApplicationAsync(HttpRequestMessage httpRequest, CancellationToken cancellationToken = default) => + TryHandleServiceMethodAsync(OapApiV1HttpMapping.CreateApplicationMapping, httpRequest, GetService(httpRequest).CreateApplicationAsync, cancellationToken); + + /// + /// Gets the specified application for the current user. + /// + public Task TryHandleGetApplicationAsync(HttpRequestMessage httpRequest, CancellationToken cancellationToken = default) => + TryHandleServiceMethodAsync(OapApiV1HttpMapping.GetApplicationMapping, httpRequest, GetService(httpRequest).GetApplicationAsync, cancellationToken); + + /// + /// Updates the application. + /// + public Task 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 m_getService; + } +} diff --git a/src/OapApi.v1.Client/Http/OapApiV1HttpMapping.g.cs b/src/OapApi.v1.Client/Http/OapApiV1HttpMapping.g.cs new file mode 100644 index 0000000..10a45db --- /dev/null +++ b/src/OapApi.v1.Client/Http/OapApiV1HttpMapping.g.cs @@ -0,0 +1,186 @@ +// +// DO NOT EDIT: generated by fsdgencsharp +// +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 + { + /// + /// Gets applications for the current user. + /// + public static readonly HttpMethodMapping GetApplicationsMapping = + new HttpMethodMapping.Builder + { + HttpMethod = HttpMethod.Get, + Path = "/applications", + GetUriParameters = request => + new Dictionary + { + { "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.Builder + { + StatusCode = (HttpStatusCode) 200, + ResponseBodyType = typeof(GetApplicationsResponseDto), + }.Build(), + }, + }.Build(); + + /// + /// Creates a new application for the current user. + /// + public static readonly HttpMethodMapping CreateApplicationMapping = + new HttpMethodMapping.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.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.Builder + { + StatusCode = (HttpStatusCode) 201, + }.Build(), + }, + }.Build(); + + /// + /// Gets the specified application for the current user. + /// + public static readonly HttpMethodMapping GetApplicationMapping = + new HttpMethodMapping.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 + { + { "id", request.Id }, + }, + SetUriParameters = (request, parameters) => + { + parameters.TryGetValue("id", out var queryParameterId); + request.Id = queryParameterId; + return request; + }, + ResponseMappings = + { + new HttpResponseMapping.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.Builder + { + StatusCode = (HttpStatusCode) 304, + MatchesResponse = response => response.NotModified.GetValueOrDefault(), + CreateResponse = body => new GetApplicationResponseDto { NotModified = true }, + }.Build(), + }, + GetResponseHeaders = response => + new Dictionary + { + ["eTag"] = response.ETag, + }, + SetResponseHeaders = (response, headers) => + { + headers.TryGetValue("eTag", out var headerETag); + response.ETag = headerETag; + return response; + }, + }.Build(); + + /// + /// Updates the application. + /// + public static readonly HttpMethodMapping UpdateApplicationMapping = + new HttpMethodMapping.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 + { + { "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.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(); + } +} diff --git a/src/OapApi.v1.Client/IOapApiV1.g.cs b/src/OapApi.v1.Client/IOapApiV1.g.cs new file mode 100644 index 0000000..06de5f2 --- /dev/null +++ b/src/OapApi.v1.Client/IOapApiV1.g.cs @@ -0,0 +1,34 @@ +// +// DO NOT EDIT: generated by fsdgencsharp +// +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 + { + /// + /// Gets applications for the current user. + /// + Task> GetApplicationsAsync(GetApplicationsRequestDto request, CancellationToken cancellationToken = default); + + /// + /// Creates a new application for the current user. + /// + Task> CreateApplicationAsync(CreateApplicationRequestDto request, CancellationToken cancellationToken = default); + + /// + /// Gets the specified application for the current user. + /// + Task> GetApplicationAsync(GetApplicationRequestDto request, CancellationToken cancellationToken = default); + + /// + /// Updates the application. + /// + Task> UpdateApplicationAsync(UpdateApplicationRequestDto request, CancellationToken cancellationToken = default); + } +} diff --git a/src/OapApi.v1.Client/OapApi.v1.Client.csproj b/src/OapApi.v1.Client/OapApi.v1.Client.csproj new file mode 100644 index 0000000..3fa9008 --- /dev/null +++ b/src/OapApi.v1.Client/OapApi.v1.Client.csproj @@ -0,0 +1,13 @@ + + + + net8.0 + enable + enable + + + + + + + diff --git a/src/OapApi.v1.Client/OapApiV1Methods.g.cs b/src/OapApi.v1.Client/OapApiV1Methods.g.cs new file mode 100644 index 0000000..9578cba --- /dev/null +++ b/src/OapApi.v1.Client/OapApiV1Methods.g.cs @@ -0,0 +1,28 @@ +// +// DO NOT EDIT: generated by fsdgencsharp +// +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( + "getApplications", "OapApiV1", x => x.GetApplicationsAsync); + + public static readonly IServiceMethodInfo CreateApplication = + ServiceMethodInfo.Create( + "createApplication", "OapApiV1", x => x.CreateApplicationAsync); + + public static readonly IServiceMethodInfo GetApplication = + ServiceMethodInfo.Create( + "getApplication", "OapApiV1", x => x.GetApplicationAsync); + + public static readonly IServiceMethodInfo UpdateApplication = + ServiceMethodInfo.Create( + "updateApplication", "OapApiV1", x => x.UpdateApplicationAsync); + } +} diff --git a/src/OapApi.v1.Client/UpdateApplicationRequestDto.g.cs b/src/OapApi.v1.Client/UpdateApplicationRequestDto.g.cs new file mode 100644 index 0000000..2bf1f99 --- /dev/null +++ b/src/OapApi.v1.Client/UpdateApplicationRequestDto.g.cs @@ -0,0 +1,48 @@ +// +// DO NOT EDIT: generated by fsdgencsharp +// +using System; +using System.Collections.Generic; +using Facility.Core; + +namespace OapApi.v1.Client +{ + /// + /// Request for UpdateApplication. + /// + [System.CodeDom.Compiler.GeneratedCode("fsdgencsharp", "")] + public sealed partial class UpdateApplicationRequestDto : ServiceDto + { + /// + /// Creates an instance. + /// + public UpdateApplicationRequestDto() + { + } + + /// + /// The application ID. + /// + public string Id { get; set; } + + /// + /// The application update set. + /// + public ApplicationChangeSetDto ApplicationChangeSet { get; set; } + + /// + /// The JSON serializer. + /// + protected override JsonServiceSerializer JsonSerializer => SystemTextJsonServiceSerializer.Instance; + + /// + /// Determines if two DTOs are equivalent. + /// + public override bool IsEquivalentTo(UpdateApplicationRequestDto other) + { + return other != null && + Id == other.Id && + ServiceDataUtility.AreEquivalentDtos(ApplicationChangeSet, other.ApplicationChangeSet); + } + } +} diff --git a/src/OapApi.v1.Client/UpdateApplicationResponseDto.g.cs b/src/OapApi.v1.Client/UpdateApplicationResponseDto.g.cs new file mode 100644 index 0000000..356ea68 --- /dev/null +++ b/src/OapApi.v1.Client/UpdateApplicationResponseDto.g.cs @@ -0,0 +1,42 @@ +// +// DO NOT EDIT: generated by fsdgencsharp +// +using System; +using System.Collections.Generic; +using Facility.Core; + +namespace OapApi.v1.Client +{ + /// + /// Response for UpdateApplication. + /// + [System.CodeDom.Compiler.GeneratedCode("fsdgencsharp", "")] + public sealed partial class UpdateApplicationResponseDto : ServiceDto + { + /// + /// Creates an instance. + /// + public UpdateApplicationResponseDto() + { + } + + /// + /// The updated Application. + /// + public ApplicationDto Application { get; set; } + + /// + /// The JSON serializer. + /// + protected override JsonServiceSerializer JsonSerializer => SystemTextJsonServiceSerializer.Instance; + + /// + /// Determines if two DTOs are equivalent. + /// + public override bool IsEquivalentTo(UpdateApplicationResponseDto other) + { + return other != null && + ServiceDataUtility.AreEquivalentDtos(Application, other.Application); + } + } +} diff --git a/src/Themes/TailwindTheme/.eslintrc.js b/src/Themes/OapTheme/.eslintrc.js similarity index 100% rename from src/Themes/TailwindTheme/.eslintrc.js rename to src/Themes/OapTheme/.eslintrc.js diff --git a/src/Themes/OapTheme/Controllers/ApplicationFormController.cs b/src/Themes/OapTheme/Controllers/ApplicationFormController.cs new file mode 100644 index 0000000..79daedf --- /dev/null +++ b/src/Themes/OapTheme/Controllers/ApplicationFormController.cs @@ -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; +} diff --git a/src/Themes/OapTheme/Manifest.cs b/src/Themes/OapTheme/Manifest.cs new file mode 100644 index 0000000..75c5d02 --- /dev/null +++ b/src/Themes/OapTheme/Manifest.cs @@ -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." +)] diff --git a/src/Themes/OapTheme/Migrations.cs b/src/Themes/OapTheme/Migrations.cs new file mode 100644 index 0000000..47b1c6c --- /dev/null +++ b/src/Themes/OapTheme/Migrations.cs @@ -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 Create() + { + await m_contentDefinitionManager.AlterTypeDefinitionAsync("ApplicationFormStep", type => type + .Draftable() + .Versionable() + .WithPart("ApplicationFormStep", part => part + .WithPosition("1")) + .WithPart("Autoroute", part => part + .WithPosition("2") + .WithSettings(new AutoroutePartSettings + { + AllowCustomPath = true, + AllowUpdatePath = true, + })) + .WithPart("Form", part => part + .WithPosition("3") + .WithSettings(new FlowPartSettings + { + ContainedContentTypes = new[] + { + "Form", + } + }))); + + await m_contentDefinitionManager.AlterPartDefinitionAsync("ApplicationFormStep", part => part + .WithField("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("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("Autoroute", part => part + .WithPosition("2") + .WithSettings(new AutoroutePartSettings + { + AllowCustomPath = true, + AllowUpdatePath = true, + })) + .WithPart("Form Steps", part => part + .WithPosition("3") + .WithSettings(new ListPartSettings + { + PageSize = 10, + EnableOrdering = true, + ContainedContentTypes = new[] + { + "ApplicationFormStep", + } + }))); + + return 1; + } + + private readonly IContentDefinitionManager m_contentDefinitionManager; +} diff --git a/src/Themes/TailwindTheme/TailwindTheme.csproj b/src/Themes/OapTheme/OapTheme.csproj similarity index 66% rename from src/Themes/TailwindTheme/TailwindTheme.csproj rename to src/Themes/OapTheme/OapTheme.csproj index 7750ba8..a5fbc71 100644 --- a/src/Themes/TailwindTheme/TailwindTheme.csproj +++ b/src/Themes/OapTheme/OapTheme.csproj @@ -12,6 +12,11 @@ + + + + + @@ -19,6 +24,7 @@ + diff --git a/src/Themes/TailwindTheme/ResourceManagementOptionsConfiguration.cs b/src/Themes/OapTheme/ResourceManagementOptionsConfiguration.cs similarity index 81% rename from src/Themes/TailwindTheme/ResourceManagementOptionsConfiguration.cs rename to src/Themes/OapTheme/ResourceManagementOptionsConfiguration.cs index 2527a56..eac3c88 100644 --- a/src/Themes/TailwindTheme/ResourceManagementOptionsConfiguration.cs +++ b/src/Themes/OapTheme/ResourceManagementOptionsConfiguration.cs @@ -1,7 +1,7 @@ using Microsoft.Extensions.Options; using OrchardCore.ResourceManagement; -namespace TailwindTheme; +namespace OapTheme; public class ResourceManagementOptionsConfiguration : IConfigureOptions { @@ -10,8 +10,8 @@ public class ResourceManagementOptionsConfiguration : IConfigureOptions, ResourceManagementOptionsConfiguration>(); + services.AddTransient, ResourceManagementOptionsConfiguration>(); + services.AddDataMigration(); } } diff --git a/src/Themes/TailwindTheme/Styles/richtext.css b/src/Themes/OapTheme/Styles/richtext.css similarity index 100% rename from src/Themes/TailwindTheme/Styles/richtext.css rename to src/Themes/OapTheme/Styles/richtext.css diff --git a/src/Themes/TailwindTheme/Styles/site.css b/src/Themes/OapTheme/Styles/site.css similarity index 100% rename from src/Themes/TailwindTheme/Styles/site.css rename to src/Themes/OapTheme/Styles/site.css diff --git a/src/Themes/TailwindTheme/Styles/validation.css b/src/Themes/OapTheme/Styles/validation.css similarity index 100% rename from src/Themes/TailwindTheme/Styles/validation.css rename to src/Themes/OapTheme/Styles/validation.css diff --git a/src/Themes/OapTheme/Views/HtmlBodyPart.liquid b/src/Themes/OapTheme/Views/HtmlBodyPart.liquid new file mode 100644 index 0000000..b8dc459 --- /dev/null +++ b/src/Themes/OapTheme/Views/HtmlBodyPart.liquid @@ -0,0 +1,3 @@ +
+ {{ Model.Html | sanitize_html | raw }} +
diff --git a/src/Themes/TailwindTheme/Views/Layout.liquid b/src/Themes/OapTheme/Views/Layout.liquid similarity index 80% rename from src/Themes/TailwindTheme/Views/Layout.liquid rename to src/Themes/OapTheme/Views/Layout.liquid index 623d7df..2457e19 100644 --- a/src/Themes/TailwindTheme/Views/Layout.liquid +++ b/src/Themes/OapTheme/Views/Layout.liquid @@ -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" %} - \ No newline at end of file + diff --git a/src/Themes/TailwindTheme/Views/Shared/NotFound.liquid b/src/Themes/OapTheme/Views/Shared/NotFound.liquid similarity index 100% rename from src/Themes/TailwindTheme/Views/Shared/NotFound.liquid rename to src/Themes/OapTheme/Views/Shared/NotFound.liquid diff --git a/src/Themes/TailwindTheme/package-lock.json b/src/Themes/OapTheme/package-lock.json similarity index 100% rename from src/Themes/TailwindTheme/package-lock.json rename to src/Themes/OapTheme/package-lock.json diff --git a/src/Themes/TailwindTheme/package.json b/src/Themes/OapTheme/package.json similarity index 100% rename from src/Themes/TailwindTheme/package.json rename to src/Themes/OapTheme/package.json diff --git a/src/Themes/TailwindTheme/postcss.config.js b/src/Themes/OapTheme/postcss.config.js similarity index 100% rename from src/Themes/TailwindTheme/postcss.config.js rename to src/Themes/OapTheme/postcss.config.js diff --git a/src/Themes/TailwindTheme/tailwind.config.js b/src/Themes/OapTheme/tailwind.config.js similarity index 100% rename from src/Themes/TailwindTheme/tailwind.config.js rename to src/Themes/OapTheme/tailwind.config.js diff --git a/src/Themes/TailwindTheme/webpack.config.js b/src/Themes/OapTheme/webpack.config.js similarity index 100% rename from src/Themes/TailwindTheme/webpack.config.js rename to src/Themes/OapTheme/webpack.config.js diff --git a/src/Themes/OapTheme/wwwroot/site.css b/src/Themes/OapTheme/wwwroot/site.css new file mode 100644 index 0000000..905fdbc --- /dev/null +++ b/src/Themes/OapTheme/wwwroot/site.css @@ -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; +} + + diff --git a/src/Themes/OapTheme/wwwroot/site.js b/src/Themes/OapTheme/wwwroot/site.js new file mode 100644 index 0000000..3411864 --- /dev/null +++ b/src/Themes/OapTheme/wwwroot/site.js @@ -0,0 +1,119 @@ +/* + * ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development"). + * This devtool is neither made for production nor for readable output files. + * It uses "eval()" calls to create a separate source file in the browser devtools. + * If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/) + * or disable the default devtool with "devtool: false". + * If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/). + */ +/******/ (() => { // webpackBootstrap +/******/ var __webpack_modules__ = ({ + +/***/ "./Scripts/site.js": +/*!*************************!*\ + !*** ./Scripts/site.js ***! + \*************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _Styles_site_css__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Styles/site.css */ \"./Styles/site.css\");\n/* harmony import */ var htmx_org__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! htmx.org */ \"./node_modules/htmx.org/dist/htmx.min.js\");\n/* harmony import */ var htmx_org__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(htmx_org__WEBPACK_IMPORTED_MODULE_1__);\n\r\n\r\n\n\n//# sourceURL=webpack://tailwindtheme/./Scripts/site.js?"); + +/***/ }), + +/***/ "./node_modules/htmx.org/dist/htmx.min.js": +/*!************************************************!*\ + !*** ./node_modules/htmx.org/dist/htmx.min.js ***! + \************************************************/ +/***/ (function(module, exports) { + +eval("var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;(function(e,t){if(true){!(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_FACTORY__ = (t),\n\t\t__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?\n\t\t(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),\n\t\t__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__))}else {}})(typeof self!==\"undefined\"?self:this,function(){return function(){\"use strict\";var Q={onLoad:F,process:zt,on:de,off:ge,trigger:ce,ajax:Nr,find:C,findAll:f,closest:v,values:function(e,t){var r=dr(e,t||\"post\");return r.values},remove:_,addClass:z,removeClass:n,toggleClass:$,takeClass:W,defineExtension:Ur,removeExtension:Br,logAll:V,logNone:j,logger:null,config:{historyEnabled:true,historyCacheSize:10,refreshOnHistoryMiss:false,defaultSwapStyle:\"innerHTML\",defaultSwapDelay:0,defaultSettleDelay:20,includeIndicatorStyles:true,indicatorClass:\"htmx-indicator\",requestClass:\"htmx-request\",addedClass:\"htmx-added\",settlingClass:\"htmx-settling\",swappingClass:\"htmx-swapping\",allowEval:true,allowScriptTags:true,inlineScriptNonce:\"\",attributesToSettle:[\"class\",\"style\",\"width\",\"height\"],withCredentials:false,timeout:0,wsReconnectDelay:\"full-jitter\",wsBinaryType:\"blob\",disableSelector:\"[hx-disable], [data-hx-disable]\",useTemplateFragments:false,scrollBehavior:\"smooth\",defaultFocusScroll:false,getCacheBusterParam:false,globalViewTransitions:false,methodsThatUseUrlParams:[\"get\"],selfRequestsOnly:false,ignoreTitle:false,scrollIntoViewOnBoost:true,triggerSpecsCache:null},parseInterval:d,_:t,createEventSource:function(e){return new EventSource(e,{withCredentials:true})},createWebSocket:function(e){var t=new WebSocket(e,[]);t.binaryType=Q.config.wsBinaryType;return t},version:\"1.9.10\"};var r={addTriggerHandler:Lt,bodyContains:se,canAccessLocalStorage:U,findThisElement:xe,filterValues:yr,hasAttribute:o,getAttributeValue:te,getClosestAttributeValue:ne,getClosestMatch:c,getExpressionVars:Hr,getHeaders:xr,getInputValues:dr,getInternalData:ae,getSwapSpecification:wr,getTriggerSpecs:it,getTarget:ye,makeFragment:l,mergeObjects:le,makeSettleInfo:T,oobSwap:Ee,querySelectorExt:ue,selectAndSwap:je,settleImmediately:nr,shouldCancel:ut,triggerEvent:ce,triggerErrorEvent:fe,withExtensions:R};var w=[\"get\",\"post\",\"put\",\"delete\",\"patch\"];var i=w.map(function(e){return\"[hx-\"+e+\"], [data-hx-\"+e+\"]\"}).join(\", \");var S=e(\"head\"),q=e(\"title\"),H=e(\"svg\",true);function e(e,t=false){return new RegExp(`<${e}(\\\\s[^>]*>|>)([\\\\s\\\\S]*?)<\\\\/${e}>`,t?\"gim\":\"im\")}function d(e){if(e==undefined){return undefined}let t=NaN;if(e.slice(-2)==\"ms\"){t=parseFloat(e.slice(0,-2))}else if(e.slice(-1)==\"s\"){t=parseFloat(e.slice(0,-1))*1e3}else if(e.slice(-1)==\"m\"){t=parseFloat(e.slice(0,-1))*1e3*60}else{t=parseFloat(e)}return isNaN(t)?undefined:t}function ee(e,t){return e.getAttribute&&e.getAttribute(t)}function o(e,t){return e.hasAttribute&&(e.hasAttribute(t)||e.hasAttribute(\"data-\"+t))}function te(e,t){return ee(e,t)||ee(e,\"data-\"+t)}function u(e){return e.parentElement}function re(){return document}function c(e,t){while(e&&!t(e)){e=u(e)}return e?e:null}function L(e,t,r){var n=te(t,r);var i=te(t,\"hx-disinherit\");if(e!==t&&i&&(i===\"*\"||i.split(\" \").indexOf(r)>=0)){return\"unset\"}else{return n}}function ne(t,r){var n=null;c(t,function(e){return n=L(t,e,r)});if(n!==\"unset\"){return n}}function h(e,t){var r=e.matches||e.matchesSelector||e.msMatchesSelector||e.mozMatchesSelector||e.webkitMatchesSelector||e.oMatchesSelector;return r&&r.call(e,t)}function A(e){var t=/<([a-z][^\\/\\0>\\x20\\t\\r\\n\\f]*)/i;var r=t.exec(e);if(r){return r[1].toLowerCase()}else{return\"\"}}function a(e,t){var r=new DOMParser;var n=r.parseFromString(e,\"text/html\");var i=n.body;while(t>0){t--;i=i.firstChild}if(i==null){i=re().createDocumentFragment()}return i}function N(e){return/\",0);return i.querySelector(\"template\").content}switch(r){case\"thead\":case\"tbody\":case\"tfoot\":case\"colgroup\":case\"caption\":return a(\"\"+n+\"
\",1);case\"col\":return a(\"\"+n+\"
\",2);case\"tr\":return a(\"\"+n+\"
\",2);case\"td\":case\"th\":return a(\"\"+n+\"
\",3);case\"script\":case\"style\":return a(\"
\"+n+\"
\",1);default:return a(n,0)}}function ie(e){if(e){e()}}function I(e,t){return Object.prototype.toString.call(e)===\"[object \"+t+\"]\"}function k(e){return I(e,\"Function\")}function P(e){return I(e,\"Object\")}function ae(e){var t=\"htmx-internal-data\";var r=e[t];if(!r){r=e[t]={}}return r}function M(e){var t=[];if(e){for(var r=0;r=0}function se(e){if(e.getRootNode&&e.getRootNode()instanceof window.ShadowRoot){return re().body.contains(e.getRootNode().host)}else{return re().body.contains(e)}}function D(e){return e.trim().split(/\\s+/)}function le(e,t){for(var r in t){if(t.hasOwnProperty(r)){e[r]=t[r]}}return e}function E(e){try{return JSON.parse(e)}catch(e){b(e);return null}}function U(){var e=\"htmx:localStorageTest\";try{localStorage.setItem(e,e);localStorage.removeItem(e);return true}catch(e){return false}}function B(t){try{var e=new URL(t);if(e){t=e.pathname+e.search}if(!/^\\/$/.test(t)){t=t.replace(/\\/+$/,\"\")}return t}catch(e){return t}}function t(e){return Tr(re().body,function(){return eval(e)})}function F(t){var e=Q.on(\"htmx:load\",function(e){t(e.detail.elt)});return e}function V(){Q.logger=function(e,t,r){if(console){console.log(t,e,r)}}}function j(){Q.logger=null}function C(e,t){if(t){return e.querySelector(t)}else{return C(re(),e)}}function f(e,t){if(t){return e.querySelectorAll(t)}else{return f(re(),e)}}function _(e,t){e=g(e);if(t){setTimeout(function(){_(e);e=null},t)}else{e.parentElement.removeChild(e)}}function z(e,t,r){e=g(e);if(r){setTimeout(function(){z(e,t);e=null},r)}else{e.classList&&e.classList.add(t)}}function n(e,t,r){e=g(e);if(r){setTimeout(function(){n(e,t);e=null},r)}else{if(e.classList){e.classList.remove(t);if(e.classList.length===0){e.removeAttribute(\"class\")}}}}function $(e,t){e=g(e);e.classList.toggle(t)}function W(e,t){e=g(e);oe(e.parentElement.children,function(e){n(e,t)});z(e,t)}function v(e,t){e=g(e);if(e.closest){return e.closest(t)}else{do{if(e==null||h(e,t)){return e}}while(e=e&&u(e));return null}}function s(e,t){return e.substring(0,t.length)===t}function G(e,t){return e.substring(e.length-t.length)===t}function J(e){var t=e.trim();if(s(t,\"<\")&&G(t,\"/>\")){return t.substring(1,t.length-2)}else{return t}}function Z(e,t){if(t.indexOf(\"closest \")===0){return[v(e,J(t.substr(8)))]}else if(t.indexOf(\"find \")===0){return[C(e,J(t.substr(5)))]}else if(t===\"next\"){return[e.nextElementSibling]}else if(t.indexOf(\"next \")===0){return[K(e,J(t.substr(5)))]}else if(t===\"previous\"){return[e.previousElementSibling]}else if(t.indexOf(\"previous \")===0){return[Y(e,J(t.substr(9)))]}else if(t===\"document\"){return[document]}else if(t===\"window\"){return[window]}else if(t===\"body\"){return[document.body]}else{return re().querySelectorAll(J(t))}}var K=function(e,t){var r=re().querySelectorAll(t);for(var n=0;n=0;n--){var i=r[n];if(i.compareDocumentPosition(e)===Node.DOCUMENT_POSITION_FOLLOWING){return i}}};function ue(e,t){if(t){return Z(e,t)[0]}else{return Z(re().body,e)[0]}}function g(e){if(I(e,\"String\")){return C(e)}else{return e}}function ve(e,t,r){if(k(t)){return{target:re().body,event:e,listener:t}}else{return{target:g(e),event:t,listener:r}}}function de(t,r,n){jr(function(){var e=ve(t,r,n);e.target.addEventListener(e.event,e.listener)});var e=k(r);return e?r:n}function ge(t,r,n){jr(function(){var e=ve(t,r,n);e.target.removeEventListener(e.event,e.listener)});return k(r)?r:n}var me=re().createElement(\"output\");function pe(e,t){var r=ne(e,t);if(r){if(r===\"this\"){return[xe(e,t)]}else{var n=Z(e,r);if(n.length===0){b('The selector \"'+r+'\" on '+t+\" returned no matches!\");return[me]}else{return n}}}}function xe(e,t){return c(e,function(e){return te(e,t)!=null})}function ye(e){var t=ne(e,\"hx-target\");if(t){if(t===\"this\"){return xe(e,\"hx-target\")}else{return ue(e,t)}}else{var r=ae(e);if(r.boosted){return re().body}else{return e}}}function be(e){var t=Q.config.attributesToSettle;for(var r=0;r0){o=e.substr(0,e.indexOf(\":\"));t=e.substr(e.indexOf(\":\")+1,e.length)}else{o=e}var r=re().querySelectorAll(t);if(r){oe(r,function(e){var t;var r=i.cloneNode(true);t=re().createDocumentFragment();t.appendChild(r);if(!Se(o,e)){t=r}var n={shouldSwap:true,target:e,fragment:t};if(!ce(e,\"htmx:oobBeforeSwap\",n))return;e=n.target;if(n[\"shouldSwap\"]){Fe(o,e,e,t,a)}oe(a.elts,function(e){ce(e,\"htmx:oobAfterSwap\",n)})});i.parentNode.removeChild(i)}else{i.parentNode.removeChild(i);fe(re().body,\"htmx:oobErrorNoTarget\",{content:i})}return e}function Ce(e,t,r){var n=ne(e,\"hx-select-oob\");if(n){var i=n.split(\",\");for(var a=0;a0){var r=t.replace(\"'\",\"\\\\'\");var n=e.tagName.replace(\":\",\"\\\\:\");var i=o.querySelector(n+\"[id='\"+r+\"']\");if(i&&i!==o){var a=e.cloneNode();we(e,i);s.tasks.push(function(){we(e,a)})}}})}function Oe(e){return function(){n(e,Q.config.addedClass);zt(e);Nt(e);qe(e);ce(e,\"htmx:load\")}}function qe(e){var t=\"[autofocus]\";var r=h(e,t)?e:e.querySelector(t);if(r!=null){r.focus()}}function m(e,t,r,n){Te(e,r,n);while(r.childNodes.length>0){var i=r.firstChild;z(i,Q.config.addedClass);e.insertBefore(i,t);if(i.nodeType!==Node.TEXT_NODE&&i.nodeType!==Node.COMMENT_NODE){n.tasks.push(Oe(i))}}}function He(e,t){var r=0;while(r-1){var t=e.replace(H,\"\");var r=t.match(q);if(r){return r[2]}}}function je(e,t,r,n,i,a){i.title=Ve(n);var o=l(n);if(o){Ce(r,o,i);o=Be(r,o,a);Re(o);return Fe(e,r,t,o,i)}}function _e(e,t,r){var n=e.getResponseHeader(t);if(n.indexOf(\"{\")===0){var i=E(n);for(var a in i){if(i.hasOwnProperty(a)){var o=i[a];if(!P(o)){o={value:o}}ce(r,a,o)}}}else{var s=n.split(\",\");for(var l=0;l0){var o=t[0];if(o===\"]\"){n--;if(n===0){if(a===null){i=i+\"true\"}t.shift();i+=\")})\";try{var s=Tr(e,function(){return Function(i)()},function(){return true});s.source=i;return s}catch(e){fe(re().body,\"htmx:syntax:error\",{error:e,source:i});return null}}}else if(o===\"[\"){n++}if(Qe(o,a,r)){i+=\"((\"+r+\".\"+o+\") ? (\"+r+\".\"+o+\") : (window.\"+o+\"))\"}else{i=i+o}a=t.shift()}}}function y(e,t){var r=\"\";while(e.length>0&&!t.test(e[0])){r+=e.shift()}return r}function tt(e){var t;if(e.length>0&&Ze.test(e[0])){e.shift();t=y(e,Ke).trim();e.shift()}else{t=y(e,x)}return t}var rt=\"input, textarea, select\";function nt(e,t,r){var n=[];var i=Ye(t);do{y(i,Je);var a=i.length;var o=y(i,/[,\\[\\s]/);if(o!==\"\"){if(o===\"every\"){var s={trigger:\"every\"};y(i,Je);s.pollInterval=d(y(i,/[,\\[\\s]/));y(i,Je);var l=et(e,i,\"event\");if(l){s.eventFilter=l}n.push(s)}else if(o.indexOf(\"sse:\")===0){n.push({trigger:\"sse\",sseEvent:o.substr(4)})}else{var u={trigger:o};var l=et(e,i,\"event\");if(l){u.eventFilter=l}while(i.length>0&&i[0]!==\",\"){y(i,Je);var f=i.shift();if(f===\"changed\"){u.changed=true}else if(f===\"once\"){u.once=true}else if(f===\"consume\"){u.consume=true}else if(f===\"delay\"&&i[0]===\":\"){i.shift();u.delay=d(y(i,x))}else if(f===\"from\"&&i[0]===\":\"){i.shift();if(Ze.test(i[0])){var c=tt(i)}else{var c=y(i,x);if(c===\"closest\"||c===\"find\"||c===\"next\"||c===\"previous\"){i.shift();var h=tt(i);if(h.length>0){c+=\" \"+h}}}u.from=c}else if(f===\"target\"&&i[0]===\":\"){i.shift();u.target=tt(i)}else if(f===\"throttle\"&&i[0]===\":\"){i.shift();u.throttle=d(y(i,x))}else if(f===\"queue\"&&i[0]===\":\"){i.shift();u.queue=y(i,x)}else if(f===\"root\"&&i[0]===\":\"){i.shift();u[f]=tt(i)}else if(f===\"threshold\"&&i[0]===\":\"){i.shift();u[f]=y(i,x)}else{fe(e,\"htmx:syntax:error\",{token:i.shift()})}}n.push(u)}}if(i.length===a){fe(e,\"htmx:syntax:error\",{token:i.shift()})}y(i,Je)}while(i[0]===\",\"&&i.shift());if(r){r[t]=n}return n}function it(e){var t=te(e,\"hx-trigger\");var r=[];if(t){var n=Q.config.triggerSpecsCache;r=n&&n[t]||nt(e,t,n)}if(r.length>0){return r}else if(h(e,\"form\")){return[{trigger:\"submit\"}]}else if(h(e,'input[type=\"button\"], input[type=\"submit\"]')){return[{trigger:\"click\"}]}else if(h(e,rt)){return[{trigger:\"change\"}]}else{return[{trigger:\"click\"}]}}function at(e){ae(e).cancelled=true}function ot(e,t,r){var n=ae(e);n.timeout=setTimeout(function(){if(se(e)&&n.cancelled!==true){if(!ct(r,e,Wt(\"hx:poll:trigger\",{triggerSpec:r,target:e}))){t(e)}ot(e,t,r)}},r.pollInterval)}function st(e){return location.hostname===e.hostname&&ee(e,\"href\")&&ee(e,\"href\").indexOf(\"#\")!==0}function lt(t,r,e){if(t.tagName===\"A\"&&st(t)&&(t.target===\"\"||t.target===\"_self\")||t.tagName===\"FORM\"){r.boosted=true;var n,i;if(t.tagName===\"A\"){n=\"get\";i=ee(t,\"href\")}else{var a=ee(t,\"method\");n=a?a.toLowerCase():\"get\";if(n===\"get\"){}i=ee(t,\"action\")}e.forEach(function(e){ht(t,function(e,t){if(v(e,Q.config.disableSelector)){p(e);return}he(n,i,e,t)},r,e,true)})}}function ut(e,t){if(e.type===\"submit\"||e.type===\"click\"){if(t.tagName===\"FORM\"){return true}if(h(t,'input[type=\"submit\"], button')&&v(t,\"form\")!==null){return true}if(t.tagName===\"A\"&&t.href&&(t.getAttribute(\"href\")===\"#\"||t.getAttribute(\"href\").indexOf(\"#\")!==0)){return true}}return false}function ft(e,t){return ae(e).boosted&&e.tagName===\"A\"&&t.type===\"click\"&&(t.ctrlKey||t.metaKey)}function ct(e,t,r){var n=e.eventFilter;if(n){try{return n.call(t,r)!==true}catch(e){fe(re().body,\"htmx:eventFilter:error\",{error:e,source:n.source});return true}}return false}function ht(a,o,e,s,l){var u=ae(a);var t;if(s.from){t=Z(a,s.from)}else{t=[a]}if(s.changed){t.forEach(function(e){var t=ae(e);t.lastValue=e.value})}oe(t,function(n){var i=function(e){if(!se(a)){n.removeEventListener(s.trigger,i);return}if(ft(a,e)){return}if(l||ut(e,a)){e.preventDefault()}if(ct(s,a,e)){return}var t=ae(e);t.triggerSpec=s;if(t.handledFor==null){t.handledFor=[]}if(t.handledFor.indexOf(a)<0){t.handledFor.push(a);if(s.consume){e.stopPropagation()}if(s.target&&e.target){if(!h(e.target,s.target)){return}}if(s.once){if(u.triggeredOnce){return}else{u.triggeredOnce=true}}if(s.changed){var r=ae(n);if(r.lastValue===n.value){return}r.lastValue=n.value}if(u.delayed){clearTimeout(u.delayed)}if(u.throttle){return}if(s.throttle>0){if(!u.throttle){o(a,e);u.throttle=setTimeout(function(){u.throttle=null},s.throttle)}}else if(s.delay>0){u.delayed=setTimeout(function(){o(a,e)},s.delay)}else{ce(a,\"htmx:trigger\");o(a,e)}}};if(e.listenerInfos==null){e.listenerInfos=[]}e.listenerInfos.push({trigger:s.trigger,listener:i,on:n});n.addEventListener(s.trigger,i)})}var vt=false;var dt=null;function gt(){if(!dt){dt=function(){vt=true};window.addEventListener(\"scroll\",dt);setInterval(function(){if(vt){vt=false;oe(re().querySelectorAll(\"[hx-trigger='revealed'],[data-hx-trigger='revealed']\"),function(e){mt(e)})}},200)}}function mt(t){if(!o(t,\"data-hx-revealed\")&&X(t)){t.setAttribute(\"data-hx-revealed\",\"true\");var e=ae(t);if(e.initHash){ce(t,\"revealed\")}else{t.addEventListener(\"htmx:afterProcessNode\",function(e){ce(t,\"revealed\")},{once:true})}}}function pt(e,t,r){var n=D(r);for(var i=0;i=0){var t=wt(n);setTimeout(function(){xt(s,r,n+1)},t)}};t.onopen=function(e){n=0};ae(s).webSocket=t;t.addEventListener(\"message\",function(e){if(yt(s)){return}var t=e.data;R(s,function(e){t=e.transformResponse(t,null,s)});var r=T(s);var n=l(t);var i=M(n.children);for(var a=0;a0){ce(u,\"htmx:validation:halted\",i);return}t.send(JSON.stringify(l));if(ut(e,u)){e.preventDefault()}})}else{fe(u,\"htmx:noWebSocketSourceError\")}}function wt(e){var t=Q.config.wsReconnectDelay;if(typeof t===\"function\"){return t(e)}if(t===\"full-jitter\"){var r=Math.min(e,6);var n=1e3*Math.pow(2,r);return n*Math.random()}b('htmx.config.wsReconnectDelay must either be a function or the string \"full-jitter\"')}function St(e,t,r){var n=D(r);for(var i=0;i0){setTimeout(i,n)}else{i()}}function Ht(t,i,e){var a=false;oe(w,function(r){if(o(t,\"hx-\"+r)){var n=te(t,\"hx-\"+r);a=true;i.path=n;i.verb=r;e.forEach(function(e){Lt(t,e,i,function(e,t){if(v(e,Q.config.disableSelector)){p(e);return}he(r,n,e,t)})})}});return a}function Lt(n,e,t,r){if(e.sseEvent){Rt(n,r,e.sseEvent)}else if(e.trigger===\"revealed\"){gt();ht(n,r,t,e);mt(n)}else if(e.trigger===\"intersect\"){var i={};if(e.root){i.root=ue(n,e.root)}if(e.threshold){i.threshold=parseFloat(e.threshold)}var a=new IntersectionObserver(function(e){for(var t=0;t0){t.polling=true;ot(n,r,e)}else{ht(n,r,t,e)}}function At(e){if(Q.config.allowScriptTags&&(e.type===\"text/javascript\"||e.type===\"module\"||e.type===\"\")){var t=re().createElement(\"script\");oe(e.attributes,function(e){t.setAttribute(e.name,e.value)});t.textContent=e.textContent;t.async=false;if(Q.config.inlineScriptNonce){t.nonce=Q.config.inlineScriptNonce}var r=e.parentElement;try{r.insertBefore(t,e)}catch(e){b(e)}finally{if(e.parentElement){e.parentElement.removeChild(e)}}}}function Nt(e){if(h(e,\"script\")){At(e)}oe(f(e,\"script\"),function(e){At(e)})}function It(e){var t=e.attributes;for(var r=0;r0){var o=n.shift();var s=o.match(/^\\s*([a-zA-Z:\\-\\.]+:)(.*)/);if(a===0&&s){o.split(\":\");i=s[1].slice(0,-1);r[i]=s[2]}else{r[i]+=o}a+=Bt(o)}for(var l in r){Ft(e,l,r[l])}}}function jt(e){Ae(e);for(var t=0;tQ.config.historyCacheSize){i.shift()}while(i.length>0){try{localStorage.setItem(\"htmx-history-cache\",JSON.stringify(i));break}catch(e){fe(re().body,\"htmx:historyCacheError\",{cause:e,cache:i});i.shift()}}}function Yt(e){if(!U()){return null}e=B(e);var t=E(localStorage.getItem(\"htmx-history-cache\"))||[];for(var r=0;r=200&&this.status<400){ce(re().body,\"htmx:historyCacheMissLoad\",o);var e=l(this.response);e=e.querySelector(\"[hx-history-elt],[data-hx-history-elt]\")||e;var t=Zt();var r=T(t);var n=Ve(this.response);if(n){var i=C(\"title\");if(i){i.innerHTML=n}else{window.document.title=n}}Ue(t,e,r);nr(r.tasks);Jt=a;ce(re().body,\"htmx:historyRestore\",{path:a,cacheMiss:true,serverResponse:this.response})}else{fe(re().body,\"htmx:historyCacheMissLoadError\",o)}};e.send()}function ar(e){er();e=e||location.pathname+location.search;var t=Yt(e);if(t){var r=l(t.content);var n=Zt();var i=T(n);Ue(n,r,i);nr(i.tasks);document.title=t.title;setTimeout(function(){window.scrollTo(0,t.scroll)},0);Jt=e;ce(re().body,\"htmx:historyRestore\",{path:e,item:t})}else{if(Q.config.refreshOnHistoryMiss){window.location.reload(true)}else{ir(e)}}}function or(e){var t=pe(e,\"hx-indicator\");if(t==null){t=[e]}oe(t,function(e){var t=ae(e);t.requestCount=(t.requestCount||0)+1;e.classList[\"add\"].call(e.classList,Q.config.requestClass)});return t}function sr(e){var t=pe(e,\"hx-disabled-elt\");if(t==null){t=[]}oe(t,function(e){var t=ae(e);t.requestCount=(t.requestCount||0)+1;e.setAttribute(\"disabled\",\"\")});return t}function lr(e,t){oe(e,function(e){var t=ae(e);t.requestCount=(t.requestCount||0)-1;if(t.requestCount===0){e.classList[\"remove\"].call(e.classList,Q.config.requestClass)}});oe(t,function(e){var t=ae(e);t.requestCount=(t.requestCount||0)-1;if(t.requestCount===0){e.removeAttribute(\"disabled\")}})}function ur(e,t){for(var r=0;r=0}function wr(e,t){var r=t?t:ne(e,\"hx-swap\");var n={swapStyle:ae(e).boosted?\"innerHTML\":Q.config.defaultSwapStyle,swapDelay:Q.config.defaultSwapDelay,settleDelay:Q.config.defaultSettleDelay};if(Q.config.scrollIntoViewOnBoost&&ae(e).boosted&&!br(e)){n[\"show\"]=\"top\"}if(r){var i=D(r);if(i.length>0){for(var a=0;a0?l.join(\":\"):null;n[\"scroll\"]=u;n[\"scrollTarget\"]=f}else if(o.indexOf(\"show:\")===0){var c=o.substr(5);var l=c.split(\":\");var h=l.pop();var f=l.length>0?l.join(\":\"):null;n[\"show\"]=h;n[\"showTarget\"]=f}else if(o.indexOf(\"focus-scroll:\")===0){var v=o.substr(\"focus-scroll:\".length);n[\"focusScroll\"]=v==\"true\"}else if(a==0){n[\"swapStyle\"]=o}else{b(\"Unknown modifier in hx-swap: \"+o)}}}}return n}function Sr(e){return ne(e,\"hx-encoding\")===\"multipart/form-data\"||h(e,\"form\")&&ee(e,\"enctype\")===\"multipart/form-data\"}function Er(t,r,n){var i=null;R(r,function(e){if(i==null){i=e.encodeParameters(t,n,r)}});if(i!=null){return i}else{if(Sr(r)){return pr(n)}else{return mr(n)}}}function T(e){return{tasks:[],elts:[e]}}function Cr(e,t){var r=e[0];var n=e[e.length-1];if(t.scroll){var i=null;if(t.scrollTarget){i=ue(r,t.scrollTarget)}if(t.scroll===\"top\"&&(r||i)){i=i||r;i.scrollTop=0}if(t.scroll===\"bottom\"&&(n||i)){i=i||n;i.scrollTop=i.scrollHeight}}if(t.show){var i=null;if(t.showTarget){var a=t.showTarget;if(t.showTarget===\"window\"){a=\"body\"}i=ue(r,a)}if(t.show===\"top\"&&(r||i)){i=i||r;i.scrollIntoView({block:\"start\",behavior:Q.config.scrollBehavior})}if(t.show===\"bottom\"&&(n||i)){i=i||n;i.scrollIntoView({block:\"end\",behavior:Q.config.scrollBehavior})}}}function Rr(e,t,r,n){if(n==null){n={}}if(e==null){return n}var i=te(e,t);if(i){var a=i.trim();var o=r;if(a===\"unset\"){return null}if(a.indexOf(\"javascript:\")===0){a=a.substr(11);o=true}else if(a.indexOf(\"js:\")===0){a=a.substr(3);o=true}if(a.indexOf(\"{\")!==0){a=\"{\"+a+\"}\"}var s;if(o){s=Tr(e,function(){return Function(\"return (\"+a+\")\")()},{})}else{s=E(a)}for(var l in s){if(s.hasOwnProperty(l)){if(n[l]==null){n[l]=s[l]}}}}return Rr(u(e),t,r,n)}function Tr(e,t,r){if(Q.config.allowEval){return t()}else{fe(e,\"htmx:evalDisallowedError\");return r}}function Or(e,t){return Rr(e,\"hx-vars\",true,t)}function qr(e,t){return Rr(e,\"hx-vals\",false,t)}function Hr(e){return le(Or(e),qr(e))}function Lr(t,r,n){if(n!==null){try{t.setRequestHeader(r,n)}catch(e){t.setRequestHeader(r,encodeURIComponent(n));t.setRequestHeader(r+\"-URI-AutoEncoded\",\"true\")}}}function Ar(t){if(t.responseURL&&typeof URL!==\"undefined\"){try{var e=new URL(t.responseURL);return e.pathname+e.search}catch(e){fe(re().body,\"htmx:badResponseUrl\",{url:t.responseURL})}}}function O(e,t){return t.test(e.getAllResponseHeaders())}function Nr(e,t,r){e=e.toLowerCase();if(r){if(r instanceof Element||I(r,\"String\")){return he(e,t,null,null,{targetOverride:g(r),returnPromise:true})}else{return he(e,t,g(r.source),r.event,{handler:r.handler,headers:r.headers,values:r.values,targetOverride:g(r.target),swapOverride:r.swap,select:r.select,returnPromise:true})}}else{return he(e,t,null,null,{returnPromise:true})}}function Ir(e){var t=[];while(e){t.push(e);e=e.parentElement}return t}function kr(e,t,r){var n;var i;if(typeof URL===\"function\"){i=new URL(t,document.location.href);var a=document.location.origin;n=a===i.origin}else{i=t;n=s(t,document.location.origin)}if(Q.config.selfRequestsOnly){if(!n){return false}}return ce(e,\"htmx:validateUrl\",le({url:i,sameHost:n},r))}function he(t,r,n,i,a,e){var o=null;var s=null;a=a!=null?a:{};if(a.returnPromise&&typeof Promise!==\"undefined\"){var l=new Promise(function(e,t){o=e;s=t})}if(n==null){n=re().body}var M=a.handler||Mr;var X=a.select||null;if(!se(n)){ie(o);return l}var u=a.targetOverride||ye(n);if(u==null||u==me){fe(n,\"htmx:targetError\",{target:te(n,\"hx-target\")});ie(s);return l}var f=ae(n);var c=f.lastButtonClicked;if(c){var h=ee(c,\"formaction\");if(h!=null){r=h}var v=ee(c,\"formmethod\");if(v!=null){if(v.toLowerCase()!==\"dialog\"){t=v}}}var d=ne(n,\"hx-confirm\");if(e===undefined){var D=function(e){return he(t,r,n,i,a,!!e)};var U={target:u,elt:n,path:r,verb:t,triggeringEvent:i,etc:a,issueRequest:D,question:d};if(ce(n,\"htmx:confirm\",U)===false){ie(o);return l}}var g=n;var m=ne(n,\"hx-sync\");var p=null;var x=false;if(m){var B=m.split(\":\");var F=B[0].trim();if(F===\"this\"){g=xe(n,\"hx-sync\")}else{g=ue(n,F)}m=(B[1]||\"drop\").trim();f=ae(g);if(m===\"drop\"&&f.xhr&&f.abortable!==true){ie(o);return l}else if(m===\"abort\"){if(f.xhr){ie(o);return l}else{x=true}}else if(m===\"replace\"){ce(g,\"htmx:abort\")}else if(m.indexOf(\"queue\")===0){var V=m.split(\" \");p=(V[1]||\"last\").trim()}}if(f.xhr){if(f.abortable){ce(g,\"htmx:abort\")}else{if(p==null){if(i){var y=ae(i);if(y&&y.triggerSpec&&y.triggerSpec.queue){p=y.triggerSpec.queue}}if(p==null){p=\"last\"}}if(f.queuedRequests==null){f.queuedRequests=[]}if(p===\"first\"&&f.queuedRequests.length===0){f.queuedRequests.push(function(){he(t,r,n,i,a)})}else if(p===\"all\"){f.queuedRequests.push(function(){he(t,r,n,i,a)})}else if(p===\"last\"){f.queuedRequests=[];f.queuedRequests.push(function(){he(t,r,n,i,a)})}ie(o);return l}}var b=new XMLHttpRequest;f.xhr=b;f.abortable=x;var w=function(){f.xhr=null;f.abortable=false;if(f.queuedRequests!=null&&f.queuedRequests.length>0){var e=f.queuedRequests.shift();e()}};var j=ne(n,\"hx-prompt\");if(j){var S=prompt(j);if(S===null||!ce(n,\"htmx:prompt\",{prompt:S,target:u})){ie(o);w();return l}}if(d&&!e){if(!confirm(d)){ie(o);w();return l}}var E=xr(n,u,S);if(t!==\"get\"&&!Sr(n)){E[\"Content-Type\"]=\"application/x-www-form-urlencoded\"}if(a.headers){E=le(E,a.headers)}var _=dr(n,t);var C=_.errors;var R=_.values;if(a.values){R=le(R,a.values)}var z=Hr(n);var $=le(R,z);var T=yr($,n);if(Q.config.getCacheBusterParam&&t===\"get\"){T[\"org.htmx.cache-buster\"]=ee(u,\"id\")||\"true\"}if(r==null||r===\"\"){r=re().location.href}var O=Rr(n,\"hx-request\");var W=ae(n).boosted;var q=Q.config.methodsThatUseUrlParams.indexOf(t)>=0;var H={boosted:W,useUrlParams:q,parameters:T,unfilteredParameters:$,headers:E,target:u,verb:t,errors:C,withCredentials:a.credentials||O.credentials||Q.config.withCredentials,timeout:a.timeout||O.timeout||Q.config.timeout,path:r,triggeringEvent:i};if(!ce(n,\"htmx:configRequest\",H)){ie(o);w();return l}r=H.path;t=H.verb;E=H.headers;T=H.parameters;C=H.errors;q=H.useUrlParams;if(C&&C.length>0){ce(n,\"htmx:validation:halted\",H);ie(o);w();return l}var G=r.split(\"#\");var J=G[0];var L=G[1];var A=r;if(q){A=J;var Z=Object.keys(T).length!==0;if(Z){if(A.indexOf(\"?\")<0){A+=\"?\"}else{A+=\"&\"}A+=mr(T);if(L){A+=\"#\"+L}}}if(!kr(n,A,H)){fe(n,\"htmx:invalidPath\",H);ie(s);return l}b.open(t.toUpperCase(),A,true);b.overrideMimeType(\"text/html\");b.withCredentials=H.withCredentials;b.timeout=H.timeout;if(O.noHeaders){}else{for(var N in E){if(E.hasOwnProperty(N)){var K=E[N];Lr(b,N,K)}}}var I={xhr:b,target:u,requestConfig:H,etc:a,boosted:W,select:X,pathInfo:{requestPath:r,finalRequestPath:A,anchor:L}};b.onload=function(){try{var e=Ir(n);I.pathInfo.responsePath=Ar(b);M(n,I);lr(k,P);ce(n,\"htmx:afterRequest\",I);ce(n,\"htmx:afterOnLoad\",I);if(!se(n)){var t=null;while(e.length>0&&t==null){var r=e.shift();if(se(r)){t=r}}if(t){ce(t,\"htmx:afterRequest\",I);ce(t,\"htmx:afterOnLoad\",I)}}ie(o);w()}catch(e){fe(n,\"htmx:onLoadError\",le({error:e},I));throw e}};b.onerror=function(){lr(k,P);fe(n,\"htmx:afterRequest\",I);fe(n,\"htmx:sendError\",I);ie(s);w()};b.onabort=function(){lr(k,P);fe(n,\"htmx:afterRequest\",I);fe(n,\"htmx:sendAbort\",I);ie(s);w()};b.ontimeout=function(){lr(k,P);fe(n,\"htmx:afterRequest\",I);fe(n,\"htmx:timeout\",I);ie(s);w()};if(!ce(n,\"htmx:beforeRequest\",I)){ie(o);w();return l}var k=or(n);var P=sr(n);oe([\"loadstart\",\"loadend\",\"progress\",\"abort\"],function(t){oe([b,b.upload],function(e){e.addEventListener(t,function(e){ce(n,\"htmx:xhr:\"+t,{lengthComputable:e.lengthComputable,loaded:e.loaded,total:e.total})})})});ce(n,\"htmx:beforeSend\",I);var Y=q?null:Er(b,n,T);b.send(Y);return l}function Pr(e,t){var r=t.xhr;var n=null;var i=null;if(O(r,/HX-Push:/i)){n=r.getResponseHeader(\"HX-Push\");i=\"push\"}else if(O(r,/HX-Push-Url:/i)){n=r.getResponseHeader(\"HX-Push-Url\");i=\"push\"}else if(O(r,/HX-Replace-Url:/i)){n=r.getResponseHeader(\"HX-Replace-Url\");i=\"replace\"}if(n){if(n===\"false\"){return{}}else{return{type:i,path:n}}}var a=t.pathInfo.finalRequestPath;var o=t.pathInfo.responsePath;var s=ne(e,\"hx-push-url\");var l=ne(e,\"hx-replace-url\");var u=ae(e).boosted;var f=null;var c=null;if(s){f=\"push\";c=s}else if(l){f=\"replace\";c=l}else if(u){f=\"push\";c=o||a}if(c){if(c===\"false\"){return{}}if(c===\"true\"){c=o||a}if(t.pathInfo.anchor&&c.indexOf(\"#\")===-1){c=c+\"#\"+t.pathInfo.anchor}return{type:f,path:c}}else{return{}}}function Mr(l,u){var f=u.xhr;var c=u.target;var e=u.etc;var t=u.requestConfig;var h=u.select;if(!ce(l,\"htmx:beforeOnLoad\",u))return;if(O(f,/HX-Trigger:/i)){_e(f,\"HX-Trigger\",l)}if(O(f,/HX-Location:/i)){er();var r=f.getResponseHeader(\"HX-Location\");var v;if(r.indexOf(\"{\")===0){v=E(r);r=v[\"path\"];delete v[\"path\"]}Nr(\"GET\",r,v).then(function(){tr(r)});return}var n=O(f,/HX-Refresh:/i)&&\"true\"===f.getResponseHeader(\"HX-Refresh\");if(O(f,/HX-Redirect:/i)){location.href=f.getResponseHeader(\"HX-Redirect\");n&&location.reload();return}if(n){location.reload();return}if(O(f,/HX-Retarget:/i)){if(f.getResponseHeader(\"HX-Retarget\")===\"this\"){u.target=l}else{u.target=ue(l,f.getResponseHeader(\"HX-Retarget\"))}}var d=Pr(l,u);var i=f.status>=200&&f.status<400&&f.status!==204;var g=f.response;var a=f.status>=400;var m=Q.config.ignoreTitle;var o=le({shouldSwap:i,serverResponse:g,isError:a,ignoreTitle:m},u);if(!ce(c,\"htmx:beforeSwap\",o))return;c=o.target;g=o.serverResponse;a=o.isError;m=o.ignoreTitle;u.target=c;u.failed=a;u.successful=!a;if(o.shouldSwap){if(f.status===286){at(l)}R(l,function(e){g=e.transformResponse(g,f,l)});if(d.type){er()}var s=e.swapOverride;if(O(f,/HX-Reswap:/i)){s=f.getResponseHeader(\"HX-Reswap\")}var v=wr(l,s);if(v.hasOwnProperty(\"ignoreTitle\")){m=v.ignoreTitle}c.classList.add(Q.config.swappingClass);var p=null;var x=null;var y=function(){try{var e=document.activeElement;var t={};try{t={elt:e,start:e?e.selectionStart:null,end:e?e.selectionEnd:null}}catch(e){}var r;if(h){r=h}if(O(f,/HX-Reselect:/i)){r=f.getResponseHeader(\"HX-Reselect\")}if(d.type){ce(re().body,\"htmx:beforeHistoryUpdate\",le({history:d},u));if(d.type===\"push\"){tr(d.path);ce(re().body,\"htmx:pushedIntoHistory\",{path:d.path})}else{rr(d.path);ce(re().body,\"htmx:replacedInHistory\",{path:d.path})}}var n=T(c);je(v.swapStyle,c,l,g,n,r);if(t.elt&&!se(t.elt)&&ee(t.elt,\"id\")){var i=document.getElementById(ee(t.elt,\"id\"));var a={preventScroll:v.focusScroll!==undefined?!v.focusScroll:!Q.config.defaultFocusScroll};if(i){if(t.start&&i.setSelectionRange){try{i.setSelectionRange(t.start,t.end)}catch(e){}}i.focus(a)}}c.classList.remove(Q.config.swappingClass);oe(n.elts,function(e){if(e.classList){e.classList.add(Q.config.settlingClass)}ce(e,\"htmx:afterSwap\",u)});if(O(f,/HX-Trigger-After-Swap:/i)){var o=l;if(!se(l)){o=re().body}_e(f,\"HX-Trigger-After-Swap\",o)}var s=function(){oe(n.tasks,function(e){e.call()});oe(n.elts,function(e){if(e.classList){e.classList.remove(Q.config.settlingClass)}ce(e,\"htmx:afterSettle\",u)});if(u.pathInfo.anchor){var e=re().getElementById(u.pathInfo.anchor);if(e){e.scrollIntoView({block:\"start\",behavior:\"auto\"})}}if(n.title&&!m){var t=C(\"title\");if(t){t.innerHTML=n.title}else{window.document.title=n.title}}Cr(n.elts,v);if(O(f,/HX-Trigger-After-Settle:/i)){var r=l;if(!se(l)){r=re().body}_e(f,\"HX-Trigger-After-Settle\",r)}ie(p)};if(v.settleDelay>0){setTimeout(s,v.settleDelay)}else{s()}}catch(e){fe(l,\"htmx:swapError\",u);ie(x);throw e}};var b=Q.config.globalViewTransitions;if(v.hasOwnProperty(\"transition\")){b=v.transition}if(b&&ce(l,\"htmx:beforeTransition\",u)&&typeof Promise!==\"undefined\"&&document.startViewTransition){var w=new Promise(function(e,t){p=e;x=t});var S=y;y=function(){document.startViewTransition(function(){S();return w})}}if(v.swapDelay>0){setTimeout(y,v.swapDelay)}else{y()}}if(a){fe(l,\"htmx:responseError\",le({error:\"Response Status Error Code \"+f.status+\" from \"+u.pathInfo.requestPath},u))}}var Xr={};function Dr(){return{init:function(e){return null},onEvent:function(e,t){return true},transformResponse:function(e,t,r){return e},isInlineSwap:function(e){return false},handleSwap:function(e,t,r,n){return false},encodeParameters:function(e,t,r){return null}}}function Ur(e,t){if(t.init){t.init(r)}Xr[e]=le(Dr(),t)}function Br(e){delete Xr[e]}function Fr(e,r,n){if(e==undefined){return r}if(r==undefined){r=[]}if(n==undefined){n=[]}var t=te(e,\"hx-ext\");if(t){oe(t.split(\",\"),function(e){e=e.replace(/ /g,\"\");if(e.slice(0,7)==\"ignore:\"){n.push(e.slice(7));return}if(n.indexOf(e)<0){var t=Xr[e];if(t&&r.indexOf(t)<0){r.push(t)}}})}return Fr(u(e),r,n)}var Vr=false;re().addEventListener(\"DOMContentLoaded\",function(){Vr=true});function jr(e){if(Vr||re().readyState===\"complete\"){e()}else{re().addEventListener(\"DOMContentLoaded\",e)}}function _r(){if(Q.config.includeIndicatorStyles!==false){re().head.insertAdjacentHTML(\"beforeend\",\"\")}}function zr(){var e=re().querySelector('meta[name=\"htmx-config\"]');if(e){return E(e.content)}else{return null}}function $r(){var e=zr();if(e){Q.config=le(Q.config,e)}}jr(function(){$r();_r();var e=re().body;zt(e);var t=re().querySelectorAll(\"[hx-trigger='restored'],[data-hx-trigger='restored']\");e.addEventListener(\"htmx:abort\",function(e){var t=e.target;var r=ae(t);if(r&&r.xhr){r.xhr.abort()}});const r=window.onpopstate?window.onpopstate.bind(window):null;window.onpopstate=function(e){if(e.state&&e.state.htmx){ar();oe(t,function(e){ce(e,\"htmx:restored\",{document:re(),triggerEvent:ce})})}else{if(r){r(e)}}};setTimeout(function(){ce(e,\"htmx:load\",{});e=null},0)});return Q}()});\n\n//# sourceURL=webpack://tailwindtheme/./node_modules/htmx.org/dist/htmx.min.js?"); + +/***/ }), + +/***/ "./Styles/site.css": +/*!*************************!*\ + !*** ./Styles/site.css ***! + \*************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n// extracted by mini-css-extract-plugin\n\n\n//# sourceURL=webpack://tailwindtheme/./Styles/site.css?"); + +/***/ }) + +/******/ }); +/************************************************************************/ +/******/ // The module cache +/******/ var __webpack_module_cache__ = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ // Check if module is in cache +/******/ var cachedModule = __webpack_module_cache__[moduleId]; +/******/ if (cachedModule !== undefined) { +/******/ return cachedModule.exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = __webpack_module_cache__[moduleId] = { +/******/ // no module.id needed +/******/ // no module.loaded needed +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/compat get default export */ +/******/ (() => { +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = (module) => { +/******/ var getter = module && module.__esModule ? +/******/ () => (module['default']) : +/******/ () => (module); +/******/ __webpack_require__.d(getter, { a: getter }); +/******/ return getter; +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/define property getters */ +/******/ (() => { +/******/ // define getter functions for harmony exports +/******/ __webpack_require__.d = (exports, definition) => { +/******/ for(var key in definition) { +/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { +/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); +/******/ } +/******/ } +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/hasOwnProperty shorthand */ +/******/ (() => { +/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) +/******/ })(); +/******/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/************************************************************************/ +/******/ +/******/ // startup +/******/ // Load entry module and return exports +/******/ // This entry module can't be inlined because the eval devtool is used. +/******/ var __webpack_exports__ = __webpack_require__("./Scripts/site.js"); +/******/ +/******/ })() +; \ No newline at end of file diff --git a/src/Themes/TailwindTheme/Manifest.cs b/src/Themes/TailwindTheme/Manifest.cs deleted file mode 100644 index 39e079a..0000000 --- a/src/Themes/TailwindTheme/Manifest.cs +++ /dev/null @@ -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" -)] diff --git a/src/Themes/TailwindTheme/wwwroot/site.css b/src/Themes/TailwindTheme/wwwroot/site.css deleted file mode 100644 index 0fa377e..0000000 --- a/src/Themes/TailwindTheme/wwwroot/site.css +++ /dev/null @@ -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} \ No newline at end of file diff --git a/src/Themes/TailwindTheme/wwwroot/site.js b/src/Themes/TailwindTheme/wwwroot/site.js deleted file mode 100644 index fa96642..0000000 --- a/src/Themes/TailwindTheme/wwwroot/site.js +++ /dev/null @@ -1,83 +0,0 @@ -/******/ (() => { // webpackBootstrap -/******/ var __webpack_modules__ = ({ - -/***/ 926: -/***/ (function(module, exports) { - -var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;(function(e,t){if(true){!(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_FACTORY__ = (t), - __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? - (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), - __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__))}else {}})(typeof self!=="undefined"?self:this,function(){return function(){"use strict";var Q={onLoad:F,process:zt,on:de,off:ge,trigger:ce,ajax:Nr,find:C,findAll:f,closest:v,values:function(e,t){var r=dr(e,t||"post");return r.values},remove:_,addClass:z,removeClass:n,toggleClass:$,takeClass:W,defineExtension:Ur,removeExtension:Br,logAll:V,logNone:j,logger:null,config:{historyEnabled:true,historyCacheSize:10,refreshOnHistoryMiss:false,defaultSwapStyle:"innerHTML",defaultSwapDelay:0,defaultSettleDelay:20,includeIndicatorStyles:true,indicatorClass:"htmx-indicator",requestClass:"htmx-request",addedClass:"htmx-added",settlingClass:"htmx-settling",swappingClass:"htmx-swapping",allowEval:true,allowScriptTags:true,inlineScriptNonce:"",attributesToSettle:["class","style","width","height"],withCredentials:false,timeout:0,wsReconnectDelay:"full-jitter",wsBinaryType:"blob",disableSelector:"[hx-disable], [data-hx-disable]",useTemplateFragments:false,scrollBehavior:"smooth",defaultFocusScroll:false,getCacheBusterParam:false,globalViewTransitions:false,methodsThatUseUrlParams:["get"],selfRequestsOnly:false,ignoreTitle:false,scrollIntoViewOnBoost:true,triggerSpecsCache:null},parseInterval:d,_:t,createEventSource:function(e){return new EventSource(e,{withCredentials:true})},createWebSocket:function(e){var t=new WebSocket(e,[]);t.binaryType=Q.config.wsBinaryType;return t},version:"1.9.10"};var r={addTriggerHandler:Lt,bodyContains:se,canAccessLocalStorage:U,findThisElement:xe,filterValues:yr,hasAttribute:o,getAttributeValue:te,getClosestAttributeValue:ne,getClosestMatch:c,getExpressionVars:Hr,getHeaders:xr,getInputValues:dr,getInternalData:ae,getSwapSpecification:wr,getTriggerSpecs:it,getTarget:ye,makeFragment:l,mergeObjects:le,makeSettleInfo:T,oobSwap:Ee,querySelectorExt:ue,selectAndSwap:je,settleImmediately:nr,shouldCancel:ut,triggerEvent:ce,triggerErrorEvent:fe,withExtensions:R};var w=["get","post","put","delete","patch"];var i=w.map(function(e){return"[hx-"+e+"], [data-hx-"+e+"]"}).join(", ");var S=e("head"),q=e("title"),H=e("svg",true);function e(e,t=false){return new RegExp(`<${e}(\\s[^>]*>|>)([\\s\\S]*?)<\\/${e}>`,t?"gim":"im")}function d(e){if(e==undefined){return undefined}let t=NaN;if(e.slice(-2)=="ms"){t=parseFloat(e.slice(0,-2))}else if(e.slice(-1)=="s"){t=parseFloat(e.slice(0,-1))*1e3}else if(e.slice(-1)=="m"){t=parseFloat(e.slice(0,-1))*1e3*60}else{t=parseFloat(e)}return isNaN(t)?undefined:t}function ee(e,t){return e.getAttribute&&e.getAttribute(t)}function o(e,t){return e.hasAttribute&&(e.hasAttribute(t)||e.hasAttribute("data-"+t))}function te(e,t){return ee(e,t)||ee(e,"data-"+t)}function u(e){return e.parentElement}function re(){return document}function c(e,t){while(e&&!t(e)){e=u(e)}return e?e:null}function L(e,t,r){var n=te(t,r);var i=te(t,"hx-disinherit");if(e!==t&&i&&(i==="*"||i.split(" ").indexOf(r)>=0)){return"unset"}else{return n}}function ne(t,r){var n=null;c(t,function(e){return n=L(t,e,r)});if(n!=="unset"){return n}}function h(e,t){var r=e.matches||e.matchesSelector||e.msMatchesSelector||e.mozMatchesSelector||e.webkitMatchesSelector||e.oMatchesSelector;return r&&r.call(e,t)}function A(e){var t=/<([a-z][^\/\0>\x20\t\r\n\f]*)/i;var r=t.exec(e);if(r){return r[1].toLowerCase()}else{return""}}function a(e,t){var r=new DOMParser;var n=r.parseFromString(e,"text/html");var i=n.body;while(t>0){t--;i=i.firstChild}if(i==null){i=re().createDocumentFragment()}return i}function N(e){return/",0);return i.querySelector("template").content}switch(r){case"thead":case"tbody":case"tfoot":case"colgroup":case"caption":return a(""+n+"
",1);case"col":return a(""+n+"
",2);case"tr":return a(""+n+"
",2);case"td":case"th":return a(""+n+"
",3);case"script":case"style":return a("
"+n+"
",1);default:return a(n,0)}}function ie(e){if(e){e()}}function I(e,t){return Object.prototype.toString.call(e)==="[object "+t+"]"}function k(e){return I(e,"Function")}function P(e){return I(e,"Object")}function ae(e){var t="htmx-internal-data";var r=e[t];if(!r){r=e[t]={}}return r}function M(e){var t=[];if(e){for(var r=0;r=0}function se(e){if(e.getRootNode&&e.getRootNode()instanceof window.ShadowRoot){return re().body.contains(e.getRootNode().host)}else{return re().body.contains(e)}}function D(e){return e.trim().split(/\s+/)}function le(e,t){for(var r in t){if(t.hasOwnProperty(r)){e[r]=t[r]}}return e}function E(e){try{return JSON.parse(e)}catch(e){b(e);return null}}function U(){var e="htmx:localStorageTest";try{localStorage.setItem(e,e);localStorage.removeItem(e);return true}catch(e){return false}}function B(t){try{var e=new URL(t);if(e){t=e.pathname+e.search}if(!/^\/$/.test(t)){t=t.replace(/\/+$/,"")}return t}catch(e){return t}}function t(e){return Tr(re().body,function(){return eval(e)})}function F(t){var e=Q.on("htmx:load",function(e){t(e.detail.elt)});return e}function V(){Q.logger=function(e,t,r){if(console){console.log(t,e,r)}}}function j(){Q.logger=null}function C(e,t){if(t){return e.querySelector(t)}else{return C(re(),e)}}function f(e,t){if(t){return e.querySelectorAll(t)}else{return f(re(),e)}}function _(e,t){e=g(e);if(t){setTimeout(function(){_(e);e=null},t)}else{e.parentElement.removeChild(e)}}function z(e,t,r){e=g(e);if(r){setTimeout(function(){z(e,t);e=null},r)}else{e.classList&&e.classList.add(t)}}function n(e,t,r){e=g(e);if(r){setTimeout(function(){n(e,t);e=null},r)}else{if(e.classList){e.classList.remove(t);if(e.classList.length===0){e.removeAttribute("class")}}}}function $(e,t){e=g(e);e.classList.toggle(t)}function W(e,t){e=g(e);oe(e.parentElement.children,function(e){n(e,t)});z(e,t)}function v(e,t){e=g(e);if(e.closest){return e.closest(t)}else{do{if(e==null||h(e,t)){return e}}while(e=e&&u(e));return null}}function s(e,t){return e.substring(0,t.length)===t}function G(e,t){return e.substring(e.length-t.length)===t}function J(e){var t=e.trim();if(s(t,"<")&&G(t,"/>")){return t.substring(1,t.length-2)}else{return t}}function Z(e,t){if(t.indexOf("closest ")===0){return[v(e,J(t.substr(8)))]}else if(t.indexOf("find ")===0){return[C(e,J(t.substr(5)))]}else if(t==="next"){return[e.nextElementSibling]}else if(t.indexOf("next ")===0){return[K(e,J(t.substr(5)))]}else if(t==="previous"){return[e.previousElementSibling]}else if(t.indexOf("previous ")===0){return[Y(e,J(t.substr(9)))]}else if(t==="document"){return[document]}else if(t==="window"){return[window]}else if(t==="body"){return[document.body]}else{return re().querySelectorAll(J(t))}}var K=function(e,t){var r=re().querySelectorAll(t);for(var n=0;n=0;n--){var i=r[n];if(i.compareDocumentPosition(e)===Node.DOCUMENT_POSITION_FOLLOWING){return i}}};function ue(e,t){if(t){return Z(e,t)[0]}else{return Z(re().body,e)[0]}}function g(e){if(I(e,"String")){return C(e)}else{return e}}function ve(e,t,r){if(k(t)){return{target:re().body,event:e,listener:t}}else{return{target:g(e),event:t,listener:r}}}function de(t,r,n){jr(function(){var e=ve(t,r,n);e.target.addEventListener(e.event,e.listener)});var e=k(r);return e?r:n}function ge(t,r,n){jr(function(){var e=ve(t,r,n);e.target.removeEventListener(e.event,e.listener)});return k(r)?r:n}var me=re().createElement("output");function pe(e,t){var r=ne(e,t);if(r){if(r==="this"){return[xe(e,t)]}else{var n=Z(e,r);if(n.length===0){b('The selector "'+r+'" on '+t+" returned no matches!");return[me]}else{return n}}}}function xe(e,t){return c(e,function(e){return te(e,t)!=null})}function ye(e){var t=ne(e,"hx-target");if(t){if(t==="this"){return xe(e,"hx-target")}else{return ue(e,t)}}else{var r=ae(e);if(r.boosted){return re().body}else{return e}}}function be(e){var t=Q.config.attributesToSettle;for(var r=0;r0){o=e.substr(0,e.indexOf(":"));t=e.substr(e.indexOf(":")+1,e.length)}else{o=e}var r=re().querySelectorAll(t);if(r){oe(r,function(e){var t;var r=i.cloneNode(true);t=re().createDocumentFragment();t.appendChild(r);if(!Se(o,e)){t=r}var n={shouldSwap:true,target:e,fragment:t};if(!ce(e,"htmx:oobBeforeSwap",n))return;e=n.target;if(n["shouldSwap"]){Fe(o,e,e,t,a)}oe(a.elts,function(e){ce(e,"htmx:oobAfterSwap",n)})});i.parentNode.removeChild(i)}else{i.parentNode.removeChild(i);fe(re().body,"htmx:oobErrorNoTarget",{content:i})}return e}function Ce(e,t,r){var n=ne(e,"hx-select-oob");if(n){var i=n.split(",");for(var a=0;a0){var r=t.replace("'","\\'");var n=e.tagName.replace(":","\\:");var i=o.querySelector(n+"[id='"+r+"']");if(i&&i!==o){var a=e.cloneNode();we(e,i);s.tasks.push(function(){we(e,a)})}}})}function Oe(e){return function(){n(e,Q.config.addedClass);zt(e);Nt(e);qe(e);ce(e,"htmx:load")}}function qe(e){var t="[autofocus]";var r=h(e,t)?e:e.querySelector(t);if(r!=null){r.focus()}}function m(e,t,r,n){Te(e,r,n);while(r.childNodes.length>0){var i=r.firstChild;z(i,Q.config.addedClass);e.insertBefore(i,t);if(i.nodeType!==Node.TEXT_NODE&&i.nodeType!==Node.COMMENT_NODE){n.tasks.push(Oe(i))}}}function He(e,t){var r=0;while(r-1){var t=e.replace(H,"");var r=t.match(q);if(r){return r[2]}}}function je(e,t,r,n,i,a){i.title=Ve(n);var o=l(n);if(o){Ce(r,o,i);o=Be(r,o,a);Re(o);return Fe(e,r,t,o,i)}}function _e(e,t,r){var n=e.getResponseHeader(t);if(n.indexOf("{")===0){var i=E(n);for(var a in i){if(i.hasOwnProperty(a)){var o=i[a];if(!P(o)){o={value:o}}ce(r,a,o)}}}else{var s=n.split(",");for(var l=0;l0){var o=t[0];if(o==="]"){n--;if(n===0){if(a===null){i=i+"true"}t.shift();i+=")})";try{var s=Tr(e,function(){return Function(i)()},function(){return true});s.source=i;return s}catch(e){fe(re().body,"htmx:syntax:error",{error:e,source:i});return null}}}else if(o==="["){n++}if(Qe(o,a,r)){i+="(("+r+"."+o+") ? ("+r+"."+o+") : (window."+o+"))"}else{i=i+o}a=t.shift()}}}function y(e,t){var r="";while(e.length>0&&!t.test(e[0])){r+=e.shift()}return r}function tt(e){var t;if(e.length>0&&Ze.test(e[0])){e.shift();t=y(e,Ke).trim();e.shift()}else{t=y(e,x)}return t}var rt="input, textarea, select";function nt(e,t,r){var n=[];var i=Ye(t);do{y(i,Je);var a=i.length;var o=y(i,/[,\[\s]/);if(o!==""){if(o==="every"){var s={trigger:"every"};y(i,Je);s.pollInterval=d(y(i,/[,\[\s]/));y(i,Je);var l=et(e,i,"event");if(l){s.eventFilter=l}n.push(s)}else if(o.indexOf("sse:")===0){n.push({trigger:"sse",sseEvent:o.substr(4)})}else{var u={trigger:o};var l=et(e,i,"event");if(l){u.eventFilter=l}while(i.length>0&&i[0]!==","){y(i,Je);var f=i.shift();if(f==="changed"){u.changed=true}else if(f==="once"){u.once=true}else if(f==="consume"){u.consume=true}else if(f==="delay"&&i[0]===":"){i.shift();u.delay=d(y(i,x))}else if(f==="from"&&i[0]===":"){i.shift();if(Ze.test(i[0])){var c=tt(i)}else{var c=y(i,x);if(c==="closest"||c==="find"||c==="next"||c==="previous"){i.shift();var h=tt(i);if(h.length>0){c+=" "+h}}}u.from=c}else if(f==="target"&&i[0]===":"){i.shift();u.target=tt(i)}else if(f==="throttle"&&i[0]===":"){i.shift();u.throttle=d(y(i,x))}else if(f==="queue"&&i[0]===":"){i.shift();u.queue=y(i,x)}else if(f==="root"&&i[0]===":"){i.shift();u[f]=tt(i)}else if(f==="threshold"&&i[0]===":"){i.shift();u[f]=y(i,x)}else{fe(e,"htmx:syntax:error",{token:i.shift()})}}n.push(u)}}if(i.length===a){fe(e,"htmx:syntax:error",{token:i.shift()})}y(i,Je)}while(i[0]===","&&i.shift());if(r){r[t]=n}return n}function it(e){var t=te(e,"hx-trigger");var r=[];if(t){var n=Q.config.triggerSpecsCache;r=n&&n[t]||nt(e,t,n)}if(r.length>0){return r}else if(h(e,"form")){return[{trigger:"submit"}]}else if(h(e,'input[type="button"], input[type="submit"]')){return[{trigger:"click"}]}else if(h(e,rt)){return[{trigger:"change"}]}else{return[{trigger:"click"}]}}function at(e){ae(e).cancelled=true}function ot(e,t,r){var n=ae(e);n.timeout=setTimeout(function(){if(se(e)&&n.cancelled!==true){if(!ct(r,e,Wt("hx:poll:trigger",{triggerSpec:r,target:e}))){t(e)}ot(e,t,r)}},r.pollInterval)}function st(e){return location.hostname===e.hostname&&ee(e,"href")&&ee(e,"href").indexOf("#")!==0}function lt(t,r,e){if(t.tagName==="A"&&st(t)&&(t.target===""||t.target==="_self")||t.tagName==="FORM"){r.boosted=true;var n,i;if(t.tagName==="A"){n="get";i=ee(t,"href")}else{var a=ee(t,"method");n=a?a.toLowerCase():"get";if(n==="get"){}i=ee(t,"action")}e.forEach(function(e){ht(t,function(e,t){if(v(e,Q.config.disableSelector)){p(e);return}he(n,i,e,t)},r,e,true)})}}function ut(e,t){if(e.type==="submit"||e.type==="click"){if(t.tagName==="FORM"){return true}if(h(t,'input[type="submit"], button')&&v(t,"form")!==null){return true}if(t.tagName==="A"&&t.href&&(t.getAttribute("href")==="#"||t.getAttribute("href").indexOf("#")!==0)){return true}}return false}function ft(e,t){return ae(e).boosted&&e.tagName==="A"&&t.type==="click"&&(t.ctrlKey||t.metaKey)}function ct(e,t,r){var n=e.eventFilter;if(n){try{return n.call(t,r)!==true}catch(e){fe(re().body,"htmx:eventFilter:error",{error:e,source:n.source});return true}}return false}function ht(a,o,e,s,l){var u=ae(a);var t;if(s.from){t=Z(a,s.from)}else{t=[a]}if(s.changed){t.forEach(function(e){var t=ae(e);t.lastValue=e.value})}oe(t,function(n){var i=function(e){if(!se(a)){n.removeEventListener(s.trigger,i);return}if(ft(a,e)){return}if(l||ut(e,a)){e.preventDefault()}if(ct(s,a,e)){return}var t=ae(e);t.triggerSpec=s;if(t.handledFor==null){t.handledFor=[]}if(t.handledFor.indexOf(a)<0){t.handledFor.push(a);if(s.consume){e.stopPropagation()}if(s.target&&e.target){if(!h(e.target,s.target)){return}}if(s.once){if(u.triggeredOnce){return}else{u.triggeredOnce=true}}if(s.changed){var r=ae(n);if(r.lastValue===n.value){return}r.lastValue=n.value}if(u.delayed){clearTimeout(u.delayed)}if(u.throttle){return}if(s.throttle>0){if(!u.throttle){o(a,e);u.throttle=setTimeout(function(){u.throttle=null},s.throttle)}}else if(s.delay>0){u.delayed=setTimeout(function(){o(a,e)},s.delay)}else{ce(a,"htmx:trigger");o(a,e)}}};if(e.listenerInfos==null){e.listenerInfos=[]}e.listenerInfos.push({trigger:s.trigger,listener:i,on:n});n.addEventListener(s.trigger,i)})}var vt=false;var dt=null;function gt(){if(!dt){dt=function(){vt=true};window.addEventListener("scroll",dt);setInterval(function(){if(vt){vt=false;oe(re().querySelectorAll("[hx-trigger='revealed'],[data-hx-trigger='revealed']"),function(e){mt(e)})}},200)}}function mt(t){if(!o(t,"data-hx-revealed")&&X(t)){t.setAttribute("data-hx-revealed","true");var e=ae(t);if(e.initHash){ce(t,"revealed")}else{t.addEventListener("htmx:afterProcessNode",function(e){ce(t,"revealed")},{once:true})}}}function pt(e,t,r){var n=D(r);for(var i=0;i=0){var t=wt(n);setTimeout(function(){xt(s,r,n+1)},t)}};t.onopen=function(e){n=0};ae(s).webSocket=t;t.addEventListener("message",function(e){if(yt(s)){return}var t=e.data;R(s,function(e){t=e.transformResponse(t,null,s)});var r=T(s);var n=l(t);var i=M(n.children);for(var a=0;a0){ce(u,"htmx:validation:halted",i);return}t.send(JSON.stringify(l));if(ut(e,u)){e.preventDefault()}})}else{fe(u,"htmx:noWebSocketSourceError")}}function wt(e){var t=Q.config.wsReconnectDelay;if(typeof t==="function"){return t(e)}if(t==="full-jitter"){var r=Math.min(e,6);var n=1e3*Math.pow(2,r);return n*Math.random()}b('htmx.config.wsReconnectDelay must either be a function or the string "full-jitter"')}function St(e,t,r){var n=D(r);for(var i=0;i0){setTimeout(i,n)}else{i()}}function Ht(t,i,e){var a=false;oe(w,function(r){if(o(t,"hx-"+r)){var n=te(t,"hx-"+r);a=true;i.path=n;i.verb=r;e.forEach(function(e){Lt(t,e,i,function(e,t){if(v(e,Q.config.disableSelector)){p(e);return}he(r,n,e,t)})})}});return a}function Lt(n,e,t,r){if(e.sseEvent){Rt(n,r,e.sseEvent)}else if(e.trigger==="revealed"){gt();ht(n,r,t,e);mt(n)}else if(e.trigger==="intersect"){var i={};if(e.root){i.root=ue(n,e.root)}if(e.threshold){i.threshold=parseFloat(e.threshold)}var a=new IntersectionObserver(function(e){for(var t=0;t0){t.polling=true;ot(n,r,e)}else{ht(n,r,t,e)}}function At(e){if(Q.config.allowScriptTags&&(e.type==="text/javascript"||e.type==="module"||e.type==="")){var t=re().createElement("script");oe(e.attributes,function(e){t.setAttribute(e.name,e.value)});t.textContent=e.textContent;t.async=false;if(Q.config.inlineScriptNonce){t.nonce=Q.config.inlineScriptNonce}var r=e.parentElement;try{r.insertBefore(t,e)}catch(e){b(e)}finally{if(e.parentElement){e.parentElement.removeChild(e)}}}}function Nt(e){if(h(e,"script")){At(e)}oe(f(e,"script"),function(e){At(e)})}function It(e){var t=e.attributes;for(var r=0;r0){var o=n.shift();var s=o.match(/^\s*([a-zA-Z:\-\.]+:)(.*)/);if(a===0&&s){o.split(":");i=s[1].slice(0,-1);r[i]=s[2]}else{r[i]+=o}a+=Bt(o)}for(var l in r){Ft(e,l,r[l])}}}function jt(e){Ae(e);for(var t=0;tQ.config.historyCacheSize){i.shift()}while(i.length>0){try{localStorage.setItem("htmx-history-cache",JSON.stringify(i));break}catch(e){fe(re().body,"htmx:historyCacheError",{cause:e,cache:i});i.shift()}}}function Yt(e){if(!U()){return null}e=B(e);var t=E(localStorage.getItem("htmx-history-cache"))||[];for(var r=0;r=200&&this.status<400){ce(re().body,"htmx:historyCacheMissLoad",o);var e=l(this.response);e=e.querySelector("[hx-history-elt],[data-hx-history-elt]")||e;var t=Zt();var r=T(t);var n=Ve(this.response);if(n){var i=C("title");if(i){i.innerHTML=n}else{window.document.title=n}}Ue(t,e,r);nr(r.tasks);Jt=a;ce(re().body,"htmx:historyRestore",{path:a,cacheMiss:true,serverResponse:this.response})}else{fe(re().body,"htmx:historyCacheMissLoadError",o)}};e.send()}function ar(e){er();e=e||location.pathname+location.search;var t=Yt(e);if(t){var r=l(t.content);var n=Zt();var i=T(n);Ue(n,r,i);nr(i.tasks);document.title=t.title;setTimeout(function(){window.scrollTo(0,t.scroll)},0);Jt=e;ce(re().body,"htmx:historyRestore",{path:e,item:t})}else{if(Q.config.refreshOnHistoryMiss){window.location.reload(true)}else{ir(e)}}}function or(e){var t=pe(e,"hx-indicator");if(t==null){t=[e]}oe(t,function(e){var t=ae(e);t.requestCount=(t.requestCount||0)+1;e.classList["add"].call(e.classList,Q.config.requestClass)});return t}function sr(e){var t=pe(e,"hx-disabled-elt");if(t==null){t=[]}oe(t,function(e){var t=ae(e);t.requestCount=(t.requestCount||0)+1;e.setAttribute("disabled","")});return t}function lr(e,t){oe(e,function(e){var t=ae(e);t.requestCount=(t.requestCount||0)-1;if(t.requestCount===0){e.classList["remove"].call(e.classList,Q.config.requestClass)}});oe(t,function(e){var t=ae(e);t.requestCount=(t.requestCount||0)-1;if(t.requestCount===0){e.removeAttribute("disabled")}})}function ur(e,t){for(var r=0;r=0}function wr(e,t){var r=t?t:ne(e,"hx-swap");var n={swapStyle:ae(e).boosted?"innerHTML":Q.config.defaultSwapStyle,swapDelay:Q.config.defaultSwapDelay,settleDelay:Q.config.defaultSettleDelay};if(Q.config.scrollIntoViewOnBoost&&ae(e).boosted&&!br(e)){n["show"]="top"}if(r){var i=D(r);if(i.length>0){for(var a=0;a0?l.join(":"):null;n["scroll"]=u;n["scrollTarget"]=f}else if(o.indexOf("show:")===0){var c=o.substr(5);var l=c.split(":");var h=l.pop();var f=l.length>0?l.join(":"):null;n["show"]=h;n["showTarget"]=f}else if(o.indexOf("focus-scroll:")===0){var v=o.substr("focus-scroll:".length);n["focusScroll"]=v=="true"}else if(a==0){n["swapStyle"]=o}else{b("Unknown modifier in hx-swap: "+o)}}}}return n}function Sr(e){return ne(e,"hx-encoding")==="multipart/form-data"||h(e,"form")&&ee(e,"enctype")==="multipart/form-data"}function Er(t,r,n){var i=null;R(r,function(e){if(i==null){i=e.encodeParameters(t,n,r)}});if(i!=null){return i}else{if(Sr(r)){return pr(n)}else{return mr(n)}}}function T(e){return{tasks:[],elts:[e]}}function Cr(e,t){var r=e[0];var n=e[e.length-1];if(t.scroll){var i=null;if(t.scrollTarget){i=ue(r,t.scrollTarget)}if(t.scroll==="top"&&(r||i)){i=i||r;i.scrollTop=0}if(t.scroll==="bottom"&&(n||i)){i=i||n;i.scrollTop=i.scrollHeight}}if(t.show){var i=null;if(t.showTarget){var a=t.showTarget;if(t.showTarget==="window"){a="body"}i=ue(r,a)}if(t.show==="top"&&(r||i)){i=i||r;i.scrollIntoView({block:"start",behavior:Q.config.scrollBehavior})}if(t.show==="bottom"&&(n||i)){i=i||n;i.scrollIntoView({block:"end",behavior:Q.config.scrollBehavior})}}}function Rr(e,t,r,n){if(n==null){n={}}if(e==null){return n}var i=te(e,t);if(i){var a=i.trim();var o=r;if(a==="unset"){return null}if(a.indexOf("javascript:")===0){a=a.substr(11);o=true}else if(a.indexOf("js:")===0){a=a.substr(3);o=true}if(a.indexOf("{")!==0){a="{"+a+"}"}var s;if(o){s=Tr(e,function(){return Function("return ("+a+")")()},{})}else{s=E(a)}for(var l in s){if(s.hasOwnProperty(l)){if(n[l]==null){n[l]=s[l]}}}}return Rr(u(e),t,r,n)}function Tr(e,t,r){if(Q.config.allowEval){return t()}else{fe(e,"htmx:evalDisallowedError");return r}}function Or(e,t){return Rr(e,"hx-vars",true,t)}function qr(e,t){return Rr(e,"hx-vals",false,t)}function Hr(e){return le(Or(e),qr(e))}function Lr(t,r,n){if(n!==null){try{t.setRequestHeader(r,n)}catch(e){t.setRequestHeader(r,encodeURIComponent(n));t.setRequestHeader(r+"-URI-AutoEncoded","true")}}}function Ar(t){if(t.responseURL&&typeof URL!=="undefined"){try{var e=new URL(t.responseURL);return e.pathname+e.search}catch(e){fe(re().body,"htmx:badResponseUrl",{url:t.responseURL})}}}function O(e,t){return t.test(e.getAllResponseHeaders())}function Nr(e,t,r){e=e.toLowerCase();if(r){if(r instanceof Element||I(r,"String")){return he(e,t,null,null,{targetOverride:g(r),returnPromise:true})}else{return he(e,t,g(r.source),r.event,{handler:r.handler,headers:r.headers,values:r.values,targetOverride:g(r.target),swapOverride:r.swap,select:r.select,returnPromise:true})}}else{return he(e,t,null,null,{returnPromise:true})}}function Ir(e){var t=[];while(e){t.push(e);e=e.parentElement}return t}function kr(e,t,r){var n;var i;if(typeof URL==="function"){i=new URL(t,document.location.href);var a=document.location.origin;n=a===i.origin}else{i=t;n=s(t,document.location.origin)}if(Q.config.selfRequestsOnly){if(!n){return false}}return ce(e,"htmx:validateUrl",le({url:i,sameHost:n},r))}function he(t,r,n,i,a,e){var o=null;var s=null;a=a!=null?a:{};if(a.returnPromise&&typeof Promise!=="undefined"){var l=new Promise(function(e,t){o=e;s=t})}if(n==null){n=re().body}var M=a.handler||Mr;var X=a.select||null;if(!se(n)){ie(o);return l}var u=a.targetOverride||ye(n);if(u==null||u==me){fe(n,"htmx:targetError",{target:te(n,"hx-target")});ie(s);return l}var f=ae(n);var c=f.lastButtonClicked;if(c){var h=ee(c,"formaction");if(h!=null){r=h}var v=ee(c,"formmethod");if(v!=null){if(v.toLowerCase()!=="dialog"){t=v}}}var d=ne(n,"hx-confirm");if(e===undefined){var D=function(e){return he(t,r,n,i,a,!!e)};var U={target:u,elt:n,path:r,verb:t,triggeringEvent:i,etc:a,issueRequest:D,question:d};if(ce(n,"htmx:confirm",U)===false){ie(o);return l}}var g=n;var m=ne(n,"hx-sync");var p=null;var x=false;if(m){var B=m.split(":");var F=B[0].trim();if(F==="this"){g=xe(n,"hx-sync")}else{g=ue(n,F)}m=(B[1]||"drop").trim();f=ae(g);if(m==="drop"&&f.xhr&&f.abortable!==true){ie(o);return l}else if(m==="abort"){if(f.xhr){ie(o);return l}else{x=true}}else if(m==="replace"){ce(g,"htmx:abort")}else if(m.indexOf("queue")===0){var V=m.split(" ");p=(V[1]||"last").trim()}}if(f.xhr){if(f.abortable){ce(g,"htmx:abort")}else{if(p==null){if(i){var y=ae(i);if(y&&y.triggerSpec&&y.triggerSpec.queue){p=y.triggerSpec.queue}}if(p==null){p="last"}}if(f.queuedRequests==null){f.queuedRequests=[]}if(p==="first"&&f.queuedRequests.length===0){f.queuedRequests.push(function(){he(t,r,n,i,a)})}else if(p==="all"){f.queuedRequests.push(function(){he(t,r,n,i,a)})}else if(p==="last"){f.queuedRequests=[];f.queuedRequests.push(function(){he(t,r,n,i,a)})}ie(o);return l}}var b=new XMLHttpRequest;f.xhr=b;f.abortable=x;var w=function(){f.xhr=null;f.abortable=false;if(f.queuedRequests!=null&&f.queuedRequests.length>0){var e=f.queuedRequests.shift();e()}};var j=ne(n,"hx-prompt");if(j){var S=prompt(j);if(S===null||!ce(n,"htmx:prompt",{prompt:S,target:u})){ie(o);w();return l}}if(d&&!e){if(!confirm(d)){ie(o);w();return l}}var E=xr(n,u,S);if(t!=="get"&&!Sr(n)){E["Content-Type"]="application/x-www-form-urlencoded"}if(a.headers){E=le(E,a.headers)}var _=dr(n,t);var C=_.errors;var R=_.values;if(a.values){R=le(R,a.values)}var z=Hr(n);var $=le(R,z);var T=yr($,n);if(Q.config.getCacheBusterParam&&t==="get"){T["org.htmx.cache-buster"]=ee(u,"id")||"true"}if(r==null||r===""){r=re().location.href}var O=Rr(n,"hx-request");var W=ae(n).boosted;var q=Q.config.methodsThatUseUrlParams.indexOf(t)>=0;var H={boosted:W,useUrlParams:q,parameters:T,unfilteredParameters:$,headers:E,target:u,verb:t,errors:C,withCredentials:a.credentials||O.credentials||Q.config.withCredentials,timeout:a.timeout||O.timeout||Q.config.timeout,path:r,triggeringEvent:i};if(!ce(n,"htmx:configRequest",H)){ie(o);w();return l}r=H.path;t=H.verb;E=H.headers;T=H.parameters;C=H.errors;q=H.useUrlParams;if(C&&C.length>0){ce(n,"htmx:validation:halted",H);ie(o);w();return l}var G=r.split("#");var J=G[0];var L=G[1];var A=r;if(q){A=J;var Z=Object.keys(T).length!==0;if(Z){if(A.indexOf("?")<0){A+="?"}else{A+="&"}A+=mr(T);if(L){A+="#"+L}}}if(!kr(n,A,H)){fe(n,"htmx:invalidPath",H);ie(s);return l}b.open(t.toUpperCase(),A,true);b.overrideMimeType("text/html");b.withCredentials=H.withCredentials;b.timeout=H.timeout;if(O.noHeaders){}else{for(var N in E){if(E.hasOwnProperty(N)){var K=E[N];Lr(b,N,K)}}}var I={xhr:b,target:u,requestConfig:H,etc:a,boosted:W,select:X,pathInfo:{requestPath:r,finalRequestPath:A,anchor:L}};b.onload=function(){try{var e=Ir(n);I.pathInfo.responsePath=Ar(b);M(n,I);lr(k,P);ce(n,"htmx:afterRequest",I);ce(n,"htmx:afterOnLoad",I);if(!se(n)){var t=null;while(e.length>0&&t==null){var r=e.shift();if(se(r)){t=r}}if(t){ce(t,"htmx:afterRequest",I);ce(t,"htmx:afterOnLoad",I)}}ie(o);w()}catch(e){fe(n,"htmx:onLoadError",le({error:e},I));throw e}};b.onerror=function(){lr(k,P);fe(n,"htmx:afterRequest",I);fe(n,"htmx:sendError",I);ie(s);w()};b.onabort=function(){lr(k,P);fe(n,"htmx:afterRequest",I);fe(n,"htmx:sendAbort",I);ie(s);w()};b.ontimeout=function(){lr(k,P);fe(n,"htmx:afterRequest",I);fe(n,"htmx:timeout",I);ie(s);w()};if(!ce(n,"htmx:beforeRequest",I)){ie(o);w();return l}var k=or(n);var P=sr(n);oe(["loadstart","loadend","progress","abort"],function(t){oe([b,b.upload],function(e){e.addEventListener(t,function(e){ce(n,"htmx:xhr:"+t,{lengthComputable:e.lengthComputable,loaded:e.loaded,total:e.total})})})});ce(n,"htmx:beforeSend",I);var Y=q?null:Er(b,n,T);b.send(Y);return l}function Pr(e,t){var r=t.xhr;var n=null;var i=null;if(O(r,/HX-Push:/i)){n=r.getResponseHeader("HX-Push");i="push"}else if(O(r,/HX-Push-Url:/i)){n=r.getResponseHeader("HX-Push-Url");i="push"}else if(O(r,/HX-Replace-Url:/i)){n=r.getResponseHeader("HX-Replace-Url");i="replace"}if(n){if(n==="false"){return{}}else{return{type:i,path:n}}}var a=t.pathInfo.finalRequestPath;var o=t.pathInfo.responsePath;var s=ne(e,"hx-push-url");var l=ne(e,"hx-replace-url");var u=ae(e).boosted;var f=null;var c=null;if(s){f="push";c=s}else if(l){f="replace";c=l}else if(u){f="push";c=o||a}if(c){if(c==="false"){return{}}if(c==="true"){c=o||a}if(t.pathInfo.anchor&&c.indexOf("#")===-1){c=c+"#"+t.pathInfo.anchor}return{type:f,path:c}}else{return{}}}function Mr(l,u){var f=u.xhr;var c=u.target;var e=u.etc;var t=u.requestConfig;var h=u.select;if(!ce(l,"htmx:beforeOnLoad",u))return;if(O(f,/HX-Trigger:/i)){_e(f,"HX-Trigger",l)}if(O(f,/HX-Location:/i)){er();var r=f.getResponseHeader("HX-Location");var v;if(r.indexOf("{")===0){v=E(r);r=v["path"];delete v["path"]}Nr("GET",r,v).then(function(){tr(r)});return}var n=O(f,/HX-Refresh:/i)&&"true"===f.getResponseHeader("HX-Refresh");if(O(f,/HX-Redirect:/i)){location.href=f.getResponseHeader("HX-Redirect");n&&location.reload();return}if(n){location.reload();return}if(O(f,/HX-Retarget:/i)){if(f.getResponseHeader("HX-Retarget")==="this"){u.target=l}else{u.target=ue(l,f.getResponseHeader("HX-Retarget"))}}var d=Pr(l,u);var i=f.status>=200&&f.status<400&&f.status!==204;var g=f.response;var a=f.status>=400;var m=Q.config.ignoreTitle;var o=le({shouldSwap:i,serverResponse:g,isError:a,ignoreTitle:m},u);if(!ce(c,"htmx:beforeSwap",o))return;c=o.target;g=o.serverResponse;a=o.isError;m=o.ignoreTitle;u.target=c;u.failed=a;u.successful=!a;if(o.shouldSwap){if(f.status===286){at(l)}R(l,function(e){g=e.transformResponse(g,f,l)});if(d.type){er()}var s=e.swapOverride;if(O(f,/HX-Reswap:/i)){s=f.getResponseHeader("HX-Reswap")}var v=wr(l,s);if(v.hasOwnProperty("ignoreTitle")){m=v.ignoreTitle}c.classList.add(Q.config.swappingClass);var p=null;var x=null;var y=function(){try{var e=document.activeElement;var t={};try{t={elt:e,start:e?e.selectionStart:null,end:e?e.selectionEnd:null}}catch(e){}var r;if(h){r=h}if(O(f,/HX-Reselect:/i)){r=f.getResponseHeader("HX-Reselect")}if(d.type){ce(re().body,"htmx:beforeHistoryUpdate",le({history:d},u));if(d.type==="push"){tr(d.path);ce(re().body,"htmx:pushedIntoHistory",{path:d.path})}else{rr(d.path);ce(re().body,"htmx:replacedInHistory",{path:d.path})}}var n=T(c);je(v.swapStyle,c,l,g,n,r);if(t.elt&&!se(t.elt)&&ee(t.elt,"id")){var i=document.getElementById(ee(t.elt,"id"));var a={preventScroll:v.focusScroll!==undefined?!v.focusScroll:!Q.config.defaultFocusScroll};if(i){if(t.start&&i.setSelectionRange){try{i.setSelectionRange(t.start,t.end)}catch(e){}}i.focus(a)}}c.classList.remove(Q.config.swappingClass);oe(n.elts,function(e){if(e.classList){e.classList.add(Q.config.settlingClass)}ce(e,"htmx:afterSwap",u)});if(O(f,/HX-Trigger-After-Swap:/i)){var o=l;if(!se(l)){o=re().body}_e(f,"HX-Trigger-After-Swap",o)}var s=function(){oe(n.tasks,function(e){e.call()});oe(n.elts,function(e){if(e.classList){e.classList.remove(Q.config.settlingClass)}ce(e,"htmx:afterSettle",u)});if(u.pathInfo.anchor){var e=re().getElementById(u.pathInfo.anchor);if(e){e.scrollIntoView({block:"start",behavior:"auto"})}}if(n.title&&!m){var t=C("title");if(t){t.innerHTML=n.title}else{window.document.title=n.title}}Cr(n.elts,v);if(O(f,/HX-Trigger-After-Settle:/i)){var r=l;if(!se(l)){r=re().body}_e(f,"HX-Trigger-After-Settle",r)}ie(p)};if(v.settleDelay>0){setTimeout(s,v.settleDelay)}else{s()}}catch(e){fe(l,"htmx:swapError",u);ie(x);throw e}};var b=Q.config.globalViewTransitions;if(v.hasOwnProperty("transition")){b=v.transition}if(b&&ce(l,"htmx:beforeTransition",u)&&typeof Promise!=="undefined"&&document.startViewTransition){var w=new Promise(function(e,t){p=e;x=t});var S=y;y=function(){document.startViewTransition(function(){S();return w})}}if(v.swapDelay>0){setTimeout(y,v.swapDelay)}else{y()}}if(a){fe(l,"htmx:responseError",le({error:"Response Status Error Code "+f.status+" from "+u.pathInfo.requestPath},u))}}var Xr={};function Dr(){return{init:function(e){return null},onEvent:function(e,t){return true},transformResponse:function(e,t,r){return e},isInlineSwap:function(e){return false},handleSwap:function(e,t,r,n){return false},encodeParameters:function(e,t,r){return null}}}function Ur(e,t){if(t.init){t.init(r)}Xr[e]=le(Dr(),t)}function Br(e){delete Xr[e]}function Fr(e,r,n){if(e==undefined){return r}if(r==undefined){r=[]}if(n==undefined){n=[]}var t=te(e,"hx-ext");if(t){oe(t.split(","),function(e){e=e.replace(/ /g,"");if(e.slice(0,7)=="ignore:"){n.push(e.slice(7));return}if(n.indexOf(e)<0){var t=Xr[e];if(t&&r.indexOf(t)<0){r.push(t)}}})}return Fr(u(e),r,n)}var Vr=false;re().addEventListener("DOMContentLoaded",function(){Vr=true});function jr(e){if(Vr||re().readyState==="complete"){e()}else{re().addEventListener("DOMContentLoaded",e)}}function _r(){if(Q.config.includeIndicatorStyles!==false){re().head.insertAdjacentHTML("beforeend","")}}function zr(){var e=re().querySelector('meta[name="htmx-config"]');if(e){return E(e.content)}else{return null}}function $r(){var e=zr();if(e){Q.config=le(Q.config,e)}}jr(function(){$r();_r();var e=re().body;zt(e);var t=re().querySelectorAll("[hx-trigger='restored'],[data-hx-trigger='restored']");e.addEventListener("htmx:abort",function(e){var t=e.target;var r=ae(t);if(r&&r.xhr){r.xhr.abort()}});const r=window.onpopstate?window.onpopstate.bind(window):null;window.onpopstate=function(e){if(e.state&&e.state.htmx){ar();oe(t,function(e){ce(e,"htmx:restored",{document:re(),triggerEvent:ce})})}else{if(r){r(e)}}};setTimeout(function(){ce(e,"htmx:load",{});e=null},0)});return Q}()}); - -/***/ }) - -/******/ }); -/************************************************************************/ -/******/ // The module cache -/******/ var __webpack_module_cache__ = {}; -/******/ -/******/ // The require function -/******/ function __webpack_require__(moduleId) { -/******/ // Check if module is in cache -/******/ var cachedModule = __webpack_module_cache__[moduleId]; -/******/ if (cachedModule !== undefined) { -/******/ return cachedModule.exports; -/******/ } -/******/ // Create a new module (and put it into the cache) -/******/ var module = __webpack_module_cache__[moduleId] = { -/******/ // no module.id needed -/******/ // no module.loaded needed -/******/ exports: {} -/******/ }; -/******/ -/******/ // Execute the module function -/******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__); -/******/ -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } -/******/ -/************************************************************************/ -/******/ /* webpack/runtime/compat get default export */ -/******/ (() => { -/******/ // getDefaultExport function for compatibility with non-harmony modules -/******/ __webpack_require__.n = (module) => { -/******/ var getter = module && module.__esModule ? -/******/ () => (module['default']) : -/******/ () => (module); -/******/ __webpack_require__.d(getter, { a: getter }); -/******/ return getter; -/******/ }; -/******/ })(); -/******/ -/******/ /* webpack/runtime/define property getters */ -/******/ (() => { -/******/ // define getter functions for harmony exports -/******/ __webpack_require__.d = (exports, definition) => { -/******/ for(var key in definition) { -/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { -/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); -/******/ } -/******/ } -/******/ }; -/******/ })(); -/******/ -/******/ /* webpack/runtime/hasOwnProperty shorthand */ -/******/ (() => { -/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) -/******/ })(); -/******/ -/************************************************************************/ -var __webpack_exports__ = {}; -// This entry need to be wrapped in an IIFE because it need to be in strict mode. -(() => { -"use strict"; -/* harmony import */ var htmx_org__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(926); -/* harmony import */ var htmx_org__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(htmx_org__WEBPACK_IMPORTED_MODULE_0__); - - - -})(); - -/******/ })() -; \ No newline at end of file diff --git a/src/Twain.Web/Twain.Web.csproj b/src/Twain.Web/Twain.Web.csproj index d6872d6..3408375 100644 --- a/src/Twain.Web/Twain.Web.csproj +++ b/src/Twain.Web/Twain.Web.csproj @@ -25,8 +25,9 @@ + - + diff --git a/tools/Build/Build.cs b/tools/Build/Build.cs new file mode 100644 index 0000000..fa6e361 --- /dev/null +++ b/tools/Build/Build.cs @@ -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 ", "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); + } + }); +} diff --git a/tools/Build/Program.cs b/tools/Build/Program.cs deleted file mode 100644 index 415b512..0000000 --- a/tools/Build/Program.cs +++ /dev/null @@ -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 ", "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() - }); - }); - }); -}