First iteration of the plugin template
Some checks failed
Nuget: publish / publish (push) Has been cancelled
Some checks failed
Nuget: publish / publish (push) Has been cancelled
This commit is contained in:
29
.gitea/workflows/publish.yml
Normal file
29
.gitea/workflows/publish.yml
Normal file
@@ -0,0 +1,29 @@
|
||||
name: "Nuget: publish"
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
paths:
|
||||
- "Moonlight.PluginTemplate.csproj"
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
# Checkout code
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# Build project
|
||||
- name: Build project
|
||||
run: dotnet build Moonlight.PluginTemplate --configuration Release
|
||||
|
||||
# Publish project
|
||||
- name: Publish NuGet package
|
||||
run: dotnet pack Moonlight.PluginTemplate --configuration Release --output ./artifacts
|
||||
|
||||
- name: Push nuget package
|
||||
run: dotnet nuget push ./artifacts/*.nupkg --skip-duplicate --source https://git.battlestati.one/api/packages/Moonlight-Panel/nuget/index.json --api-key ${{ secrets.ACCESS_TOKEN }}
|
||||
409
.gitignore
vendored
Normal file
409
.gitignore
vendored
Normal file
@@ -0,0 +1,409 @@
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
##
|
||||
## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
|
||||
|
||||
# User-specific files
|
||||
*.rsuser
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
|
||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
*.userprefs
|
||||
|
||||
# Mono auto generated files
|
||||
mono_crash.*
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
x64/
|
||||
x86/
|
||||
[Ww][Ii][Nn]32/
|
||||
[Aa][Rr][Mm]/
|
||||
[Aa][Rr][Mm]64/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
[Ll]og/
|
||||
[Ll]ogs/
|
||||
|
||||
# Visual Studio 2015/2017 cache/options directory
|
||||
.vs/
|
||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||
#wwwroot/
|
||||
|
||||
# Visual Studio 2017 auto generated files
|
||||
Generated\ Files/
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
# NUnit
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
nunit-*.xml
|
||||
|
||||
# Build Results of an ATL Project
|
||||
[Dd]ebugPS/
|
||||
[Rr]eleasePS/
|
||||
dlldata.c
|
||||
|
||||
# Benchmark Results
|
||||
BenchmarkDotNet.Artifacts/
|
||||
|
||||
# .NET Core
|
||||
project.lock.json
|
||||
project.fragment.lock.json
|
||||
artifacts/
|
||||
|
||||
# ASP.NET Scaffolding
|
||||
ScaffoldingReadMe.txt
|
||||
|
||||
# StyleCop
|
||||
StyleCopReport.xml
|
||||
|
||||
# Files built by Visual Studio
|
||||
*_i.c
|
||||
*_p.c
|
||||
*_h.h
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.iobj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.ipdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*_wpftmp.csproj
|
||||
*.log
|
||||
*.tlog
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.svclog
|
||||
*.scc
|
||||
|
||||
# Chutzpah Test files
|
||||
_Chutzpah*
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opendb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
*.VC.db
|
||||
*.VC.VC.opendb
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
*.sap
|
||||
|
||||
# Visual Studio Trace Files
|
||||
*.e2e
|
||||
|
||||
# TFS 2012 Local Workspace
|
||||
$tf/
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
*.DotSettings.user
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# AxoCover is a Code Coverage Tool
|
||||
.axoCover/*
|
||||
!.axoCover/settings.json
|
||||
|
||||
# Coverlet is a free, cross platform Code Coverage Tool
|
||||
coverage*.json
|
||||
coverage*.xml
|
||||
coverage*.info
|
||||
|
||||
# Visual Studio code coverage results
|
||||
*.coverage
|
||||
*.coveragexml
|
||||
|
||||
# NCrunch
|
||||
_NCrunch_*
|
||||
.*crunch*.local.xml
|
||||
nCrunchTemp_*
|
||||
|
||||
# MightyMoose
|
||||
*.mm.*
|
||||
AutoTest.Net/
|
||||
|
||||
# Web workbench (sass)
|
||||
.sass-cache/
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||
# but database connection strings (with potential passwords) will be unencrypted
|
||||
*.pubxml
|
||||
*.publishproj
|
||||
|
||||
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||
# in these scripts will be unencrypted
|
||||
PublishScripts/
|
||||
|
||||
# NuGet Packages
|
||||
*.nupkg
|
||||
# NuGet Symbol Packages
|
||||
*.snupkg
|
||||
# The packages folder can be ignored because of Package Restore
|
||||
**/[Pp]ackages/*
|
||||
# except build/, which is used as an MSBuild target.
|
||||
!**/[Pp]ackages/build/
|
||||
# Uncomment if necessary however generally it will be regenerated when needed
|
||||
#!**/[Pp]ackages/repositories.config
|
||||
# NuGet v3's project.json files produces more ignorable files
|
||||
*.nuget.props
|
||||
*.nuget.targets
|
||||
|
||||
# Microsoft Azure Build Output
|
||||
csx/
|
||||
*.build.csdef
|
||||
|
||||
# Microsoft Azure Emulator
|
||||
ecf/
|
||||
rcf/
|
||||
|
||||
# Windows Store app package directories and files
|
||||
AppPackages/
|
||||
BundleArtifacts/
|
||||
Package.StoreAssociation.xml
|
||||
_pkginfo.txt
|
||||
*.appx
|
||||
*.appxbundle
|
||||
*.appxupload
|
||||
|
||||
# Visual Studio cache files
|
||||
# files ending in .cache can be ignored
|
||||
*.[Cc]ache
|
||||
# but keep track of directories ending in .cache
|
||||
!?*.[Cc]ache/
|
||||
|
||||
# Others
|
||||
ClientBin/
|
||||
~$*
|
||||
*~
|
||||
*.dbmdl
|
||||
*.dbproj.schemaview
|
||||
*.jfm
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
orleans.codegen.cs
|
||||
|
||||
# Including strong name files can present a security risk
|
||||
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||
#*.snk
|
||||
|
||||
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||
#bower_components/
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project file
|
||||
# to a newer Visual Studio version. Backup files are not needed,
|
||||
# because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
ServiceFabricBackup/
|
||||
*.rptproj.bak
|
||||
|
||||
# SQL Server files
|
||||
*.mdf
|
||||
*.ldf
|
||||
*.ndf
|
||||
|
||||
# Business Intelligence projects
|
||||
*.rdl.data
|
||||
*.bim.layout
|
||||
*.bim_*.settings
|
||||
*.rptproj.rsuser
|
||||
*- [Bb]ackup.rdl
|
||||
*- [Bb]ackup ([0-9]).rdl
|
||||
*- [Bb]ackup ([0-9][0-9]).rdl
|
||||
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
|
||||
# GhostDoc plugin setting file
|
||||
*.GhostDoc.xml
|
||||
|
||||
# Node.js Tools for Visual Studio
|
||||
.ntvs_analysis.dat
|
||||
node_modules/
|
||||
|
||||
# Visual Studio 6 build log
|
||||
*.plg
|
||||
|
||||
# Visual Studio 6 workspace options file
|
||||
*.opt
|
||||
|
||||
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||
*.vbw
|
||||
|
||||
# Visual Studio 6 auto-generated project file (contains which files were open etc.)
|
||||
*.vbp
|
||||
|
||||
# Visual Studio 6 workspace and project file (working project files containing files to include in project)
|
||||
*.dsw
|
||||
*.dsp
|
||||
|
||||
# Visual Studio 6 technical files
|
||||
*.ncb
|
||||
*.aps
|
||||
|
||||
# Visual Studio LightSwitch build output
|
||||
**/*.HTMLClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/ModelManifest.xml
|
||||
**/*.Server/GeneratedArtifacts
|
||||
**/*.Server/ModelManifest.xml
|
||||
_Pvt_Extensions
|
||||
|
||||
# Paket dependency manager
|
||||
.paket/paket.exe
|
||||
paket-files/
|
||||
|
||||
# FAKE - F# Make
|
||||
.fake/
|
||||
|
||||
# CodeRush personal settings
|
||||
.cr/personal
|
||||
|
||||
# Python Tools for Visual Studio (PTVS)
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
# Cake - Uncomment if you are using it
|
||||
# tools/**
|
||||
# !tools/packages.config
|
||||
|
||||
# Tabs Studio
|
||||
*.tss
|
||||
|
||||
# Telerik's JustMock configuration file
|
||||
*.jmconfig
|
||||
|
||||
# BizTalk build output
|
||||
*.btp.cs
|
||||
*.btm.cs
|
||||
*.odx.cs
|
||||
*.xsd.cs
|
||||
|
||||
# OpenCover UI analysis results
|
||||
OpenCover/
|
||||
|
||||
# Azure Stream Analytics local run output
|
||||
ASALocalRun/
|
||||
|
||||
# MSBuild Binary and Structured Log
|
||||
*.binlog
|
||||
|
||||
# NVidia Nsight GPU debugger configuration file
|
||||
*.nvuser
|
||||
|
||||
# MFractors (Xamarin productivity tool) working folder
|
||||
.mfractor/
|
||||
|
||||
# Local History for Visual Studio
|
||||
.localhistory/
|
||||
|
||||
# Visual Studio History (VSHistory) files
|
||||
.vshistory/
|
||||
|
||||
# BeatPulse healthcheck temp database
|
||||
healthchecksdb
|
||||
|
||||
# Backup folder for Package Reference Convert tool in Visual Studio 2017
|
||||
MigrationBackup/
|
||||
|
||||
# Ionide (cross platform F# VS Code tools) working folder
|
||||
.ionide/
|
||||
|
||||
# Fody - auto-generated XML schema
|
||||
FodyWeavers.xsd
|
||||
|
||||
# VS Code files for those working on multiple tools
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
*.code-workspace
|
||||
|
||||
# Local History for Visual Studio Code
|
||||
.history/
|
||||
|
||||
# Windows Installer files from build outputs
|
||||
*.cab
|
||||
*.msi
|
||||
*.msix
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
# JetBrains Rider
|
||||
**/.idea/**
|
||||
|
||||
# Style builds
|
||||
**/style.min.css
|
||||
**/package-lock.json
|
||||
**/bun.lock
|
||||
|
||||
# Secrets
|
||||
**/.env
|
||||
**/appsettings.json
|
||||
**/appsettings.Development.json
|
||||
**/storage
|
||||
61
Moonlight.PluginTemplate.csproj
Normal file
61
Moonlight.PluginTemplate.csproj
Normal file
@@ -0,0 +1,61 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<PackageId>Moonlight.PluginTemplate</PackageId>
|
||||
<PackageVersion>1.0.0</PackageVersion>
|
||||
<Title>Moonlight.PluginTemplate</Title>
|
||||
<Authors>Moonlight-Panel</Authors>
|
||||
<Description>Template for a plugin for moonlighte</Description>
|
||||
<PackageTags>moonlight,plugin,template</PackageTags>
|
||||
<PackageProjectUrl>https://git.battlestati.one/Moonlight-Panel/PluginTemplate</PackageProjectUrl>
|
||||
<PackageType>Template</PackageType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<IncludeContentInPack>true</IncludeContentInPack>
|
||||
<IncludeBuildOutput>false</IncludeBuildOutput>
|
||||
<ContentTargetFolders>content</ContentTargetFolders>
|
||||
<NoWarn>$(NoWarn);NU5128</NoWarn>
|
||||
<NoDefaultExcludes>true</NoDefaultExcludes>
|
||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||
<RootNamespace>Moonlight.PluginTemplate</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<LocalizeTemplates>false</LocalizeTemplates>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.TemplateEngine.Tasks" Version="*" PrivateAssets="all" IsImplicitlyDefined="true"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="content\**\*" Exclude="
|
||||
content\**\bin\**;
|
||||
content\**\obj\**;
|
||||
content\**\Debug\**;
|
||||
content\**\Release\**;
|
||||
content\**\.vs\**;
|
||||
content\**\.idea\**;
|
||||
content\**\node_modules\**;
|
||||
content\**\storage\**;
|
||||
content\**\style.min.css;
|
||||
content\**\package-lock.json;
|
||||
content\**\bun.lock;
|
||||
content\**\.env;
|
||||
content\**\*.DotSettings.user;
|
||||
content\**\appsettings.json;
|
||||
content\**\appsettings.Development.json;
|
||||
"/>
|
||||
<Compile Remove="**\*"/>
|
||||
<RazorGenerate Remove="**\*"/>
|
||||
<RazorComponent Remove="**\*"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="README.md" Pack="true" PackagePath=""/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="content\"/>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
3
PluginTemplate.slnx
Normal file
3
PluginTemplate.slnx
Normal file
@@ -0,0 +1,3 @@
|
||||
<Solution>
|
||||
<Project Path="Moonlight.PluginTemplate.csproj" />
|
||||
</Solution>
|
||||
54
content/PluginTemplate/.template.config/template.json
Normal file
54
content/PluginTemplate/.template.config/template.json
Normal file
@@ -0,0 +1,54 @@
|
||||
{
|
||||
"$schema": "http://json.schemastore.org/template",
|
||||
"author": "Moonlight-Panel",
|
||||
"classifications": [
|
||||
"Moonlight"
|
||||
],
|
||||
"name": "PluginTemplate",
|
||||
"description": "Template for a plugin for moonlight",
|
||||
"precedence": "0",
|
||||
"identity": "Moonlight.PluginTemplate",
|
||||
"shortName": "moonlight-plugintemplate",
|
||||
"tags": {
|
||||
"language": "C#",
|
||||
"type": "project"
|
||||
},
|
||||
"sourceName": "PluginTemplate",
|
||||
"sources": [
|
||||
{
|
||||
"source": "./",
|
||||
"target": "./",
|
||||
"include": [
|
||||
"**/*"
|
||||
],
|
||||
"exclude": [
|
||||
"**/[Bb]in/**",
|
||||
"**/[Oo]bj/**",
|
||||
"**/.template.config/**",
|
||||
"**/*.filelist",
|
||||
"**/*.user",
|
||||
"**/*.lock.json",
|
||||
"**/bun.lock",
|
||||
"**/node_modules/**",
|
||||
"**/storage/**",
|
||||
"**/appsettings.Development.json",
|
||||
"**/appsettings.json",
|
||||
"**/.idea/**",
|
||||
"**/.idea/**",
|
||||
"**/style.min.css"
|
||||
]
|
||||
}
|
||||
],
|
||||
"postActions": [
|
||||
{
|
||||
"actionId": "AC1156F7-BB77-4DB8-B28F-24EEBCCA1E5C",
|
||||
"condition": "true",
|
||||
"id": "instructions",
|
||||
"manualInstructions": [
|
||||
{
|
||||
"text": "Template successfully applied. https://moonlightpa.nl/dev"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
<Project>
|
||||
<ItemGroup>
|
||||
<!-- Put your plugin references here -->
|
||||
<!-- E.g. <PackageReference Include="MoonlightServers.Api" Version="2.1.0" /> -->
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,29 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="10.0.1"/>
|
||||
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.1">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
||||
<PackageReference Include="SimplePlugin" Version="1.0.2" />
|
||||
|
||||
<PackageReference Include="SimplePlugin.Abstractions" Version="1.0.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\PluginTemplate.Api\PluginTemplate.Api.csproj" />
|
||||
<ProjectReference Include="..\PluginTemplate.Frontend.Host\PluginTemplate.Frontend.Host.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="Api.props"/>
|
||||
</Project>
|
||||
@@ -0,0 +1,9 @@
|
||||
using Moonlight.Api;
|
||||
using SimplePlugin.Generated;
|
||||
|
||||
var plugins = PluginRegistry
|
||||
.Modules
|
||||
.OfType<MoonlightPlugin>()
|
||||
.ToArray();
|
||||
|
||||
await StartupHandler.RunAsync(args, plugins);
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/launchsettings.json",
|
||||
"profiles": {
|
||||
"http": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": false,
|
||||
"applicationUrl": "http://localhost:5031",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"https": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": false,
|
||||
"applicationUrl": "https://localhost:7240;http://localhost:5031",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
"Moonlight": {
|
||||
"Database": {
|
||||
"Host": "your-db.host",
|
||||
"Username": "change_me",
|
||||
"Password": "change_me",
|
||||
"Database": "change_me"
|
||||
},
|
||||
"Oidc": {
|
||||
"Authority": "http://localhost:8092",
|
||||
"RequireHttpsMetadata": false,
|
||||
"ClientId": "clientId",
|
||||
"ClientSecret": "clientSecret"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
<Project>
|
||||
<ItemGroup>
|
||||
<!-- Put your plugin references here -->
|
||||
<!-- E.g. <PackageReference Include="MoonlightServers.Frontend" Version="2.1.0" /> -->
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,22 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<OverrideHtmlAssetPlaceholders>true</OverrideHtmlAssetPlaceholders>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="10.0.1"/>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="10.0.1" PrivateAssets="all"/>
|
||||
<PackageReference Include="SimplePlugin" Version="1.0.2" />
|
||||
<PackageReference Include="SimplePlugin.Abstractions" Version="1.0.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\PluginTemplate.Frontend\PluginTemplate.Frontend.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="Frontend.props"/>
|
||||
</Project>
|
||||
@@ -0,0 +1,9 @@
|
||||
using Moonlight.Frontend;
|
||||
using SimplePlugin.Generated;
|
||||
|
||||
var plugins = PluginRegistry
|
||||
.Modules
|
||||
.OfType<MoonlightPlugin>()
|
||||
.ToArray();
|
||||
|
||||
await StartupHandler.RunAsync(args, plugins);
|
||||
@@ -0,0 +1,25 @@
|
||||
import fs from 'fs';
|
||||
import selectorParser from 'postcss-selector-parser';
|
||||
|
||||
export default function extractTailwindClasses(opts = {}) {
|
||||
const classSet = new Set();
|
||||
|
||||
return {
|
||||
postcssPlugin: 'extract-tailwind-classes',
|
||||
Rule(rule) {
|
||||
selectorParser(selectors => {
|
||||
selectors.walkClasses(node => {
|
||||
classSet.add(node.value);
|
||||
});
|
||||
}).processSync(rule.selector);
|
||||
},
|
||||
OnceExit() {
|
||||
const classArray = Array.from(classSet).sort();
|
||||
fs.mkdirSync('../../../PluginTemplate.Frontend/Styles', { recursive: true });
|
||||
fs.writeFileSync('../../../PluginTemplate.Frontend/Styles/PluginTemplate.Frontend.map', classArray.join('\n'));
|
||||
console.log(`Extracted classes ${classArray.length}`);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
extractTailwindClasses.postcss = true;
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"scripts": {
|
||||
"dev": "npx postcss styles.css -o ../wwwroot/style.min.css --watch",
|
||||
"dev-build": "npx postcss styles.css -o ../wwwroot/style.min.css",
|
||||
"build": "cross-env EXTRACT_CLASSES=true npx postcss styles.css -o ../wwwroot/style.min.css"
|
||||
},
|
||||
"dependencies": {
|
||||
"@tailwindcss/postcss": "^4.1.18",
|
||||
"cssnano": "^7.1.2",
|
||||
"postcss": "^8.5.6",
|
||||
"postcss-cli": "^11.0.1",
|
||||
"postcss-selector-parser": "^7.1.1",
|
||||
"tailwindcss": "^4.1.18",
|
||||
"tw-animate-css": "^1.4.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"cross-env": "^10.1.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import tailwindcss from '@tailwindcss/postcss';
|
||||
import cssnano from 'cssnano';
|
||||
import extractTailwindClasses from './extract-classes.mjs';
|
||||
|
||||
const plugins = [
|
||||
tailwindcss,
|
||||
cssnano({
|
||||
preset: 'default'
|
||||
})
|
||||
];
|
||||
|
||||
if (process.env.EXTRACT_CLASSES === "true") {
|
||||
plugins.push(extractTailwindClasses());
|
||||
}
|
||||
|
||||
export default {
|
||||
plugins
|
||||
};
|
||||
@@ -0,0 +1,31 @@
|
||||
@import "tailwindcss";
|
||||
@import "tw-animate-css";
|
||||
|
||||
@import "../bin/ShadcnBlazor/scrollbar.css";
|
||||
@import "../bin/ShadcnBlazor/default-theme.css";
|
||||
@import "./theme.css";
|
||||
|
||||
@source "../bin/Moonlight.Frontend/*.map";
|
||||
|
||||
@source "../../../Moonlight.Api/**/*.razor";
|
||||
@source "../../../Moonlight.Api/**/*.cs";
|
||||
@source "../../../Moonlight.Api/**/*.html";
|
||||
|
||||
@source "../../../Moonlight.Frontend/**/*.razor";
|
||||
@source "../../../Moonlight.Frontend/**/*.cs";
|
||||
@source "../../../Moonlight.Frontend/**/*.html";
|
||||
|
||||
@custom-variant dark (&:is(.dark *));
|
||||
|
||||
#blazor-error-ui {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@layer base {
|
||||
* {
|
||||
@apply border-border outline-ring/50;
|
||||
}
|
||||
body {
|
||||
@apply bg-background text-foreground;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
:root {
|
||||
--radius: 0.625rem;
|
||||
--background: oklch(1 0 0);
|
||||
--foreground: oklch(0.129 0.042 264.695);
|
||||
--card: oklch(1 0 0);
|
||||
--card-foreground: oklch(0.129 0.042 264.695);
|
||||
--popover: oklch(1 0 0);
|
||||
--popover-foreground: oklch(0.129 0.042 264.695);
|
||||
--primary: oklch(0.208 0.042 265.755);
|
||||
--primary-foreground: oklch(0.984 0.003 247.858);
|
||||
--secondary: oklch(0.968 0.007 247.896);
|
||||
--secondary-foreground: oklch(0.208 0.042 265.755);
|
||||
--muted: oklch(0.968 0.007 247.896);
|
||||
--muted-foreground: oklch(0.554 0.046 257.417);
|
||||
--accent: oklch(0.968 0.007 247.896);
|
||||
--accent-foreground: oklch(0.208 0.042 265.755);
|
||||
--destructive: oklch(0.577 0.245 27.325);
|
||||
--border: oklch(0.929 0.013 255.508);
|
||||
--input: oklch(0.929 0.013 255.508);
|
||||
--ring: oklch(0.704 0.04 256.788);
|
||||
--chart-1: oklch(0.646 0.222 41.116);
|
||||
--chart-2: oklch(0.6 0.118 184.704);
|
||||
--chart-3: oklch(0.398 0.07 227.392);
|
||||
--chart-4: oklch(0.828 0.189 84.429);
|
||||
--chart-5: oklch(0.769 0.188 70.08);
|
||||
|
||||
--sidebar: var(--background);
|
||||
--sidebar-foreground: var(--foreground);
|
||||
--sidebar-primary: var(--primary);
|
||||
--sidebar-primary-foreground: var(--primary-foreground);
|
||||
--sidebar-accent: var(--accent);
|
||||
--sidebar-accent-foreground: var(--accent-foreground);
|
||||
--sidebar-border: var(--border);
|
||||
--sidebar-ring: var(--ring);
|
||||
|
||||
--font-sans: Inter, sans-serif;
|
||||
--font-serif: Georgia, serif;
|
||||
}
|
||||
|
||||
.dark {
|
||||
/* Deep blue-slate background with purple undertones */
|
||||
--background: oklch(0.16 0.028 260);
|
||||
--foreground: oklch(0.98 0.008 260);
|
||||
|
||||
/* Cards with slightly lighter blue-slate */
|
||||
--card: oklch(0.21 0.032 260);
|
||||
--card-foreground: oklch(0.98 0.008 260);
|
||||
|
||||
/* Popovers with medium depth */
|
||||
--popover: oklch(0.24 0.035 260);
|
||||
--popover-foreground: oklch(0.98 0.008 260);
|
||||
|
||||
/* Vibrant blue-purple primary */
|
||||
--primary: oklch(0.62 0.18 270);
|
||||
--primary-foreground: oklch(0.99 0.005 260);
|
||||
|
||||
/* Secondary with blue-slate tone */
|
||||
--secondary: oklch(0.27 0.038 260);
|
||||
--secondary-foreground: oklch(0.98 0.008 260);
|
||||
|
||||
/* Muted elements */
|
||||
--muted: oklch(0.25 0.035 260);
|
||||
--muted-foreground: oklch(0.66 0.025 260);
|
||||
|
||||
/* Accent with purple-blue blend */
|
||||
--accent: oklch(0.36 0.065 268);
|
||||
--accent-foreground: oklch(0.98 0.008 260);
|
||||
|
||||
/* Destructive red with good contrast */
|
||||
--destructive: oklch(0.62 0.22 25);
|
||||
--destructive-foreground: oklch(0.99 0.005 260);
|
||||
|
||||
/* Subtle borders and inputs */
|
||||
--border: oklch(0.32 0.025 260);
|
||||
--input: oklch(0.30 0.030 260);
|
||||
--ring: oklch(0.62 0.18 270);
|
||||
|
||||
/* Chart colors with blue-purple harmony */
|
||||
--chart-1: oklch(0.58 0.18 270);
|
||||
--chart-2: oklch(0.62 0.16 245);
|
||||
--chart-3: oklch(0.68 0.15 290);
|
||||
--chart-4: oklch(0.60 0.20 260);
|
||||
--chart-5: oklch(0.65 0.14 280);
|
||||
|
||||
/* Sidebar with slightly different depth */
|
||||
--sidebar: oklch(0.18 0.030 260);
|
||||
--sidebar-foreground: oklch(0.97 0.008 260);
|
||||
--sidebar-primary: oklch(0.60 0.17 270);
|
||||
--sidebar-primary-foreground: oklch(0.99 0.005 260);
|
||||
--sidebar-accent: oklch(0.26 0.038 260);
|
||||
--sidebar-accent-foreground: oklch(0.98 0.008 260);
|
||||
--sidebar-border: oklch(0.30 0.025 260);
|
||||
--sidebar-ring: oklch(0.58 0.17 270);
|
||||
}
|
||||
|
||||
@theme inline {
|
||||
--radius-sm: calc(var(--radius) - 4px);
|
||||
--radius-md: calc(var(--radius) - 2px);
|
||||
--radius-lg: var(--radius);
|
||||
--radius-xl: calc(var(--radius) + 4px);
|
||||
--color-background: var(--background);
|
||||
--color-foreground: var(--foreground);
|
||||
--color-card: var(--card);
|
||||
--color-card-foreground: var(--card-foreground);
|
||||
--color-popover: var(--popover);
|
||||
--color-popover-foreground: var(--popover-foreground);
|
||||
--color-primary: var(--primary);
|
||||
--color-primary-foreground: var(--primary-foreground);
|
||||
--color-secondary: var(--secondary);
|
||||
--color-secondary-foreground: var(--secondary-foreground);
|
||||
--color-muted: var(--muted);
|
||||
--color-muted-foreground: var(--muted-foreground);
|
||||
--color-accent: var(--accent);
|
||||
--color-accent-foreground: var(--accent-foreground);
|
||||
--color-destructive: var(--destructive);
|
||||
--color-border: var(--border);
|
||||
--color-input: var(--input);
|
||||
--color-ring: var(--ring);
|
||||
--color-chart-1: var(--chart-1);
|
||||
--color-chart-2: var(--chart-2);
|
||||
--color-chart-3: var(--chart-3);
|
||||
--color-chart-4: var(--chart-4);
|
||||
--color-chart-5: var(--chart-5);
|
||||
--color-sidebar: var(--sidebar);
|
||||
--color-sidebar-foreground: var(--sidebar-foreground);
|
||||
--color-sidebar-primary: var(--sidebar-primary);
|
||||
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
||||
--color-sidebar-accent: var(--sidebar-accent);
|
||||
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
||||
--color-sidebar-border: var(--sidebar-border);
|
||||
--color-sidebar-ring: var(--sidebar-ring);
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" class="dark">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Moonlight</title>
|
||||
<base href="/" />
|
||||
<link rel="preload" id="webassembly" />
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=fallback" />
|
||||
<link rel="stylesheet" href="style.min.css" />
|
||||
<script type="importmap"></script>
|
||||
|
||||
<script>
|
||||
window.frontendConfig = {
|
||||
STYLE_TAG_ID: 'theme-variables',
|
||||
configuration: {},
|
||||
|
||||
applyTheme: function(cssContent) {
|
||||
// Find or create the style tag
|
||||
let styleTag = document.getElementById(this.STYLE_TAG_ID);
|
||||
|
||||
if (!styleTag) {
|
||||
styleTag = document.createElement('style');
|
||||
styleTag.id = this.STYLE_TAG_ID;
|
||||
document.head.appendChild(styleTag);
|
||||
}
|
||||
|
||||
// Update the style tag content
|
||||
styleTag.textContent = cssContent;
|
||||
},
|
||||
|
||||
reloadConfiguration: function (){
|
||||
try {
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', '/api/frontend/config', false);
|
||||
xhr.send(null);
|
||||
|
||||
if (xhr.status === 200) {
|
||||
this.configuration = JSON.parse(xhr.responseText);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to load initial theme:', error);
|
||||
}
|
||||
},
|
||||
|
||||
getConfiguration: function (){
|
||||
return this.configuration;
|
||||
},
|
||||
|
||||
reload: function () {
|
||||
this.reloadConfiguration();
|
||||
|
||||
document.title = this.configuration.name;
|
||||
this.applyTheme(this.configuration.themeCss);
|
||||
}
|
||||
};
|
||||
|
||||
window.frontendConfig.reload();
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body class="bg-background text-foreground">
|
||||
<div id="app">
|
||||
<div class="h-screen w-full flex items-center justify-center">
|
||||
|
||||
<div class="flex min-w-0 flex-1 flex-col items-center justify-center gap-3 rounded-lg border-dashed p-6 text-center text-balance md:p-12">
|
||||
<div class="flex max-w-sm flex-col items-center gap-2 text-center">
|
||||
<div class="flex shrink-0 items-center justify-center [&_svg]:pointer-events-none [&_svg]:shrink-0 bg-muted text-foreground size-10 rounded-lg [&_svg:not([class*='size-'])]:size-6">
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
|
||||
class="lucide lucide-zap-icon lucide-zap size-6">
|
||||
<path d="M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z"/>
|
||||
</svg>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-lg font-medium tracking-tight">
|
||||
Loading application
|
||||
</div>
|
||||
<div class="flex w-full max-w-sm min-w-0 flex-col items-center gap-4 text-sm text-balance">
|
||||
|
||||
<div class="bg-primary/20 w-full relative h-2 overflow-hidden rounded-full">
|
||||
<div class="bg-primary h-full w-[var(--blazor-load-percentage,0)] flex-1 transition-all">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="blazor-error-ui">
|
||||
An unhandled error has occurred.
|
||||
<a href="." class="reload">Reload</a>
|
||||
<span class="dismiss">🗙</span>
|
||||
</div>
|
||||
|
||||
<script src="/_content/ShadcnBlazor/interop.js" defer></script>
|
||||
<script src="/_content/ShadcnBlazor.Extras/interop.js" defer></script>
|
||||
<script src="/_content/ShadcnBlazor.Extras/codemirror-bundle.js" defer></script>
|
||||
<script src="_framework/blazor.webassembly#[.{fingerprint}].js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,21 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using PluginTemplate.Shared.Http.Requests;
|
||||
using PluginTemplate.Shared.Http.Responses;
|
||||
|
||||
namespace PluginTemplate.Api.Http.Controllers;
|
||||
|
||||
[Authorize]
|
||||
[ApiController]
|
||||
[Route("api/form")]
|
||||
public class FormController : Controller
|
||||
{
|
||||
[HttpPost]
|
||||
public async Task<ActionResult<FormResultDto>> PostAsync([FromBody] FormSubmitDto dto)
|
||||
{
|
||||
return new FormResultDto()
|
||||
{
|
||||
Result = dto.TextField.Replace(" ", string.Empty)
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Razor">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<SupportedPlatform Include="browser"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Moonlight.Api" Version="2.1.0">
|
||||
<ExcludeAssets>content;contentfiles</ExcludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Configuration\" />
|
||||
<Folder Include="Database\Entities\" />
|
||||
<Folder Include="Database\Migrations\" />
|
||||
<Folder Include="Helpers\" />
|
||||
<Folder Include="Implementations\" />
|
||||
<Folder Include="Interfaces\" />
|
||||
<Folder Include="Mappers\" />
|
||||
<Folder Include="Models\" />
|
||||
<Folder Include="Services\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\PluginTemplate.Shared\PluginTemplate.Shared.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
21
content/PluginTemplate/PluginTemplate.Api/Startup.cs
Normal file
21
content/PluginTemplate/PluginTemplate.Api/Startup.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Moonlight.Api;
|
||||
using SimplePlugin.Abstractions;
|
||||
using SerializationContext = PluginTemplate.Shared.SerializationContext;
|
||||
|
||||
namespace PluginTemplate.Api;
|
||||
|
||||
[PluginModule]
|
||||
public class Startup : MoonlightPlugin
|
||||
{
|
||||
public override void PreBuild(WebApplicationBuilder builder)
|
||||
{
|
||||
builder.Services.AddControllers()
|
||||
.AddApplicationPart(typeof(Startup).Assembly)
|
||||
.AddJsonOptions(options =>
|
||||
{
|
||||
options.JsonSerializerOptions.TypeInfoResolverChain.Add(SerializationContext.Default);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using LucideBlazor;
|
||||
using Moonlight.Frontend.Interfaces;
|
||||
using Moonlight.Frontend.Models;
|
||||
|
||||
namespace PluginTemplate.Frontend.Implementations;
|
||||
|
||||
public class PermissionProvider : IPermissionProvider
|
||||
{
|
||||
public Task<PermissionCategory[]> GetPermissionsAsync()
|
||||
{
|
||||
return Task.FromResult<PermissionCategory[]>([
|
||||
new PermissionCategory("Demo", typeof(SparklesIcon), [
|
||||
new Permission("Permissions:Demo", "Demo", "Access to demo page")
|
||||
])
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using LucideBlazor;
|
||||
using Moonlight.Frontend.Interfaces;
|
||||
using Moonlight.Frontend.Models;
|
||||
|
||||
namespace PluginTemplate.Frontend.Implementations;
|
||||
|
||||
public sealed class SidebarProvider : ISidebarProvider
|
||||
{
|
||||
public Task<SidebarItem[]> GetItemsAsync()
|
||||
{
|
||||
return Task.FromResult<SidebarItem[]>([
|
||||
new SidebarItem()
|
||||
{
|
||||
Group = "Demo",
|
||||
Name = "Demo",
|
||||
IconType = typeof(SparklesIcon),
|
||||
Path = "/demo"
|
||||
}
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Razor">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<SupportedPlatform Include="browser"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Moonlight.Frontend" Version="2.1.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="wwwroot\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\PluginTemplate.Shared\PluginTemplate.Shared.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="Styles/*" Pack="true" PackagePath="Styles/" />
|
||||
<None Include="Moonlight.Frontend.targets" Pack="true" PackagePath="build\PluginTemplate.Frontend.targets" />
|
||||
<None Include="Moonlight.Frontend.targets" Pack="true" PackagePath="buildTransitive\PluginTemplate.Frontend.targets" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,15 @@
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<PluginTemplateCssClassDir Condition="'$(PluginTemplateCssClassDir)' == ''">
|
||||
$(MSBuildProjectDirectory)\bin\PluginTemplate
|
||||
</PluginTemplateCssClassDir>
|
||||
</PropertyGroup>
|
||||
|
||||
<Target Name="PluginTemplate_CopyContents" BeforeTargets="Build">
|
||||
<ItemGroup>
|
||||
<Files Include="$(MSBuildThisFileDirectory)..\Styles\**\*" />
|
||||
</ItemGroup>
|
||||
|
||||
<Copy SourceFiles="@(Files)" DestinationFolder="$(PluginTemplateCssClassDir)" SkipUnchangedFiles="true" />
|
||||
</Target>
|
||||
</Project>
|
||||
29
content/PluginTemplate/PluginTemplate.Frontend/Startup.cs
Normal file
29
content/PluginTemplate/PluginTemplate.Frontend/Startup.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Moonlight.Frontend;
|
||||
using Moonlight.Frontend.Configuration;
|
||||
using Moonlight.Frontend.Interfaces;
|
||||
using PluginTemplate.Frontend.Implementations;
|
||||
using SimplePlugin.Abstractions;
|
||||
|
||||
namespace PluginTemplate.Frontend;
|
||||
|
||||
[PluginModule]
|
||||
public sealed class Startup : MoonlightPlugin
|
||||
{
|
||||
public override void PreBuild(WebAssemblyHostBuilder builder)
|
||||
{
|
||||
builder.Services.AddSingleton<IPermissionProvider, PermissionProvider>();
|
||||
builder.Services.AddSingleton<ISidebarProvider, SidebarProvider>();
|
||||
|
||||
builder.Services.Configure<NavigationAssemblyOptions>(options =>
|
||||
{
|
||||
options.Assemblies.Add(typeof(Startup).Assembly);
|
||||
});
|
||||
}
|
||||
|
||||
public override void PostBuild(WebAssemblyHost application)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
@using Moonlight.Frontend.Helpers
|
||||
@using PluginTemplate.Shared
|
||||
@using PluginTemplate.Shared.Http.Requests
|
||||
@using PluginTemplate.Shared.Http.Responses
|
||||
@using ShadcnBlazor.Buttons
|
||||
@using ShadcnBlazor.Dialogs
|
||||
@using ShadcnBlazor.Extras.AlertDialogs
|
||||
@using ShadcnBlazor.Extras.Forms
|
||||
@using ShadcnBlazor.Fields
|
||||
@using ShadcnBlazor.Inputs
|
||||
|
||||
@inherits ShadcnBlazor.Extras.Dialogs.DialogBase
|
||||
|
||||
@inject HttpClient HttpClient
|
||||
@inject AlertDialogService AlertDialogService
|
||||
|
||||
<DialogHeader>
|
||||
<DialogTitle>Example Form</DialogTitle>
|
||||
<DialogDescription>This forms removes all spaces from the input</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
<EnhancedEditForm @ref="Form" OnValidSubmit="OnSubmit" Model="Dto">
|
||||
<DataAnnotationsValidator/>
|
||||
|
||||
<FieldSet>
|
||||
<FormValidationSummary/>
|
||||
|
||||
<FieldGroup>
|
||||
<Field>
|
||||
<FieldLabel for="formInput">Form Input</FieldLabel>
|
||||
<TextInputField id="formInput" @bind-Value="Dto.TextField"/>
|
||||
<FieldDescription>Input you want to remove the spaces from</FieldDescription>
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
</FieldSet>
|
||||
</EnhancedEditForm>
|
||||
|
||||
<DialogFooter>
|
||||
<Button @onclick="() => Form.SubmitAsync()">Submit</Button>
|
||||
<DialogClose/>
|
||||
</DialogFooter>
|
||||
|
||||
@code
|
||||
{
|
||||
private FormSubmitDto Dto = new();
|
||||
private EnhancedEditForm Form;
|
||||
|
||||
private async Task<bool> OnSubmit(EditContext editContext, ValidationMessageStore validationMessageStore)
|
||||
{
|
||||
var response = await HttpClient.PostAsJsonAsync(
|
||||
"api/form",
|
||||
Dto,
|
||||
SerializationContext.Default.Options
|
||||
);
|
||||
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
var data = await response.Content.ReadFromJsonAsync<FormResultDto>(
|
||||
SerializationContext.Default.Options
|
||||
);
|
||||
|
||||
if (data == null)
|
||||
return true;
|
||||
|
||||
await AlertDialogService.InfoAsync("Result", data.Result);
|
||||
|
||||
await CloseAsync();
|
||||
return true;
|
||||
}
|
||||
|
||||
await ProblemDetailsHelper.HandleProblemDetailsAsync(response, Dto, validationMessageStore);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
@page "/demo"
|
||||
@using LucideBlazor
|
||||
@using PluginTemplate.Frontend.UI.Components
|
||||
@using ShadcnBlazor.Buttons
|
||||
@using ShadcnBlazor.Cards
|
||||
@using ShadcnBlazor.Extras.Dialogs
|
||||
|
||||
@inject DialogService DialogService
|
||||
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-5"
|
||||
>
|
||||
<Card ClassName="col-span-1">
|
||||
<CardHeader>
|
||||
<CardTitle>Demo</CardTitle>
|
||||
<CardDescription>A cool demo page</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
You successfully used the plugin template to create your moonlight plugin :)
|
||||
</CardContent>
|
||||
<CardFooter>
|
||||
<Button>
|
||||
<Slot>
|
||||
<a @attributes="context" href="https://moonlightpa.nl/dev">
|
||||
<ExternalLinkIcon />
|
||||
Visit documentation
|
||||
</a>
|
||||
</Slot>
|
||||
</Button>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
<Card>
|
||||
<CardContent>
|
||||
<Button @onclick="LaunchFormAsync" Variant="ButtonVariant.Outline">
|
||||
Open Form
|
||||
</Button>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
@code
|
||||
{
|
||||
private async Task LaunchFormAsync()
|
||||
=> await DialogService.LaunchAsync<FormDialog>();
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
@using System.Net.Http
|
||||
@using System.Net.Http.Json
|
||||
@using Microsoft.AspNetCore.Components.Forms
|
||||
@using Microsoft.AspNetCore.Components.Routing
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@using Microsoft.AspNetCore.Components.Web.Virtualization
|
||||
@@ -0,0 +1,10 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace PluginTemplate.Shared.Http.Requests;
|
||||
|
||||
public class FormSubmitDto
|
||||
{
|
||||
[Required]
|
||||
[MaxLength(32)]
|
||||
public string TextField { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace PluginTemplate.Shared.Http.Responses;
|
||||
|
||||
public class FormResultDto
|
||||
{
|
||||
public string Result { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,15 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using PluginTemplate.Shared.Http.Requests;
|
||||
using PluginTemplate.Shared.Http.Responses;
|
||||
|
||||
namespace PluginTemplate.Shared;
|
||||
|
||||
[JsonSerializable(typeof(FormSubmitDto))]
|
||||
[JsonSerializable(typeof(FormResultDto))]
|
||||
|
||||
[JsonSourceGenerationOptions(JsonSerializerDefaults.Web)]
|
||||
public partial class SerializationContext : JsonSerializerContext
|
||||
{
|
||||
|
||||
}
|
||||
9
content/PluginTemplate/PluginTemplate.slnx
Normal file
9
content/PluginTemplate/PluginTemplate.slnx
Normal file
@@ -0,0 +1,9 @@
|
||||
<Solution>
|
||||
<Folder Name="/Hosts/">
|
||||
<Project Path="Hosts/PluginTemplate.Api.Host/PluginTemplate.Api.Host.csproj" />
|
||||
<Project Path="Hosts/PluginTemplate.Frontend.Host/PluginTemplate.Frontend.Host.csproj" />
|
||||
</Folder>
|
||||
<Project Path="PluginTemplate.Api/PluginTemplate.Api.csproj" />
|
||||
<Project Path="PluginTemplate.Frontend/PluginTemplate.Frontend.csproj" />
|
||||
<Project Path="PluginTemplate.Shared/PluginTemplate.Shared.csproj" />
|
||||
</Solution>
|
||||
Reference in New Issue
Block a user