diff --git a/.dokku/Procfile b/.dokku/Procfile new file mode 100644 index 0000000..c2bcaf5 --- /dev/null +++ b/.dokku/Procfile @@ -0,0 +1,2 @@ +web: run-web.sh +silo: run-silo.sh \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..0e33bc8 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,47 @@ +FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS base +USER $APP_UID +WORKDIR /app +EXPOSE 8080 + +FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build +ARG BUILD_CONFIGURATION=Release + +WORKDIR /src +COPY ["Pushy.Domain/Pushy.Domain.csproj", "Pushy.Domain/"] + +COPY ["Pushy/Pushy/Pushy.csproj", "Pushy/Pushy/"] +COPY ["Pushy/Pushy.Client/Pushy.Client.csproj", "Pushy/Pushy.Client/"] + +COPY ["Pushy.Silo/Pushy.Silo.csproj", "Pushy.Silo/"] +COPY . . + +RUN dotnet restore "Pushy.Silo/Pushy.Silo.csproj" +RUN dotnet restore "Pushy/Pushy/Pushy.csproj" + +WORKDIR "/src/Pushy.Silo" +RUN dotnet build "Pushy.Silo.csproj" --no-restore -c $BUILD_CONFIGURATION -o /app/silo + +WORKDIR "/src/Pushy/Pushy" +RUN dotnet build "Pushy.csproj" --no-restore -c $BUILD_CONFIGURATION -o /app/pushy + +COPY .dokku/Procfile /app/.dokku/Procfile +COPY run-silo.sh /app/run-silo.sh +COPY run-web.sh /app/run-web.sh + +FROM build AS publish +ARG BUILD_CONFIGURATION=Release + +WORKDIR "/src/Pushy.Silo" +RUN dotnet publish "Pushy.Silo.csproj" -c $BUILD_CONFIGURATION -o /app/publish/silo /p:UseAppHost=false + +WORKDIR "/src/Pushy/Pushy" +RUN dotnet publish "Pushy.csproj" -c $BUILD_CONFIGURATION -o /app/publish/pushy /p:UseAppHost=false + + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +COPY --from=publish /app/.dokku /app/.dokku +COPY --from=publish /app/*.sh /app/ + +ENTRYPOINT ["sh"] \ No newline at end of file diff --git a/GitVersion.yml b/GitVersion.yml new file mode 100644 index 0000000..570a504 --- /dev/null +++ b/GitVersion.yml @@ -0,0 +1,7 @@ +branches: + main: + regex: ^master$|^main$ + mode: ContinuousDelivery + develop: + regex: ^develop$ + mode: ContinuousDelivery \ No newline at end of file diff --git a/Pushy.Domain/ILinkGenerator.cs b/Pushy.Domain/ILinkGenerator.cs new file mode 100644 index 0000000..892b86e --- /dev/null +++ b/Pushy.Domain/ILinkGenerator.cs @@ -0,0 +1,7 @@ +namespace Pushy.Domain; + +public interface ILinkGenerator : IGrainWithGuidKey +{ + [Alias("GenerateLink")] + public ValueTask GenerateTextShare([Immutable] string text); +} \ No newline at end of file diff --git a/Pushy.Domain/ITextItem.cs b/Pushy.Domain/ITextItem.cs new file mode 100644 index 0000000..37dfc3c --- /dev/null +++ b/Pushy.Domain/ITextItem.cs @@ -0,0 +1,14 @@ +using Orleans.Concurrency; + +namespace Pushy.Domain; + +public interface ITextItem : IGrainWithStringKey +{ + [Alias("SetText")] + public ValueTask SetText(string text); + + [ReadOnly] + [return: Immutable] + [Alias("GetText")] + ValueTask GetText(); +} \ No newline at end of file diff --git a/Pushy.Domain/LinkResult.cs b/Pushy.Domain/LinkResult.cs new file mode 100644 index 0000000..8f2ff37 --- /dev/null +++ b/Pushy.Domain/LinkResult.cs @@ -0,0 +1,6 @@ +namespace Pushy.Domain; + +[Immutable] +[GenerateSerializer] +[Alias("Pushy.Grains.LinkResult")] +public record LinkResult(ITextItem? Item); \ No newline at end of file diff --git a/Pushy.Domain/Pushy.Domain.csproj b/Pushy.Domain/Pushy.Domain.csproj new file mode 100644 index 0000000..25e2f49 --- /dev/null +++ b/Pushy.Domain/Pushy.Domain.csproj @@ -0,0 +1,13 @@ + + + + net9.0 + enable + enable + + + + + + + diff --git a/Pushy.Domain/TextItem.cs b/Pushy.Domain/TextItem.cs new file mode 100644 index 0000000..de15c4d --- /dev/null +++ b/Pushy.Domain/TextItem.cs @@ -0,0 +1,6 @@ +namespace Pushy.Domain; + +public sealed class TextItem +{ + public string? Text { get; set; } +} \ No newline at end of file diff --git a/Pushy.Domain/TextSetResult.cs b/Pushy.Domain/TextSetResult.cs new file mode 100644 index 0000000..ff4733e --- /dev/null +++ b/Pushy.Domain/TextSetResult.cs @@ -0,0 +1,8 @@ +namespace Pushy.Domain; + +[GenerateSerializer] +public enum TextSetResult +{ + Failure, + Success +} \ No newline at end of file diff --git a/Pushy/Pushy/Grains/LinkGenerator.cs b/Pushy.Silo/Grains/LinkGenerator.cs similarity index 74% rename from Pushy/Pushy/Grains/LinkGenerator.cs rename to Pushy.Silo/Grains/LinkGenerator.cs index 0b975aa..22a379b 100644 --- a/Pushy/Pushy/Grains/LinkGenerator.cs +++ b/Pushy.Silo/Grains/LinkGenerator.cs @@ -1,17 +1,6 @@ -using System.Diagnostics.CodeAnalysis; +using Pushy.Domain; -namespace Pushy.Grains; - -[Immutable] -[GenerateSerializer] -[Alias("Pushy.Grains.LinkResult")] -public record LinkResult(ITextItem? Item); - -public interface ILinkGenerator : IGrainWithGuidKey -{ - [Alias("GenerateLink")] - public ValueTask GenerateTextShare([Immutable] string text); -} +namespace Pushy.Silo.Grains; public sealed class LinkGenerator : IGrainBase, ILinkGenerator { diff --git a/Pushy/Pushy/Grains/TextItemGrain.cs b/Pushy.Silo/Grains/TextItemGrain.cs similarity index 75% rename from Pushy/Pushy/Grains/TextItemGrain.cs rename to Pushy.Silo/Grains/TextItemGrain.cs index 1d926b4..0136221 100644 --- a/Pushy/Pushy/Grains/TextItemGrain.cs +++ b/Pushy.Silo/Grains/TextItemGrain.cs @@ -1,41 +1,21 @@ -using Orleans.Concurrency; +using Pushy.Domain; -namespace Pushy.Grains; - -[GenerateSerializer] -public enum TextSetResult -{ - Failure, - Success -} - -public sealed class TextItem -{ - public string? Text { get; set; } -} - -public interface ITextItem : IGrainWithStringKey -{ - [Alias("SetText")] - public ValueTask SetText(string text); - - [ReadOnly] - [return: Immutable] - [Alias("GetText")] - ValueTask GetText(); -} +namespace Pushy.Silo.Grains; public sealed class TextItemGrain : IGrainBase, ITextItem, IRemindable { private readonly IPersistentState _state; + private readonly ILogger _logger; private IGrainReminder? _reminder; public TextItemGrain( IGrainContext grainContext, - [PersistentState("text")] IPersistentState state) + [PersistentState("text")] IPersistentState state, + ILogger logger) { _state = state; + _logger = logger; GrainContext = grainContext; } @@ -78,8 +58,10 @@ public sealed class TextItemGrain : IGrainBase, ITextItem, IRemindable if (reminderName == "clear") { _state.State.Text = null; - await _state.WriteStateAsync(); + await _state.WriteStateAsync(); this.DeactivateOnIdle(); + + _logger.LogInformation("Text item have been cleared!"); } } } \ No newline at end of file diff --git a/Pushy.Silo/Program.cs b/Pushy.Silo/Program.cs new file mode 100644 index 0000000..bae36e3 --- /dev/null +++ b/Pushy.Silo/Program.cs @@ -0,0 +1,28 @@ +using StackExchange.Redis; + +var builder = Host.CreateApplicationBuilder(args); + +builder.UseOrleans(silo => +{ + silo.AddActivityPropagation(); + silo.UseRedisClustering(builder.Configuration.GetConnectionString("Valkey")!); + silo.UseRedisReminderService(conf => + { + ConfigurationOptions configurationOptions = + ConfigurationOptions.Parse(builder.Configuration.GetConnectionString("Valkey")!); + configurationOptions.DefaultDatabase = 0; + conf.ConfigurationOptions = configurationOptions; + }); + + silo.AddRedisGrainStorageAsDefault(options => + { + ConfigurationOptions configurationOptions = ConfigurationOptions.Parse(builder.Configuration.GetConnectionString("Valkey")!); + configurationOptions.DefaultDatabase = 1; + options.ConfigurationOptions = configurationOptions; + }); +}); + +builder.Services.AddAllElasticApm(); + +var host = builder.Build(); +host.Run(); \ No newline at end of file diff --git a/Pushy.Silo/Properties/launchSettings.json b/Pushy.Silo/Properties/launchSettings.json new file mode 100644 index 0000000..3ca60ad --- /dev/null +++ b/Pushy.Silo/Properties/launchSettings.json @@ -0,0 +1,12 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "profiles": { + "Pushy.Silo": { + "commandName": "Project", + "dotnetRunMessages": true, + "environmentVariables": { + "DOTNET_ENVIRONMENT": "Development" + } + } + } +} diff --git a/Pushy.Silo/Pushy.Silo.csproj b/Pushy.Silo/Pushy.Silo.csproj new file mode 100644 index 0000000..841adea --- /dev/null +++ b/Pushy.Silo/Pushy.Silo.csproj @@ -0,0 +1,25 @@ + + + + net9.0 + enable + enable + dotnet-Pushy.Silo-607fe096-6d3f-44f4-8e5d-8a2c875f8758 + Linux + Pushy Silo + Henrik Lassen + + + + + + + + + + + + + + + diff --git a/Pushy.Silo/appsettings.Development.json b/Pushy.Silo/appsettings.Development.json new file mode 100644 index 0000000..b2dcdb6 --- /dev/null +++ b/Pushy.Silo/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.Hosting.Lifetime": "Information" + } + } +} diff --git a/Pushy.Silo/appsettings.json b/Pushy.Silo/appsettings.json new file mode 100644 index 0000000..d7be3a4 --- /dev/null +++ b/Pushy.Silo/appsettings.json @@ -0,0 +1,11 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "ElasticApm": { + "ServerUrl": "http://apm.home.local:8200" + } +} diff --git a/Pushy.sln b/Pushy.sln index d241b50..e632121 100644 --- a/Pushy.sln +++ b/Pushy.sln @@ -4,6 +4,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Pushy", "Pushy\Pushy\Pushy. EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Pushy.Client", "Pushy\Pushy.Client\Pushy.Client.csproj", "{E7FD5748-F854-48A7-ABE0-4E5C66B3671D}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Pushy.Silo", "Pushy.Silo\Pushy.Silo.csproj", "{7D79D5F5-95F6-40C3-8908-3853AEEBF70B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Pushy.Domain", "Pushy.Domain\Pushy.Domain.csproj", "{F8840C69-22DF-4B0A-A2A3-366DFCA059DE}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Frontend", "Frontend", "{C4155A90-7E85-4BB0-BB3E-E9FBF9F6D2B3}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -18,5 +24,17 @@ Global {E7FD5748-F854-48A7-ABE0-4E5C66B3671D}.Debug|Any CPU.Build.0 = Debug|Any CPU {E7FD5748-F854-48A7-ABE0-4E5C66B3671D}.Release|Any CPU.ActiveCfg = Release|Any CPU {E7FD5748-F854-48A7-ABE0-4E5C66B3671D}.Release|Any CPU.Build.0 = Release|Any CPU + {7D79D5F5-95F6-40C3-8908-3853AEEBF70B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7D79D5F5-95F6-40C3-8908-3853AEEBF70B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7D79D5F5-95F6-40C3-8908-3853AEEBF70B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7D79D5F5-95F6-40C3-8908-3853AEEBF70B}.Release|Any CPU.Build.0 = Release|Any CPU + {F8840C69-22DF-4B0A-A2A3-366DFCA059DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F8840C69-22DF-4B0A-A2A3-366DFCA059DE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F8840C69-22DF-4B0A-A2A3-366DFCA059DE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F8840C69-22DF-4B0A-A2A3-366DFCA059DE}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {1156C75D-F4F0-42CA-A007-724AC6CEC123} = {C4155A90-7E85-4BB0-BB3E-E9FBF9F6D2B3} + {E7FD5748-F854-48A7-ABE0-4E5C66B3671D} = {C4155A90-7E85-4BB0-BB3E-E9FBF9F6D2B3} EndGlobalSection EndGlobal diff --git a/Pushy.sln.DotSettings.user b/Pushy.sln.DotSettings.user index 79bc171..28132b7 100644 --- a/Pushy.sln.DotSettings.user +++ b/Pushy.sln.DotSettings.user @@ -1,3 +1,4 @@  ForceIncluded - ForceIncluded \ No newline at end of file + ForceIncluded + ForceIncluded \ No newline at end of file diff --git a/Pushy.slnx b/Pushy.slnx index 5162cfc..29b46c9 100644 --- a/Pushy.slnx +++ b/Pushy.slnx @@ -1,4 +1,8 @@  - - + + + + + + \ No newline at end of file diff --git a/Pushy/Pushy.Client/Pushy.Client.csproj b/Pushy/Pushy.Client/Pushy.Client.csproj index 606449b..f3eba12 100644 --- a/Pushy/Pushy.Client/Pushy.Client.csproj +++ b/Pushy/Pushy.Client/Pushy.Client.csproj @@ -7,12 +7,11 @@ true Default Linux - 13 - + diff --git a/Pushy/Pushy/Components/App.razor b/Pushy/Pushy/Components/App.razor index ae06d9f..383a3e7 100644 --- a/Pushy/Pushy/Components/App.razor +++ b/Pushy/Pushy/Components/App.razor @@ -14,11 +14,12 @@ + - + @if (Agent.Configuration.Enabled && Environment.IsProduction()) { diff --git a/Pushy/Pushy/Components/Pages/DisplayText.razor b/Pushy/Pushy/Components/Pages/DisplayText.razor index 23d4120..dfd2200 100644 --- a/Pushy/Pushy/Components/Pages/DisplayText.razor +++ b/Pushy/Pushy/Components/Pages/DisplayText.razor @@ -1,5 +1,5 @@ @page "/t/{id}" -@using Pushy.Grains +@using Pushy.Domain @if (SharedText is null) { diff --git a/Pushy/Pushy/Components/Pages/Home.razor b/Pushy/Pushy/Components/Pages/Home.razor index 9a41617..62f6e63 100644 --- a/Pushy/Pushy/Components/Pages/Home.razor +++ b/Pushy/Pushy/Components/Pages/Home.razor @@ -1,5 +1,5 @@ @page "/" -@using Pushy.Grains +@using Pushy.Domain @inject NavigationManager Nav Share Something! diff --git a/Pushy/Pushy/Dockerfile b/Pushy/Pushy/Dockerfile deleted file mode 100644 index 9f2c761..0000000 --- a/Pushy/Pushy/Dockerfile +++ /dev/null @@ -1,23 +0,0 @@ -FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS base -USER $APP_UID -WORKDIR /app -EXPOSE 8080 - -FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build -ARG BUILD_CONFIGURATION=Release -WORKDIR /src -COPY ["Pushy/Pushy/Pushy.csproj", "Pushy/Pushy/"] -COPY ["Pushy/Pushy.Client/Pushy.Client.csproj", "Pushy/Pushy.Client/"] -RUN dotnet restore "Pushy/Pushy/Pushy.csproj" -COPY . . -WORKDIR "/src/Pushy/Pushy" -RUN dotnet build "Pushy.csproj" -c $BUILD_CONFIGURATION -o /app/build - -FROM build AS publish -ARG BUILD_CONFIGURATION=Release -RUN dotnet publish "Pushy.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false - -FROM base AS final -WORKDIR /app -COPY --from=publish /app/publish . -ENTRYPOINT ["dotnet", "Pushy.dll"] diff --git a/Pushy/Pushy/Program.cs b/Pushy/Pushy/Program.cs index d329835..18974c3 100644 --- a/Pushy/Pushy/Program.cs +++ b/Pushy/Pushy/Program.cs @@ -3,42 +3,43 @@ using Elastic.Extensions.Logging.Options; using Elastic.Transport; using Microsoft.AspNetCore.DataProtection; using Pushy.Components; -using Pushy.Grains; +using Pushy.Domain; using StackExchange.Redis; var builder = WebApplication.CreateBuilder(args); -builder.UseOrleans(silo => -{ - silo.UseLocalhostClustering(); - silo.UseRedisReminderService(conf => - { - ConfigurationOptions configurationOptions = - ConfigurationOptions.Parse(builder.Configuration.GetConnectionString("Valkey")!); - configurationOptions.DefaultDatabase = 0; - conf.ConfigurationOptions = configurationOptions; - }); - - silo.AddRedisGrainStorageAsDefault(options => - { - ConfigurationOptions configurationOptions = ConfigurationOptions.Parse(builder.Configuration.GetConnectionString("Valkey")!); - configurationOptions.DefaultDatabase = 1; - options.ConfigurationOptions = configurationOptions; - }); +string? connectionString = builder.Configuration.GetConnectionString("Valkey"); +if (string.IsNullOrEmpty(connectionString)) + throw new InvalidOperationException("Missing Valkey connection string"); +builder.UseOrleansClient(silo => +{ + silo.UseRedisClustering(connectionString); silo.AddActivityPropagation(); }); if (builder.Environment.IsProduction()) { - IConnectionMultiplexer multiplexer = ConnectionMultiplexer.Connect(builder.Configuration.GetConnectionString("Valkey")!); + string? elasticRawUrl = builder.Configuration["Elasticsearch:Url"]; + string? elasticApiKey = builder.Configuration["Elasticsearch:ApiKey"]; + + if (string.IsNullOrEmpty(elasticRawUrl)) + throw new InvalidOperationException( + "Missing Elasticsearch URL for logging"); + + if(string.IsNullOrEmpty(elasticApiKey)) + throw new InvalidOperationException("Missing Elasticsearch API key"); + + IConnectionMultiplexer multiplexer = ConnectionMultiplexer.Connect(connectionString); builder.Services.AddDataProtection() .PersistKeysToStackExchangeRedis(multiplexer); - - var transport = new TransportConfiguration(new StaticNodePool([new Uri("https://elastic-node-1.home.local:9200")])) - .Authentication(new ApiKey(builder.Configuration["Elasticsearch:ApiKey"]!)) - .ServerCertificateValidationCallback((_, _, _, _) => true); + + var transport = new TransportConfiguration(new StaticNodePool([new Uri(elasticRawUrl)])) + { + Authentication = new ApiKey(elasticApiKey), + ServerCertificateValidationCallback = (_, _, _, _) => true + }; builder.Logging.AddElasticsearch(opt => { @@ -50,17 +51,18 @@ if (builder.Environment.IsProduction()) opt.Transport = new DistributedTransport(transport); }); } +builder.Services.AddAllElasticApm(); builder.Services.AddScoped(service => - service.GetRequiredService().GetGrain(Guid.Empty)); -builder.Services.AddAllElasticApm(); + service.GetRequiredService().GetGrain(Guid.Empty) + ); builder.Services.AddHealthChecks(); builder.Services.AddCors(policy => { - policy.AddDefaultPolicy(builder => + policy.AddDefaultPolicy(cors => { - builder.WithOrigins("https://henrikml.dk") + cors.WithOrigins("https://henrikml.dk") .AllowAnyHeader(); }); }); diff --git a/Pushy/Pushy/Pushy.csproj b/Pushy/Pushy/Pushy.csproj index b4c3193..d2cedc3 100644 --- a/Pushy/Pushy/Pushy.csproj +++ b/Pushy/Pushy/Pushy.csproj @@ -5,7 +5,6 @@ enable enable Linux - 13 d8fe2296-80f7-4812-b26a-ccaa6167a6e1 @@ -15,28 +14,18 @@ - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - + + - - - - + + + - + + - - - .dockerignore - - - diff --git a/Pushy/Pushy/Pushy.csproj.DotSettings.user b/Pushy/Pushy/Pushy.csproj.DotSettings.user new file mode 100644 index 0000000..1946bb7 --- /dev/null +++ b/Pushy/Pushy/Pushy.csproj.DotSettings.user @@ -0,0 +1,3 @@ + + + wwwroot\_framework\blazor.web.js \ No newline at end of file diff --git a/Pushy/Pushy/appsettings.json b/Pushy/Pushy/appsettings.json index 4359f0c..9e56493 100644 --- a/Pushy/Pushy/appsettings.json +++ b/Pushy/Pushy/appsettings.json @@ -7,8 +7,7 @@ } }, "AllowedHosts": "*", - "ElasticApm": - { + "ElasticApm": { "ServerUrl": "http://apm.home.local:8200", "TransactionNameGroups": "GET /t/*" } diff --git a/Pushy/Pushy/wwwroot/app.tailwind.css b/Pushy/Pushy/wwwroot/app.tailwind.css index 5d0a9c6..2821ea1 100644 --- a/Pushy/Pushy/wwwroot/app.tailwind.css +++ b/Pushy/Pushy/wwwroot/app.tailwind.css @@ -625,13 +625,14 @@ html { } :root { - color-scheme: light; + color-scheme: dark; --in: 72.06% 0.191 231.6; --su: 64.8% 0.150 160; --wa: 84.71% 0.199 83.87; --er: 71.76% 0.221 22.18; - --pc: 89.824% 0.06192 275.75; - --ac: 15.352% 0.0368 183.61; + --pc: 13.138% 0.0392 275.75; + --sc: 14.96% 0.052 342.55; + --ac: 14.902% 0.0334 183.61; --inc: 0% 0 0; --suc: 0% 0 0; --wac: 0% 0 0; @@ -645,84 +646,15 @@ html { --border-btn: 1px; --tab-border: 1px; --tab-radius: 0.5rem; - --p: 49.12% 0.3096 275.75; - --s: 69.71% 0.329 342.55; - --sc: 98.71% 0.0106 342.55; - --a: 76.76% 0.184 183.61; - --n: 32.1785% 0.02476 255.701624; - --nc: 89.4994% 0.011585 252.096176; - --b1: 100% 0 0; - --b2: 96.1151% 0 0; - --b3: 92.4169% 0.00108 197.137559; - --bc: 27.8078% 0.029596 256.847952; -} - -@media (prefers-color-scheme: dark) { - :root { - color-scheme: dark; - --in: 72.06% 0.191 231.6; - --su: 64.8% 0.150 160; - --wa: 84.71% 0.199 83.87; - --er: 71.76% 0.221 22.18; - --pc: 13.138% 0.0392 275.75; - --sc: 14.96% 0.052 342.55; - --ac: 14.902% 0.0334 183.61; - --inc: 0% 0 0; - --suc: 0% 0 0; - --wac: 0% 0 0; - --erc: 0% 0 0; - --rounded-box: 1rem; - --rounded-btn: 0.5rem; - --rounded-badge: 1.9rem; - --animation-btn: 0.25s; - --animation-input: .2s; - --btn-focus-scale: 0.95; - --border-btn: 1px; - --tab-border: 1px; - --tab-radius: 0.5rem; - --p: 65.69% 0.196 275.75; - --s: 74.8% 0.26 342.55; - --a: 74.51% 0.167 183.61; - --n: 31.3815% 0.021108 254.139175; - --nc: 74.6477% 0.0216 264.435964; - --b1: 25.3267% 0.015896 252.417568; - --b2: 23.2607% 0.013807 253.100675; - --b3: 21.1484% 0.01165 254.087939; - --bc: 74.6477% 0.0216 264.435964; - } -} - -[data-theme=light] { - color-scheme: light; - --in: 72.06% 0.191 231.6; - --su: 64.8% 0.150 160; - --wa: 84.71% 0.199 83.87; - --er: 71.76% 0.221 22.18; - --pc: 89.824% 0.06192 275.75; - --ac: 15.352% 0.0368 183.61; - --inc: 0% 0 0; - --suc: 0% 0 0; - --wac: 0% 0 0; - --erc: 0% 0 0; - --rounded-box: 1rem; - --rounded-btn: 0.5rem; - --rounded-badge: 1.9rem; - --animation-btn: 0.25s; - --animation-input: .2s; - --btn-focus-scale: 0.95; - --border-btn: 1px; - --tab-border: 1px; - --tab-radius: 0.5rem; - --p: 49.12% 0.3096 275.75; - --s: 69.71% 0.329 342.55; - --sc: 98.71% 0.0106 342.55; - --a: 76.76% 0.184 183.61; - --n: 32.1785% 0.02476 255.701624; - --nc: 89.4994% 0.011585 252.096176; - --b1: 100% 0 0; - --b2: 96.1151% 0 0; - --b3: 92.4169% 0.00108 197.137559; - --bc: 27.8078% 0.029596 256.847952; + --p: 65.69% 0.196 275.75; + --s: 74.8% 0.26 342.55; + --a: 74.51% 0.167 183.61; + --n: 31.3815% 0.021108 254.139175; + --nc: 74.6477% 0.0216 264.435964; + --b1: 25.3267% 0.015896 252.417568; + --b2: 23.2607% 0.013807 253.100675; + --b3: 21.1484% 0.01165 254.087939; + --bc: 74.6477% 0.0216 264.435964; } [data-theme=dark] { @@ -758,6 +690,39 @@ html { --bc: 74.6477% 0.0216 264.435964; } +[data-theme=light] { + color-scheme: light; + --in: 72.06% 0.191 231.6; + --su: 64.8% 0.150 160; + --wa: 84.71% 0.199 83.87; + --er: 71.76% 0.221 22.18; + --pc: 89.824% 0.06192 275.75; + --ac: 15.352% 0.0368 183.61; + --inc: 0% 0 0; + --suc: 0% 0 0; + --wac: 0% 0 0; + --erc: 0% 0 0; + --rounded-box: 1rem; + --rounded-btn: 0.5rem; + --rounded-badge: 1.9rem; + --animation-btn: 0.25s; + --animation-input: .2s; + --btn-focus-scale: 0.95; + --border-btn: 1px; + --tab-border: 1px; + --tab-radius: 0.5rem; + --p: 49.12% 0.3096 275.75; + --s: 69.71% 0.329 342.55; + --sc: 98.71% 0.0106 342.55; + --a: 76.76% 0.184 183.61; + --n: 32.1785% 0.02476 255.701624; + --nc: 89.4994% 0.011585 252.096176; + --b1: 100% 0 0; + --b2: 96.1151% 0 0; + --b3: 92.4169% 0.00108 197.137559; + --bc: 27.8078% 0.029596 256.847952; +} + @media (hover:hover) { .label a:hover { --tw-text-opacity: 1; @@ -1572,11 +1537,6 @@ html { mask-image: url("data:image/svg+xml,%3Csvg width='24' height='24' stroke='black' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cg transform-origin='center'%3E%3Ccircle cx='12' cy='12' r='9.5' fill='none' stroke-width='3' stroke-linecap='round'%3E%3CanimateTransform attributeName='transform' type='rotate' from='0 12 12' to='360 12 12' dur='2s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dasharray' values='0,150;42,150;42,150' keyTimes='0;0.475;1' dur='1.5s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dashoffset' values='0;-16;-59' keyTimes='0;0.475;1' dur='1.5s' repeatCount='indefinite'/%3E%3C/circle%3E%3C/g%3E%3C/svg%3E"); } -.loading-spinner { - -webkit-mask-image: url("data:image/svg+xml,%3Csvg width='24' height='24' stroke='black' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cg transform-origin='center'%3E%3Ccircle cx='12' cy='12' r='9.5' fill='none' stroke-width='3' stroke-linecap='round'%3E%3CanimateTransform attributeName='transform' type='rotate' from='0 12 12' to='360 12 12' dur='2s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dasharray' values='0,150;42,150;42,150' keyTimes='0;0.475;1' dur='1.5s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dashoffset' values='0;-16;-59' keyTimes='0;0.475;1' dur='1.5s' repeatCount='indefinite'/%3E%3C/circle%3E%3C/g%3E%3C/svg%3E"); - mask-image: url("data:image/svg+xml,%3Csvg width='24' height='24' stroke='black' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cg transform-origin='center'%3E%3Ccircle cx='12' cy='12' r='9.5' fill='none' stroke-width='3' stroke-linecap='round'%3E%3CanimateTransform attributeName='transform' type='rotate' from='0 12 12' to='360 12 12' dur='2s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dasharray' values='0,150;42,150;42,150' keyTimes='0;0.475;1' dur='1.5s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dashoffset' values='0;-16;-59' keyTimes='0;0.475;1' dur='1.5s' repeatCount='indefinite'/%3E%3C/circle%3E%3C/g%3E%3C/svg%3E"); -} - :where(.menu li:not(.menu-title, .disabled) > *:not(ul, details, .menu-title)):not(summary, .active, .btn).focus, :where(.menu li:not(.menu-title, .disabled) > *:not(ul, details, .menu-title)):not(summary, .active, .btn):focus, :where(.menu li:not(.menu-title, .disabled) > *:not(ul, details, .menu-title)):is(summary):not(.active, .btn):focus-visible, :where(.menu li:not(.menu-title, .disabled) > details > summary:not(.menu-title)):not(summary, .active, .btn).focus, :where(.menu li:not(.menu-title, .disabled) > details > summary:not(.menu-title)):not(summary, .active, .btn):focus, :where(.menu li:not(.menu-title, .disabled) > details > summary:not(.menu-title)):is(summary):not(.active, .btn):focus-visible { cursor: pointer; background-color: var(--fallback-bc,oklch(var(--bc)/0.1)); @@ -2274,89 +2234,20 @@ html { display: none; } -.h-10 { - height: 2.5rem; -} - -.h-5\/6 { - height: 83.333333%; +.h-48 { + height: 12rem; } .h-full { height: 100%; } -.h-4\/6 { - height: 66.666667%; -} - -.h-\[64px\] { - height: 64px; -} - -.h-16 { - height: 4rem; -} - -.h-32 { - height: 8rem; -} - -.h-48 { - height: 12rem; -} - -.w-4 { - width: 1rem; -} - -.w-16 { - width: 4rem; -} - -.w-1\/2 { - width: 50%; -} - -.w-64 { - width: 16rem; -} - -.w-auto { - width: auto; -} - -.w-max { - width: -moz-max-content; - width: max-content; -} - -.w-10\/12 { - width: 83.333333%; -} - -.w-11\/12 { - width: 91.666667%; -} - -.w-8\/12 { - width: 66.666667%; -} - -.w-4\/12 { - width: 33.333333%; -} - .w-6\/12 { width: 50%; } -.w-8 { - width: 2rem; -} - -.flex-grow { - flex-grow: 1; +.w-auto { + width: auto; } .grow { @@ -2371,14 +2262,6 @@ html { flex-direction: column; } -.content-center { - align-content: center; -} - -.items-center { - align-items: center; -} - .justify-center { justify-content: center; } @@ -2401,10 +2284,6 @@ html { text-align: center; } -.align-middle { - vertical-align: middle; -} - .blur { --tw-blur: blur(8px); filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); @@ -2412,26 +2291,4 @@ html { .filter { filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); -} - -@media (min-width: 640px) { - .sm\:w-8\/12 { - width: 66.666667%; - } -} - -@media (min-width: 768px) { - .md\:w-4\/12 { - width: 33.333333%; - } - - .md\:w-8\/12 { - width: 66.666667%; - } -} - -@media (min-width: 1024px) { - .lg\:w-4\/12 { - width: 33.333333%; - } } \ No newline at end of file diff --git a/Pushy/tailwind.config.js b/Pushy/tailwind.config.js index 9372598..6f24af6 100644 --- a/Pushy/tailwind.config.js +++ b/Pushy/tailwind.config.js @@ -4,6 +4,9 @@ module.exports = { theme: { extend: {}, }, + daisyui: { + themes: ['dark', 'light'], + }, plugins: [ require('daisyui') ], diff --git a/app.json b/app.json index 2dd532e..593296f 100644 --- a/app.json +++ b/app.json @@ -1,4 +1,12 @@ { + "formation": { + "web": { + "quantity": 1 + }, + "silo": { + "quantity": 2 + } + }, "healthchecks": { "web": [ { diff --git a/run-silo.sh b/run-silo.sh new file mode 100644 index 0000000..fe4507f --- /dev/null +++ b/run-silo.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +cd /app/silo +dotnet Pushy.Silo.dll \ No newline at end of file diff --git a/run-web.sh b/run-web.sh new file mode 100644 index 0000000..0114fbe --- /dev/null +++ b/run-web.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +cd /app/pushy +dotnet Pushy.dll \ No newline at end of file