Add project files.
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
using Elsa.Studio.Components;
|
||||
using Elsa.Studio.Host.CustomElements.Services;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace Elsa.Studio.Host.CustomElements.Components;
|
||||
|
||||
public abstract class BackendComponentBase : StudioComponentBase
|
||||
{
|
||||
[Parameter] public string? RemoteEndpoint { get; set; }
|
||||
[Parameter] public string? ApiKey { get; set; }
|
||||
[Parameter] public string? AccessToken { get; set; }
|
||||
[Parameter] public string? TenantId { get; set; }
|
||||
[Parameter] public string? TenantIdHeaderName { get; set; }
|
||||
[Inject] private BackendService BackendService { get; set; } = null!;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(RemoteEndpoint))
|
||||
BackendService.RemoteEndpoint = RemoteEndpoint;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(ApiKey))
|
||||
BackendService.ApiKey = ApiKey;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(AccessToken))
|
||||
BackendService.AccessToken = AccessToken;
|
||||
|
||||
if(!string.IsNullOrWhiteSpace(TenantId))
|
||||
BackendService.TenantId = TenantId;
|
||||
|
||||
if(!string.IsNullOrWhiteSpace(TenantIdHeaderName))
|
||||
BackendService.TenantIdHeaderName = TenantIdHeaderName;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
@inherits BackendComponentBase
|
||||
@@ -0,0 +1,18 @@
|
||||
@using Elsa.Studio.Contracts
|
||||
@inherits BackendComponentBase
|
||||
@inject IThemeService ThemeService
|
||||
|
||||
<MudThemeProvider IsDarkMode="false" Theme="@ThemeService.CurrentTheme"/>
|
||||
<MudPopoverProvider/>
|
||||
<MudDialogProvider/>
|
||||
<MudSnackbarProvider/>
|
||||
@ChildContent
|
||||
|
||||
@code
|
||||
{
|
||||
/// <summary>
|
||||
/// The component to render.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public RenderFragment ChildContent { get; set; } = default!;
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
@using System.Text.Json.Nodes
|
||||
@using Elsa.Api.Client.Resources.WorkflowDefinitions.Models
|
||||
@inherits BackendComponentBase
|
||||
|
||||
<ThemedComponentWrapper>
|
||||
<WorkflowDefinitionEditor DefinitionId="@DefinitionId"
|
||||
WorkflowDefinitionExecuted="WorkflowDefinitionExecuted"
|
||||
WorkflowDefinitionVersionSelected="WorkflowDefinitionVersionSelected"
|
||||
ActivitySelected="ActivitySelected"/>
|
||||
</ThemedComponentWrapper>
|
||||
|
||||
@code
|
||||
{
|
||||
private bool _shouldRender;
|
||||
private string _definitionId = default!;
|
||||
|
||||
/// The ID of the workflow definition to edit.
|
||||
[Parameter] public string DefinitionId
|
||||
{
|
||||
get => _definitionId;
|
||||
set
|
||||
{
|
||||
if (_definitionId == value) return;
|
||||
_definitionId = value;
|
||||
_shouldRender = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>An event that is invoked when a workflow definition has been executed.</summary>
|
||||
/// <remarks>The ID of the workflow instance is provided as the value to the event callback.</remarks>
|
||||
[Parameter] public Func<string, Task>? WorkflowDefinitionExecuted { get; set; }
|
||||
|
||||
/// Gets or sets the event that occurs when the workflow definition version is updated.
|
||||
[Parameter] public Func<WorkflowDefinition, Task>? WorkflowDefinitionVersionSelected { get; set; }
|
||||
|
||||
/// Gets or sets the event triggered when an activity is selected.
|
||||
[Parameter] public Func<JsonObject, Task>? ActivitySelected { get; set; }
|
||||
|
||||
/// Gets the currently selected activity ID.
|
||||
public string? SelectedActivityId => WorkflowDefinitionEditor.SelectedActivityId;
|
||||
|
||||
private WorkflowDefinitionEditor WorkflowDefinitionEditor { get; set; } = default!;
|
||||
|
||||
/// Gets the currently selected workflow definition version.
|
||||
public WorkflowDefinition? GetSelectedWorkflowDefinitionVersion() => WorkflowDefinitionEditor.GetSelectedWorkflowDefinitionVersion();
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override bool ShouldRender()
|
||||
{
|
||||
if (!_shouldRender) return false;
|
||||
_shouldRender = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
@inherits BackendComponentBase
|
||||
|
||||
<ThemedComponentWrapper>
|
||||
<WorkflowDefinitionList EditWorkflowDefinition="@EditWorkflowDefinition"/>
|
||||
</ThemedComponentWrapper>
|
||||
|
||||
@code
|
||||
{
|
||||
/// <summary>
|
||||
/// An event that is invoked when a workflow definition is edited.
|
||||
/// </summary>
|
||||
[Parameter] public EventCallback<string> EditWorkflowDefinition { get; set; }
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
@inherits BackendComponentBase
|
||||
|
||||
<ThemedComponentWrapper>
|
||||
<WorkflowInstanceList ViewWorkflowInstance="@ViewWorkflowInstance"/>
|
||||
</ThemedComponentWrapper>
|
||||
|
||||
@code{
|
||||
|
||||
/// <summary>
|
||||
/// An event that is invoked when a workflow instance is viewed.
|
||||
/// </summary>
|
||||
[Parameter] public EventCallback<string> ViewWorkflowInstance { get; set; }
|
||||
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
@inherits BackendComponentBase
|
||||
|
||||
<ThemedComponentWrapper>
|
||||
<WorkflowInstanceViewer InstanceId="@InstanceId" EditWorkflowDefinition="EditWorkflowDefinition"/>
|
||||
</ThemedComponentWrapper>
|
||||
|
||||
@code
|
||||
{
|
||||
/// <summary>
|
||||
/// The ID of the workflow definition to edit.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string InstanceId { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// An event that is invoked when a workflow definition is edited.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public EventCallback<string> EditWorkflowDefinition { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
|
||||
|
||||
<PropertyGroup>
|
||||
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
||||
<BlazorWebAssemblyLoadAllGlobalizationData>true</BlazorWebAssemblyLoadAllGlobalizationData>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly"/>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication"/>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Update="appsettings.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<!-- <Content Update="npm\package.json">-->
|
||||
<!-- <CopyToOutputDirectory>Always</CopyToOutputDirectory>-->
|
||||
<!-- <CopyToPublishDirectory>Always</CopyToPublishDirectory>-->
|
||||
<!-- </Content>-->
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\framework\Elsa.Studio.Core.BlazorWasm\Elsa.Studio.Core.BlazorWasm.csproj" />
|
||||
<ProjectReference Include="..\..\framework\Elsa.Studio.Shell\Elsa.Studio.Shell.csproj"/>
|
||||
<ProjectReference Include="..\..\modules\Elsa.Studio.Localization.BlazorWasm\Elsa.Studio.Localization.BlazorWasm.csproj" />
|
||||
<ProjectReference Include="..\..\modules\Elsa.Studio.Login\Elsa.Studio.Login.csproj" />
|
||||
<ProjectReference Include="..\..\modules\Elsa.Studio.Workflows\Elsa.Studio.Workflows.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
using Elsa.Studio.Host.CustomElements.Services;
|
||||
|
||||
namespace Elsa.Studio.Host.CustomElements.HttpMessageHandlers;
|
||||
|
||||
/// <summary>
|
||||
/// An <see cref="HttpMessageHandler"/> that configures the outgoing HTTP request to use the configured API key or bearer token.
|
||||
/// </summary>
|
||||
public class AuthHttpMessageHandler : DelegatingHandler
|
||||
{
|
||||
private readonly BackendService _backendService;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AuthHttpMessageHandler"/> class.
|
||||
/// </summary>
|
||||
public AuthHttpMessageHandler(BackendService backendService)
|
||||
{
|
||||
_backendService = backendService;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
|
||||
{
|
||||
var apiKey = _backendService.ApiKey;
|
||||
var accessToken = _backendService.AccessToken;
|
||||
var tenantId = _backendService.TenantId;
|
||||
var tenantIdHeaderName = _backendService.TenantIdHeaderName;
|
||||
|
||||
if(!string.IsNullOrEmpty(apiKey))
|
||||
request.Headers.Authorization = new("ApiKey", apiKey);
|
||||
else if(!string.IsNullOrEmpty(accessToken))
|
||||
request.Headers.Authorization = new("Bearer", accessToken);
|
||||
|
||||
if(!string.IsNullOrEmpty(tenantId))
|
||||
request.Headers.Add(tenantIdHeaderName, tenantId);
|
||||
|
||||
return await base.SendAsync(request, cancellationToken);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
using Elsa.Studio.Shell.Extensions;
|
||||
using Elsa.Studio.Workflows.Extensions;
|
||||
using Elsa.Studio.Contracts;
|
||||
using Elsa.Studio.Core.BlazorWasm.Extensions;
|
||||
using Elsa.Studio.Extensions;
|
||||
using Elsa.Studio.Host.CustomElements.Components;
|
||||
using Elsa.Studio.Host.CustomElements.HttpMessageHandlers;
|
||||
using Elsa.Studio.Host.CustomElements.Services;
|
||||
using Elsa.Studio.Localization.Time;
|
||||
using Elsa.Studio.Localization.Time.Providers;
|
||||
using Elsa.Studio.Localization.Models;
|
||||
using Elsa.Studio.Localization.BlazorWasm.Extensions;
|
||||
using Elsa.Studio.Models;
|
||||
using Elsa.Studio.Workflows.Designer.Extensions;
|
||||
using Microsoft.AspNetCore.Components.Web;
|
||||
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
|
||||
// Build the host.
|
||||
var builder = WebAssemblyHostBuilder.CreateDefault(args);
|
||||
var configuration = builder.Configuration;
|
||||
|
||||
// Register the custom elements.
|
||||
builder.RootComponents.RegisterCustomElsaStudioElements();
|
||||
builder.RootComponents.RegisterCustomElement<BackendProvider>("elsa-backend-provider");
|
||||
builder.RootComponents.RegisterCustomElement<WorkflowDefinitionEditorWrapper>("elsa-workflow-definition-editor");
|
||||
builder.RootComponents.RegisterCustomElement<WorkflowInstanceViewerWrapper>("elsa-workflow-instance-viewer");
|
||||
builder.RootComponents.RegisterCustomElement<WorkflowInstanceListWrapper>("elsa-workflow-instance-list");
|
||||
builder.RootComponents.RegisterCustomElement<WorkflowDefinitionListWrapper>("elsa-workflow-definition-list");
|
||||
|
||||
// Register local services.
|
||||
builder.Services.AddSingleton<BackendService>();
|
||||
|
||||
// Register the modules.
|
||||
var backendApiConfig = new BackendApiConfig
|
||||
{
|
||||
ConfigureBackendOptions = options => configuration.GetSection("Backend").Bind(options),
|
||||
ConfigureHttpClientBuilder = options =>
|
||||
{
|
||||
options.ApiKey = configuration["Backend:ApiKey"];
|
||||
options.AuthenticationHandler = typeof(AuthHttpMessageHandler);
|
||||
},
|
||||
};
|
||||
|
||||
var localizationConfig = new LocalizationConfig
|
||||
{
|
||||
ConfigureLocalizationOptions = options => configuration.GetSection("Localization").Bind(options),
|
||||
};
|
||||
|
||||
builder.Services.AddCore();
|
||||
builder.Services.AddShell();
|
||||
builder.Services.AddRemoteBackend(backendApiConfig);
|
||||
builder.Services.Replace(ServiceDescriptor.Scoped<IRemoteBackendAccessor, ComponentRemoteBackendAccessor>());
|
||||
builder.Services.AddWorkflowsModule();
|
||||
builder.Services.AddLocalizationModule(localizationConfig);
|
||||
builder.Services.AddScoped<ITimeZoneProvider, LocalTimeZoneProvider>();
|
||||
|
||||
// Build the application.
|
||||
var app = builder.Build();
|
||||
|
||||
await app.UseElsaLocalization();
|
||||
|
||||
// Run each startup task.
|
||||
var startupTask = app.Services.GetServices<IStartupTask>();
|
||||
foreach (var task in startupTask) await task.ExecuteAsync();
|
||||
|
||||
// Run the application.
|
||||
await app.RunAsync();
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:15721",
|
||||
"sslPort": 44319
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"http": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"applicationUrl": "http://localhost:5122",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"https": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"applicationUrl": "https://localhost:7251;http://localhost:5122",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
namespace Elsa.Studio.Host.CustomElements.Services;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a service for backend configuration and information management.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The <see cref="BackendService"/> class provides properties to manage backend connectivity,
|
||||
/// including endpoint configuration, API key management, access token, and tenant identification.
|
||||
/// It acts as a centralized configuration point for backend communication settings.
|
||||
/// </remarks>
|
||||
public class BackendService
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the remote endpoint URL for backend communication.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The <c>RemoteEndpoint</c> property specifies the base URL of the backend service that the application interacts with.
|
||||
/// It is used as a key configuration for defining the remote backend's address and is essential for facilitating communication with the service.
|
||||
/// This property is typically configured during application initialization or dynamically at runtime.
|
||||
/// </remarks>
|
||||
public string RemoteEndpoint { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the API key used for authenticating requests to the backend service.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The <c>ApiKey</c> property is used to supply authentication credentials in the form of an API key
|
||||
/// when communicating with the backend service. It is typically included in the request headers to identify
|
||||
/// and authorize the client. This property should hold a secure, non-empty value if API key-based authentication
|
||||
/// is enabled for the backend. Configuring this property correctly is critical for ensuring authorized access
|
||||
/// to backend resources.
|
||||
/// </remarks>
|
||||
public string? ApiKey { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the access token used for authentication in backend communication.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The <c>AccessToken</c> property specifies a bearer token used for authorizing requests to protected backend resources.
|
||||
/// This property is typically set during initialization or dynamically updated to ensure proper authorization headers are sent with HTTP requests.
|
||||
/// It is utilized when API key-based authentication is not provided, ensuring secure access through bearer token mechanisms.
|
||||
/// </remarks>
|
||||
public string? AccessToken { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the tenant identifier for backend communication.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The <c>TenantId</c> property specifies the unique identifier associated with the tenant context in the backend service.
|
||||
/// It is used to distinguish resources and operations specific to a particular tenant, enabling multi-tenancy support.
|
||||
/// This property can be set during initialization or dynamically altered at runtime to switch between tenants.
|
||||
/// Setting this property is not necessary if the <see cref="AccessToken"/> carries a claim that can be used on the back-end to determine the current tenant.
|
||||
/// </remarks>
|
||||
public string? TenantId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the HTTP header used for tenant identification during backend communication.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The <c>TenantIdHeaderName</c> property defines the header key that carries the tenant identifier in HTTP requests.
|
||||
/// It is essential for multi-tenant applications to distinguish between different tenants while interacting with the backend service.
|
||||
/// This property can be customized to align with specific header naming conventions required by the backend.
|
||||
/// </remarks>
|
||||
public string TenantIdHeaderName { get; set; } = "X-Tenant-Id";
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using Elsa.Studio.Contracts;
|
||||
using Elsa.Studio.Models;
|
||||
using Elsa.Studio.Options;
|
||||
using Elsa.Studio.Services;
|
||||
|
||||
namespace Elsa.Studio.Host.CustomElements.Services;
|
||||
|
||||
/// <summary>
|
||||
/// A default implementation of <see cref="IRemoteBackendAccessor"/> that uses the <see cref="BackendOptions"/> to determine the URL of the remote backend.
|
||||
/// </summary>
|
||||
public class ComponentRemoteBackendAccessor : IRemoteBackendAccessor
|
||||
{
|
||||
private readonly BackendService _backendService;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DefaultRemoteBackendAccessor"/> class.
|
||||
/// </summary>
|
||||
public ComponentRemoteBackendAccessor(BackendService backendService)
|
||||
{
|
||||
_backendService = backendService;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public RemoteBackend RemoteBackend => new(new(_backendService.RemoteEndpoint));
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@using Microsoft.JSInterop
|
||||
@using MudBlazor
|
||||
@using Elsa.Studio.Components
|
||||
@using Elsa.Studio.Shell
|
||||
@using Elsa.Studio.Workflows.Components.WorkflowDefinitionEditor
|
||||
@using Elsa.Studio.Workflows.Components.WorkflowInstanceViewer
|
||||
@using Elsa.Studio.Workflows.Components.WorkflowDefinitionList
|
||||
@using Elsa.Studio.Workflows.Components.WorkflowInstanceList
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
"Shell": {
|
||||
"DisableAuthorization": false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"name": "@elsa-workflows/elsa-studio-wasm",
|
||||
"version": "3.0.0-preview.1",
|
||||
"description": "Provides Elsa Studio Blazor components wrapped as custom elements.",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [
|
||||
"elsa workflows",
|
||||
"blazor"
|
||||
],
|
||||
"author": "Sipke Schoorstra",
|
||||
"license": "MIT",
|
||||
"files": [
|
||||
"_framework/*",
|
||||
"_content/*",
|
||||
"index.html",
|
||||
"appsettings.json",
|
||||
"Elsa.Studio.Host.CustomElements.styles.css"
|
||||
]
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"Backend": {
|
||||
"Url": "https://localhost:5001/elsa/api"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
|
||||
<title>MyApplication</title>
|
||||
<base href="/"/>
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="_content/Elsa.Studio.Shell/apple-touch-icon.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="_content/Elsa.Studio.Shell/favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="_content/Elsa.Studio.Shell/favicon-16x16.png">
|
||||
<link rel="manifest" href="_content/Elsa.Studio.Shell/site.webmanifest">
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" rel="stylesheet" />
|
||||
<link href="https://fonts.googleapis.com/css2?family=Ubuntu:wght@300;400;500;700&display=swap" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;600;700&display=swap" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Grandstander:wght@100&display=swap" rel="stylesheet">
|
||||
<link href="_content/MudBlazor/MudBlazor.min.css" rel="stylesheet" />
|
||||
<link href="_content/CodeBeam.MudBlazor.Extensions/MudExtensions.min.css" rel="stylesheet" />
|
||||
<link href="_content/Radzen.Blazor/css/material-base.css" rel="stylesheet" >
|
||||
<link href="_content/Elsa.Studio.Shell/css/shell.css" rel="stylesheet">
|
||||
<link href="Elsa.Studio.Host.CustomElements.styles.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<elsa-studio-workflow-definition-editor definition-id="c6deed7e9c4847e8af0647109781e1f3"></elsa-studio-workflow-definition-editor>
|
||||
|
||||
<div id="blazor-error-ui">
|
||||
An unhandled error has occurred.
|
||||
<a href="" class="reload">Reload</a>
|
||||
<a class="dismiss">🗙</a>
|
||||
</div>
|
||||
<script src="_content/BlazorMonaco/jsInterop.js"></script>
|
||||
<script src="_content/BlazorMonaco/lib/monaco-editor/min/vs/loader.js"></script>
|
||||
<script src="_content/BlazorMonaco/lib/monaco-editor/min/vs/editor/editor.main.js"></script>
|
||||
<script src="_content/MudBlazor/MudBlazor.min.js"></script>
|
||||
<script src="_content/CodeBeam.MudBlazor.Extensions/MudExtensions.min.js"></script>
|
||||
<script src="_content/Radzen.Blazor/Radzen.Blazor.js"></script>
|
||||
<script src="_framework/blazor.webassembly.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,11 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Elsa.Studio.Host.Wasm\Elsa.Studio.Host.Wasm.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,63 @@
|
||||
namespace Elsa.Studio.Host.HostedWasm.Middleware;
|
||||
|
||||
/// <summary>
|
||||
/// Middleware that intercepts HTTP requests and rewrites specific asset-related paths
|
||||
/// for Web Assembly applications to ensure proper routing and handling of static files.
|
||||
/// </summary>
|
||||
public class WasmAssetsRewritingMiddleware(RequestDelegate next, ILogger<WasmAssetsRewritingMiddleware> logger)
|
||||
{
|
||||
private static readonly string[] TargetSegments = { "_content", "_framework" };
|
||||
|
||||
public async Task InvokeAsync(HttpContext context)
|
||||
{
|
||||
if (context.Request.Path.HasValue && NeedsRewriting(context.Request.Path.Value!))
|
||||
{
|
||||
var path = context.Request.Path.Value!;
|
||||
|
||||
// Call the private method to get the index of the target segment using spans
|
||||
var segmentIndex = GetTargetSegmentIndex(path.AsSpan());
|
||||
|
||||
if (segmentIndex > 0)
|
||||
{
|
||||
// Use slices instead of Substring to avoid allocations
|
||||
var newPath = path.AsSpan(segmentIndex).ToString(); // Convert back to a string only when required
|
||||
context.Request.Path = newPath.StartsWith('/') ? newPath : $"/{newPath}";
|
||||
|
||||
if (logger.IsEnabled(LogLevel.Debug)) logger.LogDebug("Rewritten: {Path} -> {NewPath}", path, context.Request.Path.Value);
|
||||
}
|
||||
}
|
||||
|
||||
// Call the next middleware in the pipeline
|
||||
await next(context);
|
||||
}
|
||||
|
||||
private static bool NeedsRewriting(string path)
|
||||
{
|
||||
// Fast path: Return if the path does not include potential target segments
|
||||
foreach (var segment in TargetSegments)
|
||||
{
|
||||
if (path.Contains(segment, StringComparison.OrdinalIgnoreCase))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static int GetTargetSegmentIndex(ReadOnlySpan<char> path)
|
||||
{
|
||||
foreach (var segment in TargetSegments)
|
||||
{
|
||||
// Use Span instead of string concatenation and index search
|
||||
var segmentAsSpan = $"{segment}/".AsSpan();
|
||||
var index = path.IndexOf(segmentAsSpan, StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
if (index >= 0)
|
||||
{
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
return -1; // No valid index found
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
@page "/"
|
||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
@inject IConfiguration Configuration;
|
||||
@{
|
||||
var apiUrl = Configuration["Hosting:ApiUrl"];
|
||||
|
||||
// Get the first segment of the request path, which represents the tenant ID.
|
||||
var segments = Request.Path.Value!.Split('/', StringSplitOptions.RemoveEmptyEntries);
|
||||
var tenantId = segments.Length is 1 or > 2 ? segments[0] : null;
|
||||
var baseRef = tenantId != null ? $"/{tenantId}/" : "/";
|
||||
}
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
|
||||
<title>Elsa Studio 3</title>
|
||||
<base href="@baseRef"/>
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="_content/Elsa.Studio.Shell/apple-touch-icon.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="_content/Elsa.Studio.Shell/favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="_content/Elsa.Studio.Shell/favicon-16x16.png">
|
||||
<link rel="manifest" href="_content/Elsa.Studio.Shell/site.webmanifest">
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" rel="stylesheet"/>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Ubuntu:wght@300;400;500;700&display=swap" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;600;700&display=swap" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Grandstander:wght@100&display=swap" rel="stylesheet">
|
||||
<link href="_content/MudBlazor/MudBlazor.min.css" rel="stylesheet"/>
|
||||
<link href="_content/CodeBeam.MudBlazor.Extensions/MudExtensions.min.css" rel="stylesheet"/>
|
||||
<link href="_content/Radzen.Blazor/css/material-base.css" rel="stylesheet">
|
||||
<link href="_content/Elsa.Studio.Shell/css/shell.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app">
|
||||
<div class="loading-splash mud-container mud-container-maxwidth-false">
|
||||
<h5 class="mud-typography mud-typography-h5 mud-primary-text my-6">Loading...</h5>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="blazor-error-ui">
|
||||
An unhandled error has occurred.
|
||||
<a href="" class="reload">Reload</a>
|
||||
<a class="dismiss">🗙</a>
|
||||
</div>
|
||||
<script src="_content/BlazorMonaco/jsInterop.js"></script>
|
||||
<script src="_content/BlazorMonaco/lib/monaco-editor/min/vs/loader.js"></script>
|
||||
<script src="_content/BlazorMonaco/lib/monaco-editor/min/vs/editor/editor.main.js"></script>
|
||||
<script src="_content/MudBlazor/MudBlazor.min.js"></script>
|
||||
<script src="_content/CodeBeam.MudBlazor.Extensions/MudExtensions.min.js"></script>
|
||||
<script src="_content/Radzen.Blazor/Radzen.Blazor.js"></script>
|
||||
<script>
|
||||
window.getClientConfig = function() { return {
|
||||
"apiUrl": "@apiUrl"
|
||||
} };
|
||||
</script>
|
||||
<script src="_framework/blazor.webassembly.js" autostart="false"></script>
|
||||
|
||||
<script type="application/javascript">
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
Blazor.start({
|
||||
loadBootResource: function (type, name, defaultUri, integrity) {
|
||||
if (defaultUri.startsWith('http'))
|
||||
return defaultUri;
|
||||
|
||||
if (!defaultUri.startsWith('/'))
|
||||
return `/${defaultUri}`;
|
||||
|
||||
return defaultUri;
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,43 @@
|
||||
using Elsa.Studio.Host.HostedWasm.Middleware;
|
||||
using Microsoft.AspNetCore.StaticFiles;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
builder.WebHost.UseStaticWebAssets();
|
||||
|
||||
// Add services to the container.
|
||||
builder.Services.AddRazorPages();
|
||||
builder.Services.AddCors(cors => cors.AddDefaultPolicy(policy => policy.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod()));
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
// Configure the HTTP request pipeline.
|
||||
if (!app.Environment.IsDevelopment())
|
||||
{
|
||||
app.UseExceptionHandler("/Error", createScopeForErrors: true);
|
||||
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
|
||||
app.UseHsts();
|
||||
}
|
||||
|
||||
app.UseHttpsRedirection();
|
||||
app.UseBlazorFrameworkFiles();
|
||||
app.UseRouting();
|
||||
app.UseCors();
|
||||
|
||||
// Insert this BEFORE UseStaticFiles middleware.
|
||||
app.UseMiddleware<WasmAssetsRewritingMiddleware>();
|
||||
|
||||
// Use Static Files instead of MapStaticAssets.
|
||||
app.UseStaticFiles(new StaticFileOptions
|
||||
{
|
||||
ContentTypeProvider = new FileExtensionContentTypeProvider
|
||||
{
|
||||
Mappings =
|
||||
{
|
||||
// Add custom MIME type mappings for WASM
|
||||
[".dat"] = "application/octet-stream"
|
||||
}
|
||||
}
|
||||
});
|
||||
app.MapFallbackToPage("/_Host");
|
||||
|
||||
app.Run();
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/launchsettings.json",
|
||||
"profiles": {
|
||||
"https": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": false,
|
||||
"applicationUrl": "https://localhost:7267",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
"Hosting": {
|
||||
"ApiUrl": "https://localhost:5001/elsa/api"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base
|
||||
WORKDIR /app
|
||||
EXPOSE 80
|
||||
EXPOSE 443
|
||||
|
||||
FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
|
||||
WORKDIR /src
|
||||
COPY ["Elsa.Studio.ServerApp/Elsa.Studio.ServerApp.csproj", "Elsa.Studio.ServerApp/"]
|
||||
RUN dotnet restore "Elsa.Studio.ServerApp/Elsa.Studio.ServerApp.csproj"
|
||||
COPY . .
|
||||
WORKDIR "/src/Elsa.Studio.ServerApp"
|
||||
RUN dotnet build "Elsa.Studio.ServerApp.csproj" -c Release -o /app/build
|
||||
|
||||
FROM build AS publish
|
||||
RUN dotnet publish "Elsa.Studio.ServerApp.csproj" -c Release -o /app/publish
|
||||
|
||||
FROM base AS final
|
||||
WORKDIR /app
|
||||
COPY --from=publish /app/publish .
|
||||
ENTRYPOINT ["dotnet", "Elsa.Studio.ServerApp.dll"]
|
||||
@@ -0,0 +1,27 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="..\.dockerignore">
|
||||
<Link>.dockerignore</Link>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\bundles\Elsa.Studio\Elsa.Studio.csproj" />
|
||||
<ProjectReference Include="..\..\framework\Elsa.Studio.Core.BlazorServer\Elsa.Studio.Core.BlazorServer.csproj" />
|
||||
<ProjectReference Include="..\..\framework\Elsa.Studio.Translations\Elsa.Studio.Translations.csproj" />
|
||||
<ProjectReference Include="..\..\modules\Elsa.Studio.Dashboard\Elsa.Studio.Dashboard.csproj" />
|
||||
<ProjectReference Include="..\..\modules\Elsa.Studio.Localization.BlazorServer\Elsa.Studio.Localization.BlazorServer.csproj" />
|
||||
<ProjectReference Include="..\..\modules\Elsa.Studio.Login.BlazorServer\Elsa.Studio.Login.BlazorServer.csproj" />
|
||||
<ProjectReference Include="..\..\modules\Elsa.Studio.Login\Elsa.Studio.Login.csproj" />
|
||||
<ProjectReference Include="..\..\modules\Elsa.Studio.Secrets\Elsa.Studio.Secrets.csproj" />
|
||||
<ProjectReference Include="..\..\modules\Elsa.Studio.Webhooks\Elsa.Studio.Webhooks.csproj" />
|
||||
<ProjectReference Include="..\..\modules\Elsa.Studio.WorkflowContexts\Elsa.Studio.WorkflowContexts.csproj" />
|
||||
<ProjectReference Include="..\..\modules\Elsa.Studio.Workflows\Elsa.Studio.Workflows.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,56 @@
|
||||
@page "/"
|
||||
@using Elsa.Studio.Shell
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@namespace Elsa.Studio.Host.Server.Pages
|
||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<base href="~/"/>
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="_content/Elsa.Studio.Shell/apple-touch-icon.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="_content/Elsa.Studio.Shell/favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="_content/Elsa.Studio.Shell/favicon-16x16.png">
|
||||
<link rel="manifest" href="_content/Elsa.Studio.Shell/site.webmanifest">
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" rel="stylesheet"/>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Ubuntu:wght@300;400;500;700&display=swap" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;600;700&display=swap" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Grandstander:wght@100&display=swap" rel="stylesheet">
|
||||
<link href="_content/MudBlazor/MudBlazor.min.css" rel="stylesheet"/>
|
||||
<link href="_content/CodeBeam.MudBlazor.Extensions/MudExtensions.min.css" rel="stylesheet"/>
|
||||
<link href="_content/Radzen.Blazor/css/material-base.css" rel="stylesheet">
|
||||
<link href="_content/Elsa.Studio.Shell/css/shell.css" rel="stylesheet">
|
||||
<link href="_content/Elsa.Studio.Workflows.Designer/designer.css" rel="stylesheet">
|
||||
|
||||
@* Use designer.v1.css for the old designer (and comment out the previous designer.css style reference).*@
|
||||
@* <link href="_content/Elsa.Studio.Workflows.Designer/designer.css" rel="stylesheet"> *@
|
||||
|
||||
<link href="Elsa.Studio.Host.Server.styles.css" rel="stylesheet">
|
||||
<component type="typeof(HeadOutlet)" render-mode="ServerPrerendered"/>
|
||||
</head>
|
||||
<body>
|
||||
<component type="typeof(App)" render-mode="ServerPrerendered" />
|
||||
|
||||
<div id="blazor-error-ui">
|
||||
<environment include="Staging,Production">
|
||||
An error has occurred. This application may no longer respond until reloaded.
|
||||
</environment>
|
||||
<environment include="Development">
|
||||
An unhandled exception has occurred. See browser dev tools for details.
|
||||
</environment>
|
||||
<a href="" class="reload">Reload</a>
|
||||
<a class="dismiss">🗙</a>
|
||||
</div>
|
||||
<script src="_content/BlazorMonaco/jsInterop.js"></script>
|
||||
<script src="_content/BlazorMonaco/lib/monaco-editor/min/vs/loader.js"></script>
|
||||
<script src="_content/BlazorMonaco/lib/monaco-editor/min/vs/editor/editor.main.js"></script>
|
||||
<script src="_content/MudBlazor/MudBlazor.min.js"></script>
|
||||
<script src="_content/CodeBeam.MudBlazor.Extensions/MudExtensions.min.js"></script>
|
||||
<script src="_content/Radzen.Blazor/Radzen.Blazor.js"></script>
|
||||
<script src="_framework/blazor.server.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,122 @@
|
||||
using Elsa.Studio.Core.BlazorServer.Extensions;
|
||||
using Elsa.Studio.Dashboard.Extensions;
|
||||
using Elsa.Studio.Extensions;
|
||||
using Elsa.Studio.Localization.Time;
|
||||
using Elsa.Studio.Localization.Time.Providers;
|
||||
using Elsa.Studio.Login.BlazorServer.Extensions;
|
||||
using Elsa.Studio.Login.HttpMessageHandlers;
|
||||
using Elsa.Studio.Models;
|
||||
using Elsa.Studio.Secrets;
|
||||
using Elsa.Studio.Shell.Extensions;
|
||||
using Elsa.Studio.Webhooks.Extensions;
|
||||
using Elsa.Studio.Workflows.Extensions;
|
||||
using Elsa.Studio.Workflows.Designer.Extensions;
|
||||
using Elsa.Studio.Localization.BlazorServer.Extensions;
|
||||
using Elsa.Studio.Localization.Models;
|
||||
using Elsa.Studio.Localization.Options;
|
||||
using Elsa.Studio.Translations;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using Elsa.Studio.Branding;
|
||||
using Elsa.Studio.Host.Server;
|
||||
using Elsa.Studio.Login.Extensions;
|
||||
|
||||
// Build the host.
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
var configuration = builder.Configuration;
|
||||
|
||||
// Register Razor services.
|
||||
builder.Services.AddRazorPages();
|
||||
builder.Services.AddServerSideBlazor(options =>
|
||||
{
|
||||
// Register the root components.
|
||||
// V2 activity wrapper by default.
|
||||
options.RootComponents.RegisterCustomElsaStudioElements();
|
||||
|
||||
// To use V1 activity wrapper layout, specify the V1 component instead:
|
||||
//options.RootComponents.RegisterCustomElsaStudioElements(typeof(Elsa.Studio.Workflows.Designer.Components.ActivityWrappers.V1.EmbeddedActivityWrapper));
|
||||
|
||||
options.RootComponents.MaxJSRootComponents = 1000;
|
||||
});
|
||||
|
||||
// Register shell services and modules.
|
||||
var backendApiConfig = new BackendApiConfig
|
||||
{
|
||||
ConfigureBackendOptions = options => configuration.GetSection("Backend").Bind(options),
|
||||
ConfigureHttpClientBuilder = options =>
|
||||
{
|
||||
options.AuthenticationHandler = typeof(AuthenticatingApiHttpMessageHandler);
|
||||
options.ConfigureHttpClient = (_, client) =>
|
||||
{
|
||||
// Set a long time out to simplify debugging both Elsa Studio and the Elsa Server backend.
|
||||
client.Timeout = TimeSpan.FromHours(1);
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
var localizationConfig = new LocalizationConfig
|
||||
{
|
||||
ConfigureLocalizationOptions = options =>
|
||||
{
|
||||
configuration.GetSection(LocalizationOptions.LocalizationSection).Bind(options);
|
||||
options.SupportedCultures = new[] { options?.DefaultCulture ?? new LocalizationOptions().DefaultCulture }
|
||||
.Concat(options?.SupportedCultures.Where(culture => culture != options?.DefaultCulture) ?? []) .ToArray();
|
||||
}
|
||||
};
|
||||
|
||||
builder.Services.AddScoped<IBrandingProvider, StudioBrandingProvider>();
|
||||
builder.Services.AddCore().Replace(new(typeof(IBrandingProvider), typeof(StudioBrandingProvider), ServiceLifetime.Scoped));
|
||||
builder.Services.AddShell(options => configuration.GetSection("Shell").Bind(options));
|
||||
builder.Services.AddRemoteBackend(backendApiConfig);
|
||||
builder.Services.AddLoginModule();
|
||||
builder.Services.UseElsaIdentity();
|
||||
// builder.Services.UseOAuth2(options =>
|
||||
// {
|
||||
// options.ClientId = "ElsaStudio";
|
||||
// options.TokenEndpoint = "https://localhost:44366/connect/token";
|
||||
// options.Scope = "YourSite offline_access";
|
||||
// });
|
||||
builder.Services.AddDashboardModule();
|
||||
builder.Services.AddWorkflowsModule();
|
||||
builder.Services.AddWebhooksModule();
|
||||
builder.Services.AddSecretsModule(backendApiConfig);
|
||||
builder.Services.AddLocalizationModule(localizationConfig);
|
||||
builder.Services.AddTranslations();
|
||||
|
||||
// Replace some services with other implementations.
|
||||
builder.Services.AddScoped<ITimeZoneProvider, LocalTimeZoneProvider>();
|
||||
|
||||
// Uncomment for V1 designer theme (default is V2).
|
||||
// builder.Services.Configure<DesignerOptions>(options =>
|
||||
// {
|
||||
// options.DesignerCssClass = "elsa-flowchart-diagram-designer-v1";
|
||||
// options.GraphSettings.Grid.Type = "mesh";
|
||||
// });
|
||||
|
||||
// Configure SignalR.
|
||||
builder.Services.AddSignalR(options =>
|
||||
{
|
||||
// Set MaximumReceiveMessageSize:
|
||||
options.MaximumReceiveMessageSize = 5 * 1024 * 1000; // 5MB
|
||||
});
|
||||
|
||||
// Build the application.
|
||||
var app = builder.Build();
|
||||
|
||||
// Configure the HTTP request pipeline.
|
||||
if (!app.Environment.IsDevelopment())
|
||||
{
|
||||
app.UseResponseCompression();
|
||||
|
||||
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
|
||||
app.UseHsts();
|
||||
}
|
||||
|
||||
app.UseElsaLocalization();
|
||||
app.UseHttpsRedirection();
|
||||
app.UseStaticFiles();
|
||||
app.UseRouting();
|
||||
app.UseAuthorization();
|
||||
app.MapControllers();
|
||||
app.MapBlazorHub();
|
||||
app.MapFallbackToPage("/_Host");
|
||||
app.Run();
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"iisSettings": {
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:50413",
|
||||
"sslPort": 44382
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"http": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"applicationUrl": "http://localhost:5010",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"https": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"applicationUrl": "https://localhost:7113;http://localhost:5010",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using Elsa.Studio.Branding;
|
||||
|
||||
namespace Elsa.Studio.Host.Server
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public class StudioBrandingProvider : DefaultBrandingProvider
|
||||
{
|
||||
public override string AppName => "Elsa Studio 3.5";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
@using Microsoft.AspNetCore.Authorization
|
||||
@using Microsoft.AspNetCore.Components.Routing
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
@using Microsoft.JSInterop
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"DetailedErrors": true,
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
"Shell": {
|
||||
"DisableAuthorization": false
|
||||
},
|
||||
"Backend": {
|
||||
"Url": "https://localhost:5001/elsa/api"
|
||||
},
|
||||
"Localization": {
|
||||
"DefaultCulture": "fa-IR",
|
||||
"SupportedCultures": [
|
||||
"fa-IR",
|
||||
"en-US"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base
|
||||
WORKDIR /app
|
||||
EXPOSE 80
|
||||
EXPOSE 443
|
||||
|
||||
FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
|
||||
WORKDIR /src
|
||||
COPY ["src/Elsa.Studio.WebAssemblyApp/Elsa.Studio.WebAssemblyApp.csproj", "src/Elsa.Studio.WebAssemblyApp/"]
|
||||
RUN dotnet restore "src/Elsa.Studio.WebAssemblyApp/Elsa.Studio.WebAssemblyApp.csproj"
|
||||
COPY . .
|
||||
WORKDIR "/src/src/Elsa.Studio.WebAssemblyApp"
|
||||
RUN dotnet build "Elsa.Studio.WebAssemblyApp.csproj" -c Release -o /app/build
|
||||
|
||||
FROM build AS publish
|
||||
RUN dotnet publish "Elsa.Studio.WebAssemblyApp.csproj" -c Release -o /app/publish
|
||||
|
||||
FROM base AS final
|
||||
WORKDIR /app
|
||||
COPY --from=publish /app/publish .
|
||||
ENTRYPOINT ["dotnet", "Elsa.Studio.WebAssemblyApp.dll"]
|
||||
@@ -0,0 +1,30 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
|
||||
|
||||
<PropertyGroup>
|
||||
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
||||
<BlazorWebAssemblyLoadAllGlobalizationData>true</BlazorWebAssemblyLoadAllGlobalizationData>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Update="wwwroot\appsettings.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\bundles\Elsa.Studio\Elsa.Studio.csproj" />
|
||||
<ProjectReference Include="..\..\framework\Elsa.Studio.Core.BlazorWasm\Elsa.Studio.Core.BlazorWasm.csproj" />
|
||||
<ProjectReference Include="..\..\framework\Elsa.Studio.DomInterop\Elsa.Studio.DomInterop.csproj" />
|
||||
<ProjectReference Include="..\..\modules\Elsa.Studio.Dashboard\Elsa.Studio.Dashboard.csproj" />
|
||||
<ProjectReference Include="..\..\modules\Elsa.Studio.Localization.BlazorWasm\Elsa.Studio.Localization.BlazorWasm.csproj" />
|
||||
<ProjectReference Include="..\..\modules\Elsa.Studio.Login.BlazorWasm\Elsa.Studio.Login.BlazorWasm.csproj" />
|
||||
<ProjectReference Include="..\..\modules\Elsa.Studio.WorkflowContexts\Elsa.Studio.WorkflowContexts.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,63 @@
|
||||
using Elsa.Studio.Dashboard.Extensions;
|
||||
using Elsa.Studio.Shell;
|
||||
using Elsa.Studio.Shell.Extensions;
|
||||
using Elsa.Studio.Workflows.Extensions;
|
||||
using Elsa.Studio.Contracts;
|
||||
using Elsa.Studio.Core.BlazorWasm.Extensions;
|
||||
using Elsa.Studio.Extensions;
|
||||
using Elsa.Studio.Localization.Time;
|
||||
using Elsa.Studio.Localization.Time.Providers;
|
||||
using Elsa.Studio.Login.BlazorWasm.Extensions;
|
||||
using Elsa.Studio.Login.HttpMessageHandlers;
|
||||
using Elsa.Studio.Models;
|
||||
using Elsa.Studio.WorkflowContexts.Extensions;
|
||||
using Elsa.Studio.Workflows.Designer.Extensions;
|
||||
using Microsoft.AspNetCore.Components.Web;
|
||||
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
|
||||
using Elsa.Studio.Localization.Models;
|
||||
using Elsa.Studio.Localization.BlazorWasm.Extensions;
|
||||
|
||||
// Build the host.
|
||||
var builder = WebAssemblyHostBuilder.CreateDefault(args);
|
||||
var configuration = builder.Configuration;
|
||||
|
||||
// Register root components.
|
||||
builder.RootComponents.Add<App>("#app");
|
||||
builder.RootComponents.Add<HeadOutlet>("head::after");
|
||||
builder.RootComponents.RegisterCustomElsaStudioElements();
|
||||
|
||||
// Register shell services and modules.
|
||||
var backendApiConfig = new BackendApiConfig
|
||||
{
|
||||
ConfigureBackendOptions = options => configuration.GetSection("Backend").Bind(options),
|
||||
ConfigureHttpClientBuilder = options => options.AuthenticationHandler = typeof(AuthenticatingApiHttpMessageHandler),
|
||||
};
|
||||
|
||||
var localizationConfig = new LocalizationConfig
|
||||
{
|
||||
ConfigureLocalizationOptions = options => configuration.GetSection("Localization").Bind(options),
|
||||
};
|
||||
|
||||
builder.Services.AddCore();
|
||||
builder.Services.AddShell();
|
||||
builder.Services.AddRemoteBackend(backendApiConfig);
|
||||
builder.Services.AddLoginModule();
|
||||
builder.Services.AddDashboardModule();
|
||||
builder.Services.AddWorkflowsModule();
|
||||
builder.Services.AddWorkflowContextsModule();
|
||||
builder.Services.AddLocalizationModule(localizationConfig);
|
||||
|
||||
// Replace some services with other implementations.
|
||||
builder.Services.AddScoped<ITimeZoneProvider, LocalTimeZoneProvider>();
|
||||
|
||||
// Build the application.
|
||||
var app = builder.Build();
|
||||
|
||||
await app.UseElsaLocalization();
|
||||
|
||||
// Run each startup task.
|
||||
var startupTaskRunner = app.Services.GetRequiredService<IStartupTaskRunner>();
|
||||
await startupTaskRunner.RunStartupTasksAsync();
|
||||
|
||||
// Run the application.
|
||||
await app.RunAsync();
|
||||
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"iisSettings": {
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:10111",
|
||||
"sslPort": 44341
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"http": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
|
||||
"applicationUrl": "http://localhost:5275",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"https": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
|
||||
"applicationUrl": "https://localhost:7052;http://localhost:5275",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
@using System.Net.Http
|
||||
@using System.Net.Http.Json
|
||||
@using Microsoft.AspNetCore.Components.Routing
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@using Microsoft.AspNetCore.Components.WebAssembly.Http
|
||||
@using Microsoft.JSInterop
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"Backend": {
|
||||
"Url": "https://localhost:5001/elsa/api"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
|
||||
<title>Elsa Studio 3.5</title>
|
||||
<base href="/"/>
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="_content/Elsa.Studio.Shell/apple-touch-icon.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="_content/Elsa.Studio.Shell/favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="_content/Elsa.Studio.Shell/favicon-16x16.png">
|
||||
<link rel="manifest" href="_content/Elsa.Studio.Shell/site.webmanifest">
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" rel="stylesheet" />
|
||||
<link href="https://fonts.googleapis.com/css2?family=Ubuntu:wght@300;400;500;700&display=swap" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;600;700&display=swap" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Grandstander:wght@100&display=swap" rel="stylesheet">
|
||||
<link href="_content/MudBlazor/MudBlazor.min.css" rel="stylesheet" />
|
||||
<link href="_content/CodeBeam.MudBlazor.Extensions/MudExtensions.min.css" rel="stylesheet" />
|
||||
<link href="_content/Radzen.Blazor/css/material-base.css" rel="stylesheet" >
|
||||
<link href="_content/Elsa.Studio.Shell/css/shell.css" rel="stylesheet">
|
||||
<link href="Elsa.Studio.Host.Wasm.styles.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app">
|
||||
<div class="loading-splash mud-container mud-container-maxwidth-false">
|
||||
<h5 class="mud-typography mud-typography-h5 mud-primary-text my-6">Loading...</h5>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="blazor-error-ui">
|
||||
An unhandled error has occurred.
|
||||
<a href="" class="reload">Reload</a>
|
||||
<a class="dismiss">🗙</a>
|
||||
</div>
|
||||
<script src="_content/BlazorMonaco/jsInterop.js"></script>
|
||||
<script src="_content/BlazorMonaco/lib/monaco-editor/min/vs/loader.js"></script>
|
||||
<script src="_content/BlazorMonaco/lib/monaco-editor/min/vs/editor/editor.main.js"></script>
|
||||
<script src="_content/MudBlazor/MudBlazor.min.js"></script>
|
||||
<script src="_content/CodeBeam.MudBlazor.Extensions/MudExtensions.min.js"></script>
|
||||
<script src="_content/Radzen.Blazor/Radzen.Blazor.js"></script>
|
||||
<script src="_framework/blazor.webassembly.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Reference in New Issue
Block a user