diff --git a/.github/workflows/azure-static-web-apps-orange-water-0badfae10.yml b/.github/workflows/azure-static-web-apps-orange-water-0badfae10.yml new file mode 100644 index 0000000..cca802c --- /dev/null +++ b/.github/workflows/azure-static-web-apps-orange-water-0badfae10.yml @@ -0,0 +1,74 @@ +name: Azure Static Web Apps CI/CD + +on: + push: + branches: + - main + pull_request: + types: [opened, synchronize, reopened, closed] + branches: + - main + +jobs: + build_and_deploy_job: + if: github.event_name == 'push' || + (github.event_name == 'pull_request' && github.event.action != 'closed') + runs-on: ubuntu-latest + name: Build and Deploy Job + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + with: + submodules: true + lfs: false + + - name: Setup .NET SDK + uses: actions/setup-dotnet@v3 + with: + dotnet-version: '8.0.x' + + - name: Cache NuGet packages + uses: actions/cache@v3 + with: + path: ~/.nuget/packages + key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj') }} + restore-keys: | + ${{ runner.os }}-nuget- + + - name: Cache .NET Workload Packs + uses: actions/cache@v3 + with: + path: ~/.dotnet + key: ${{ runner.os }}-dotnet-workloads-${{ hashFiles('**/*.csproj') }} + restore-keys: | + ${{ runner.os }}-dotnet-workloads- + + - name: Install WASM Tools workload + run: dotnet workload install wasm-tools + + - name: Publish Blazor WebAssembly (AOT + Brotli) + run: dotnet publish ./Client -c Release /p:BlazorWebAssemblyEnableAOT=true /p:CompressionEnabled=true + + - name: Build and Deploy to Azure Static Web Apps + uses: Azure/static-web-apps-deploy@v1 + with: + azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_ORANGE_WATER_0BADFAE10 }} + repo_token: ${{ secrets.GITHUB_TOKEN }} + action: upload + app_location: ./Client + api_location: Api + output_location: wwwroot + + close_pull_request_job: + if: github.event_name == 'pull_request' && + github.event.action == 'closed' + runs-on: ubuntu-latest + name: Close Pull Request Job + + steps: + - name: Close Preview + uses: Azure/static-web-apps-deploy@v1 + with: + azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_ORANGE_WATER_0BADFAE10 }} + action: close diff --git a/Api/WeatherForecastFunction.cs b/Api/Functions/WeatherForecastFunction.cs similarity index 98% rename from Api/WeatherForecastFunction.cs rename to Api/Functions/WeatherForecastFunction.cs index 706badb..2875c93 100644 --- a/Api/WeatherForecastFunction.cs +++ b/Api/Functions/WeatherForecastFunction.cs @@ -4,7 +4,7 @@ using Microsoft.Azure.Functions.Worker.Http; using Microsoft.Extensions.Logging; -namespace Api +namespace Api.Functions { public class HttpTrigger { diff --git a/Client/Client.csproj b/Client/Client.csproj index 2578370..74e8346 100644 --- a/Client/Client.csproj +++ b/Client/Client.csproj @@ -4,17 +4,31 @@ net8.0 enable enable - BlazorApp.Client + BlazorApp.Client + + + - - + - diff --git a/Client/Pages/Home.razor b/Client/Pages/Home.razor index dfcdf75..b60adb9 100644 --- a/Client/Pages/Home.razor +++ b/Client/Pages/Home.razor @@ -2,6 +2,4 @@ Home -

Hello, world!

- -Welcome to your new app. \ No newline at end of file +

Welcome to Bill Me App.

diff --git a/Client/staticwebapp.config.json b/Client/staticwebapp.config.json index 4a1bb1f..e094983 100644 --- a/Client/staticwebapp.config.json +++ b/Client/staticwebapp.config.json @@ -1,5 +1,5 @@ { - "navigationFallback": { - "rewrite": "/index.html" - } -} \ No newline at end of file + "navigationFallback": { + "rewrite": "/index.html" + } +} diff --git a/Client/wwwroot/index.html b/Client/wwwroot/index.html index efc9613..d67715f 100644 --- a/Client/wwwroot/index.html +++ b/Client/wwwroot/index.html @@ -10,6 +10,10 @@ + + + + @@ -26,7 +30,8 @@ Reload 🗙 - + + diff --git a/Client/wwwroot/manifest.webmanifest b/Client/wwwroot/manifest.webmanifest new file mode 100644 index 0000000..96edfce --- /dev/null +++ b/Client/wwwroot/manifest.webmanifest @@ -0,0 +1,22 @@ +{ + "name": "BillMeApp", + "short_name": "BillMeApp", + "id": "./", + "start_url": "./", + "display": "standalone", + "background_color": "#ffffff", + "theme_color": "#03173d", + "prefer_related_applications": false, + "icons": [ + { + "src": "icon-512.png", + "type": "image/png", + "sizes": "512x512" + }, + { + "src": "icon-192.png", + "type": "image/png", + "sizes": "192x192" + } + ] +} diff --git a/Client/wwwroot/service-worker.js b/Client/wwwroot/service-worker.js new file mode 100644 index 0000000..fe614da --- /dev/null +++ b/Client/wwwroot/service-worker.js @@ -0,0 +1,4 @@ +// In development, always fetch from the network and do not enable offline support. +// This is because caching would make development more difficult (changes would not +// be reflected on the first load after each change). +self.addEventListener('fetch', () => { }); diff --git a/Client/wwwroot/service-worker.published.js b/Client/wwwroot/service-worker.published.js new file mode 100644 index 0000000..1f7f543 --- /dev/null +++ b/Client/wwwroot/service-worker.published.js @@ -0,0 +1,55 @@ +// Caution! Be sure you understand the caveats before publishing an application with +// offline support. See https://aka.ms/blazor-offline-considerations + +self.importScripts('./service-worker-assets.js'); +self.addEventListener('install', event => event.waitUntil(onInstall(event))); +self.addEventListener('activate', event => event.waitUntil(onActivate(event))); +self.addEventListener('fetch', event => event.respondWith(onFetch(event))); + +const cacheNamePrefix = 'offline-cache-'; +const cacheName = `${cacheNamePrefix}${self.assetsManifest.version}`; +const offlineAssetsInclude = [ /\.dll$/, /\.pdb$/, /\.wasm/, /\.html/, /\.js$/, /\.json$/, /\.css$/, /\.woff$/, /\.png$/, /\.jpe?g$/, /\.gif$/, /\.ico$/, /\.blat$/, /\.dat$/ ]; +const offlineAssetsExclude = [ /^service-worker\.js$/ ]; + +// Replace with your base path if you are hosting on a subfolder. Ensure there is a trailing '/'. +const base = "/"; +const baseUrl = new URL(base, self.origin); +const manifestUrlList = self.assetsManifest.assets.map(asset => new URL(asset.url, baseUrl).href); + +async function onInstall(event) { + console.info('Service worker: Install'); + + // Fetch and cache all matching items from the assets manifest + const assetsRequests = self.assetsManifest.assets + .filter(asset => offlineAssetsInclude.some(pattern => pattern.test(asset.url))) + .filter(asset => !offlineAssetsExclude.some(pattern => pattern.test(asset.url))) + .map(asset => new Request(asset.url, { integrity: asset.hash, cache: 'no-cache' })); + await caches.open(cacheName).then(cache => cache.addAll(assetsRequests)); +} + +async function onActivate(event) { + console.info('Service worker: Activate'); + + // Delete unused caches + const cacheKeys = await caches.keys(); + await Promise.all(cacheKeys + .filter(key => key.startsWith(cacheNamePrefix) && key !== cacheName) + .map(key => caches.delete(key))); +} + +async function onFetch(event) { + let cachedResponse = null; + if (event.request.method === 'GET') { + // For all navigation requests, try to serve index.html from cache, + // unless that request is for an offline resource. + // If you need some URLs to be server-rendered, edit the following check to exclude those URLs + const shouldServeIndexHtml = event.request.mode === 'navigate' + && !manifestUrlList.some(url => url === event.request.url); + + const request = shouldServeIndexHtml ? 'index.html' : event.request; + const cache = await caches.open(cacheName); + cachedResponse = await cache.match(request); + } + + return cachedResponse || fetch(event.request); +} diff --git a/README.md b/README.md index f739d39..fa811de 100644 --- a/README.md +++ b/README.md @@ -1,65 +1 @@ -# Blazor Starter Application - -This template contains an example .NET 8 [Blazor WebAssembly](https://docs.microsoft.com/aspnet/core/blazor/?view=aspnetcore-6.0#blazor-webassembly) client application, a .NET 8 C# [Azure Functions](https://docs.microsoft.com/azure/azure-functions/functions-overview), and a C# class library with shared code. - -## Getting Started - -1. Create a repository from the [GitHub template](https://docs.github.com/en/enterprise/2.22/user/github/creating-cloning-and-archiving-repositories/creating-a-repository-from-a-template) and then clone it locally to your machine. - -1. In the **Api** folder, copy `local.settings.example.json` to `local.settings.json` - -1. Continue using either Visual Studio or Visual Studio Code. - -### Visual Studio 2022 - -Once you clone the project, open the solution in the latest release of [Visual Studio 2022](https://visualstudio.microsoft.com/vs/) with the Azure workload installed, and follow these steps: - -1. Right-click on the solution and select **Configure Startup Projects...**. - -1. Select **Multiple startup projects** and set the following actions for each project: - - *Api* - **Start** - - *Client* - **Start** - - *Shared* - None - -1. Press **F5** to launch both the client application and the Functions API app. - -### Visual Studio Code with Azure Static Web Apps CLI for a better development experience (Optional) - -1. Install (or update) the [Azure Static Web Apps CLI](https://www.npmjs.com/package/@azure/static-web-apps-cli) and [Azure Functions Core Tools CLI](https://www.npmjs.com/package/azure-functions-core-tools). - -1. Open the folder in Visual Studio Code. - -1. Delete file `Client/wwwroot/appsettings.Development.json` - -1. In the VS Code terminal, run the following command to start the Static Web Apps CLI, along with the Blazor WebAssembly client application and the Functions API app: - - In the Client folder, run: - ```bash - dotnet run - ``` - - In the API folder, run: - ```bash - func start - ``` - - In another terminal, run: - ```bash - swa start http://localhost:5000 --api-location http://localhost:7071 - ``` - - The Static Web Apps CLI (`swa`) starts a proxy on port 4280 that will forward static site requests to the Blazor server on port 5000 and requests to the `/api` endpoint to the Functions server. - -1. Open a browser and navigate to the Static Web Apps CLI's address at `http://localhost:4280`. You'll be able to access both the client application and the Functions API app in this single address. When you navigate to the "Fetch Data" page, you'll see the data returned by the Functions API app. - -1. Enter Ctrl-C to stop the Static Web Apps CLI. - -## Template Structure - -- **Client**: The Blazor WebAssembly sample application -- **Api**: A C# Azure Functions API, which the Blazor application will call -- **Shared**: A C# class library with a shared data model between the Blazor and Functions application - -## Deploy to Azure Static Web Apps - -This application can be deployed to [Azure Static Web Apps](https://docs.microsoft.com/azure/static-web-apps), to learn how, check out [our quickstart guide](https://aka.ms/blazor-swa/quickstart). +This is Bill Me App.