├── .gitignore ├── .vscode ├── launch.json └── tasks.json ├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.md ├── SECURITY.md ├── SUPPORT.md ├── appsettings.secret.json ├── blazor-graphql.sln ├── blazorui ├── App.razor ├── GraphQLAPIClient.cs ├── GraphQLRequest.cs ├── GraphQLResponse.cs ├── Pages │ ├── Authentication.razor │ ├── GraphqlFetcher.razor │ ├── GraphqlFetcher.razor.cs │ └── Index.razor ├── Program.cs ├── Properties │ └── launchSettings.json ├── Shared │ ├── LoginDisplay.razor │ ├── MainLayout.razor │ ├── MainLayout.razor.css │ ├── NavMenu.razor │ ├── NavMenu.razor.css │ ├── RedirectToLogin.razor │ └── SurveyPrompt.razor ├── _Imports.razor ├── blazorui.csproj └── wwwroot │ ├── appsettings.json │ ├── css │ ├── app.css │ ├── bootstrap │ │ ├── bootstrap.min.css │ │ └── bootstrap.min.css.map │ └── open-iconic │ │ ├── FONT-LICENSE │ │ ├── ICON-LICENSE │ │ ├── README.md │ │ └── font │ │ ├── css │ │ └── open-iconic-bootstrap.min.css │ │ └── fonts │ │ ├── open-iconic.eot │ │ ├── open-iconic.otf │ │ ├── open-iconic.svg │ │ ├── open-iconic.ttf │ │ └── open-iconic.woff │ ├── favicon.ico │ ├── index.html │ └── sample-data │ └── weather.json ├── docs └── create_static_webapp.png └── graphqlapi ├── .config └── dotnet-tools.json ├── Models ├── BackboneElement.cs ├── Coding.cs ├── DomainResource.cs ├── Element.cs ├── Extension.cs ├── Identifier.cs ├── IdentifierType.cs ├── IdentifierUse.cs ├── Meta.cs ├── Narrative.cs ├── NarrativeStatus.cs ├── Period.cs ├── PublicationStatus.cs ├── Questionnaire.cs ├── QuestionnaireItem.cs ├── QuestionnaireItemType.cs └── Resource.cs ├── Program.cs ├── Properties ├── launchSettings.json ├── serviceDependencies.json └── serviceDependencies.local.json ├── Resolvers └── Query.cs ├── Services ├── FhirServiceInMemory.cs └── IFhirService.cs ├── Startup.cs ├── appsettings.Development.json ├── appsettings.json └── graphqlapi.csproj /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Ww][Ii][Nn]32/ 27 | [Aa][Rr][Mm]/ 28 | [Aa][Rr][Mm]64/ 29 | bld/ 30 | [Bb]in/ 31 | [Oo]bj/ 32 | [Ll]og/ 33 | [Ll]ogs/ 34 | 35 | # Visual Studio 2015/2017 cache/options directory 36 | .vs/ 37 | # Uncomment if you have tasks that create the project's static files in wwwroot 38 | #wwwroot/ 39 | 40 | # Visual Studio 2017 auto generated files 41 | Generated\ Files/ 42 | 43 | # MSTest test Results 44 | [Tt]est[Rr]esult*/ 45 | [Bb]uild[Ll]og.* 46 | 47 | # NUnit 48 | *.VisualState.xml 49 | TestResult.xml 50 | nunit-*.xml 51 | 52 | # Build Results of an ATL Project 53 | [Dd]ebugPS/ 54 | [Rr]eleasePS/ 55 | dlldata.c 56 | 57 | # Benchmark Results 58 | BenchmarkDotNet.Artifacts/ 59 | 60 | # .NET Core 61 | project.lock.json 62 | project.fragment.lock.json 63 | artifacts/ 64 | 65 | # ASP.NET Scaffolding 66 | ScaffoldingReadMe.txt 67 | 68 | # StyleCop 69 | StyleCopReport.xml 70 | 71 | # Files built by Visual Studio 72 | *_i.c 73 | *_p.c 74 | *_h.h 75 | *.ilk 76 | *.meta 77 | *.obj 78 | *.iobj 79 | *.pch 80 | *.pdb 81 | *.ipdb 82 | *.pgc 83 | *.pgd 84 | *.rsp 85 | *.sbr 86 | *.tlb 87 | *.tli 88 | *.tlh 89 | *.tmp 90 | *.tmp_proj 91 | *_wpftmp.csproj 92 | *.log 93 | *.tlog 94 | *.vspscc 95 | *.vssscc 96 | .builds 97 | *.pidb 98 | *.svclog 99 | *.scc 100 | 101 | # Chutzpah Test files 102 | _Chutzpah* 103 | 104 | # Visual C++ cache files 105 | ipch/ 106 | *.aps 107 | *.ncb 108 | *.opendb 109 | *.opensdf 110 | *.sdf 111 | *.cachefile 112 | *.VC.db 113 | *.VC.VC.opendb 114 | 115 | # Visual Studio profiler 116 | *.psess 117 | *.vsp 118 | *.vspx 119 | *.sap 120 | 121 | # Visual Studio Trace Files 122 | *.e2e 123 | 124 | # TFS 2012 Local Workspace 125 | $tf/ 126 | 127 | # Guidance Automation Toolkit 128 | *.gpState 129 | 130 | # ReSharper is a .NET coding add-in 131 | _ReSharper*/ 132 | *.[Rr]e[Ss]harper 133 | *.DotSettings.user 134 | 135 | # TeamCity is a build add-in 136 | _TeamCity* 137 | 138 | # DotCover is a Code Coverage Tool 139 | *.dotCover 140 | 141 | # AxoCover is a Code Coverage Tool 142 | .axoCover/* 143 | !.axoCover/settings.json 144 | 145 | # Coverlet is a free, cross platform Code Coverage Tool 146 | coverage*.json 147 | coverage*.xml 148 | coverage*.info 149 | 150 | # Visual Studio code coverage results 151 | *.coverage 152 | *.coveragexml 153 | 154 | # NCrunch 155 | _NCrunch_* 156 | .*crunch*.local.xml 157 | nCrunchTemp_* 158 | 159 | # MightyMoose 160 | *.mm.* 161 | AutoTest.Net/ 162 | 163 | # Web workbench (sass) 164 | .sass-cache/ 165 | 166 | # Installshield output folder 167 | [Ee]xpress/ 168 | 169 | # DocProject is a documentation generator add-in 170 | DocProject/buildhelp/ 171 | DocProject/Help/*.HxT 172 | DocProject/Help/*.HxC 173 | DocProject/Help/*.hhc 174 | DocProject/Help/*.hhk 175 | DocProject/Help/*.hhp 176 | DocProject/Help/Html2 177 | DocProject/Help/html 178 | 179 | # Click-Once directory 180 | publish/ 181 | 182 | # Publish Web Output 183 | *.[Pp]ublish.xml 184 | *.azurePubxml 185 | # Note: Comment the next line if you want to checkin your web deploy settings, 186 | # but database connection strings (with potential passwords) will be unencrypted 187 | *.pubxml 188 | *.publishproj 189 | 190 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 191 | # checkin your Azure Web App publish settings, but sensitive information contained 192 | # in these scripts will be unencrypted 193 | PublishScripts/ 194 | 195 | # NuGet Packages 196 | *.nupkg 197 | # NuGet Symbol Packages 198 | *.snupkg 199 | # The packages folder can be ignored because of Package Restore 200 | **/[Pp]ackages/* 201 | # except build/, which is used as an MSBuild target. 202 | !**/[Pp]ackages/build/ 203 | # Uncomment if necessary however generally it will be regenerated when needed 204 | #!**/[Pp]ackages/repositories.config 205 | # NuGet v3's project.json files produces more ignorable files 206 | *.nuget.props 207 | *.nuget.targets 208 | 209 | # Nuget personal access tokens and Credentials 210 | nuget.config 211 | 212 | # Microsoft Azure Build Output 213 | csx/ 214 | *.build.csdef 215 | 216 | # Microsoft Azure Emulator 217 | ecf/ 218 | rcf/ 219 | 220 | # Windows Store app package directories and files 221 | AppPackages/ 222 | BundleArtifacts/ 223 | Package.StoreAssociation.xml 224 | _pkginfo.txt 225 | *.appx 226 | *.appxbundle 227 | *.appxupload 228 | 229 | # Visual Studio cache files 230 | # files ending in .cache can be ignored 231 | *.[Cc]ache 232 | # but keep track of directories ending in .cache 233 | !?*.[Cc]ache/ 234 | 235 | # Others 236 | ClientBin/ 237 | ~$* 238 | *~ 239 | *.dbmdl 240 | *.dbproj.schemaview 241 | *.jfm 242 | *.pfx 243 | *.publishsettings 244 | orleans.codegen.cs 245 | 246 | # Including strong name files can present a security risk 247 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 248 | #*.snk 249 | 250 | # Since there are multiple workflows, uncomment next line to ignore bower_components 251 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 252 | #bower_components/ 253 | 254 | # RIA/Silverlight projects 255 | Generated_Code/ 256 | 257 | # Backup & report files from converting an old project file 258 | # to a newer Visual Studio version. Backup files are not needed, 259 | # because we have git ;-) 260 | _UpgradeReport_Files/ 261 | Backup*/ 262 | UpgradeLog*.XML 263 | UpgradeLog*.htm 264 | ServiceFabricBackup/ 265 | *.rptproj.bak 266 | 267 | # SQL Server files 268 | *.mdf 269 | *.ldf 270 | *.ndf 271 | 272 | # Business Intelligence projects 273 | *.rdl.data 274 | *.bim.layout 275 | *.bim_*.settings 276 | *.rptproj.rsuser 277 | *- [Bb]ackup.rdl 278 | *- [Bb]ackup ([0-9]).rdl 279 | *- [Bb]ackup ([0-9][0-9]).rdl 280 | 281 | # Microsoft Fakes 282 | FakesAssemblies/ 283 | 284 | # GhostDoc plugin setting file 285 | *.GhostDoc.xml 286 | 287 | # Node.js Tools for Visual Studio 288 | .ntvs_analysis.dat 289 | node_modules/ 290 | 291 | # Visual Studio 6 build log 292 | *.plg 293 | 294 | # Visual Studio 6 workspace options file 295 | *.opt 296 | 297 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 298 | *.vbw 299 | 300 | # Visual Studio LightSwitch build output 301 | **/*.HTMLClient/GeneratedArtifacts 302 | **/*.DesktopClient/GeneratedArtifacts 303 | **/*.DesktopClient/ModelManifest.xml 304 | **/*.Server/GeneratedArtifacts 305 | **/*.Server/ModelManifest.xml 306 | _Pvt_Extensions 307 | 308 | # Paket dependency manager 309 | .paket/paket.exe 310 | paket-files/ 311 | 312 | # FAKE - F# Make 313 | .fake/ 314 | 315 | # CodeRush personal settings 316 | .cr/personal 317 | 318 | # Python Tools for Visual Studio (PTVS) 319 | __pycache__/ 320 | *.pyc 321 | 322 | # Cake - Uncomment if you are using it 323 | # tools/** 324 | # !tools/packages.config 325 | 326 | # Tabs Studio 327 | *.tss 328 | 329 | # Telerik's JustMock configuration file 330 | *.jmconfig 331 | 332 | # BizTalk build output 333 | *.btp.cs 334 | *.btm.cs 335 | *.odx.cs 336 | *.xsd.cs 337 | 338 | # OpenCover UI analysis results 339 | OpenCover/ 340 | 341 | # Azure Stream Analytics local run output 342 | ASALocalRun/ 343 | 344 | # MSBuild Binary and Structured Log 345 | *.binlog 346 | 347 | # NVidia Nsight GPU debugger configuration file 348 | *.nvuser 349 | 350 | # MFractors (Xamarin productivity tool) working folder 351 | .mfractor/ 352 | 353 | # Local History for Visual Studio 354 | .localhistory/ 355 | 356 | # BeatPulse healthcheck temp database 357 | healthchecksdb 358 | 359 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 360 | MigrationBackup/ 361 | 362 | # Ionide (cross platform F# VS Code tools) working folder 363 | .ionide/ 364 | 365 | # Fody - auto-generated XML schema 366 | FodyWeavers.xsd 367 | 368 | # VS Code files for those working on multiple tools 369 | .vscode/* 370 | !.vscode/settings.json 371 | !.vscode/tasks.json 372 | !.vscode/launch.json 373 | !.vscode/extensions.json 374 | *.code-workspace 375 | 376 | # Local History for Visual Studio Code 377 | .history/ 378 | 379 | # Windows Installer files from build outputs 380 | *.cab 381 | *.msi 382 | *.msix 383 | *.msm 384 | *.msp 385 | 386 | # JetBrains Rider 387 | .idea/ 388 | *.sln.iml -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | // Use IntelliSense to find out which attributes exist for C# debugging 6 | // Use hover for the description of the existing attributes 7 | // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md 8 | "name": ".NET Core Launch (web)", 9 | "type": "coreclr", 10 | "request": "launch", 11 | "preLaunchTask": "build", 12 | // If you have changed target frameworks, make sure to update the program path. 13 | "program": "${workspaceFolder}/graphqlapi/bin/Debug/net5.0/graphqlapi.dll", 14 | "args": [], 15 | "cwd": "${workspaceFolder}/graphqlapi", 16 | "stopAtEntry": false, 17 | // Enable launching a web browser when ASP.NET Core starts. For more information: https://aka.ms/VSCode-CS-LaunchJson-WebBrowser 18 | "serverReadyAction": { 19 | "action": "openExternally", 20 | "pattern": "\\bNow listening on:\\s+(https?://\\S+)" 21 | }, 22 | "env": { 23 | "ASPNETCORE_ENVIRONMENT": "Development" 24 | }, 25 | "sourceFileMap": { 26 | "/Views": "${workspaceFolder}/Views" 27 | } 28 | }, 29 | { 30 | "name": ".NET Core Attach", 31 | "type": "coreclr", 32 | "request": "attach" 33 | } 34 | ] 35 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "label": "build", 6 | "command": "dotnet", 7 | "type": "process", 8 | "args": [ 9 | "build", 10 | "${workspaceFolder}/graphqlapi/graphqlapi.csproj", 11 | "/property:GenerateFullPaths=true", 12 | "/consoleloggerparameters:NoSummary" 13 | ], 14 | "problemMatcher": "$msCompile" 15 | }, 16 | { 17 | "label": "publish", 18 | "command": "dotnet", 19 | "type": "process", 20 | "args": [ 21 | "publish", 22 | "${workspaceFolder}/graphqlapi/graphqlapi.csproj", 23 | "/property:GenerateFullPaths=true", 24 | "/consoleloggerparameters:NoSummary" 25 | ], 26 | "problemMatcher": "$msCompile" 27 | }, 28 | { 29 | "label": "watch", 30 | "command": "dotnet", 31 | "type": "process", 32 | "args": [ 33 | "watch", 34 | "run", 35 | "${workspaceFolder}/graphqlapi/graphqlapi.csproj", 36 | "/property:GenerateFullPaths=true", 37 | "/consoleloggerparameters:NoSummary" 38 | ], 39 | "problemMatcher": "$msCompile" 40 | } 41 | ] 42 | } -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Microsoft Open Source Code of Conduct 2 | 3 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 4 | 5 | Resources: 6 | 7 | - [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/) 8 | - [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) 9 | - Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Microsoft Corporation. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Project 2 | 3 | ## How did this template come about? 4 | 5 | We wanted to create a one stop tutorial for anyone wanting to create their own Blazor WASM application backed by GraphQL / EntityFramework. 6 | 7 | > **Go [check out](https://github.com/microsoft/emerging-opportunities/blob/main/MotherBox/Readme.md) our internal tool that inspired us to create this template** 8 | 9 | > This repo contains sample code for creating a secure app with the following stack. 10 | > UI: Blazor Web Assembly (WASM) 11 | > API: GraphQL based on the HotChocolate package 12 | 13 | [What is a GraphQL?](https://github.com/microsoft/emerging-opportunities/tree/main/MotherBox/GraphQL) 14 | 15 | > In this app the UI uses Azure AD for auth. The API is protected and only accepts authorized requests with a valid Oaauth token. 16 | 17 | 18 | ## Steps to deploy in your Azure subscription 19 | 20 | ## Azure AD 21 | 22 | > Go and read more about [Authentication and Authorization in AzureAd](https://github.com/microsoft/emerging-opportunities/tree/main/.NET/Authentication) 23 | 24 | ### Create API App Registration 25 | 26 | 1. Name: _blazor-graphql-api_ 27 | 2. Select Multi or Single Tenant (we used single tenant for our example) 28 | 3. Redirect URL: 29 | - https://localhost:/.auth/login/aad/callback 30 | - https://blazorgraphqlapi.azurewebsites.net/.auth/login/aad/callbackClick 31 | 4. "Certificates and Secrets" and add a new secret. **Please store it somewhere safe** 32 | 5. Click Expose API 33 | - Add a new scope: leave the api url the same (ex: api://x8xxd1e-141c-xxxxxx-32aba6f12dxx) 34 | - scope: graphql.all 35 | - Who can consent: Admins and users 36 | - Fill out consent title and descripton for both Admin and User 37 | 38 | 39 | _Things you will need for further setup (copy somewhere)_ 40 | 41 | **Client ID** 42 | 43 | **Client Secret** 44 | 45 | **API Url** (ex: api://18715d1e-141c-445e-999c-432aba6f12d2)) 46 | 47 | **Tenant ID** 48 | 49 | 50 | ### Create UI App Registration 51 | 52 | Name: (*for example*) 53 | blazor-graphql-ui 54 | 55 | Accounts in this organization (single or multi) 56 | 57 | Redirect URLs: 58 | - (Single Page App): https://localhost:5001/authentication/callback 59 | - https://blazorgraphqlui.azurewebsites.net/authentication/callback 60 | 61 | Click on Authentication 62 | - Check both ID Token and Access Token boxes 63 | - Click **+ Add a Platform** and add Single Page Application and put down the callback url (for example, https://localhost:44362/authentication/login-callback) 64 | 65 | _If you want to separately test out the API with out the blazor portion you can use apps like *Postman*._ 66 | 67 | - Add Web Redirect URL (for example, https://oauth.pstmn.io/v1/callback) 68 | - *If you have Multifactor Auth you must use Authorize wtih PKCE in the postman app.* 69 | 70 | **Add API Permissions** 71 | 72 | * In the portal click on API Permissions 73 | * Click + Add a New Permission 74 | * Click on "My APIs" 75 | * Click on the API you exposed earlier (for example: blazor-graphql-api) 76 | * Check the checkbox for 'graphql.all' 77 | * Click 'Add Permission' 78 | 79 | _Things you will need for further setup (copy somewhere)_ 80 | 81 | **Client ID** 82 | 83 | **Tenant ID** 84 | 85 | ## Tie the UI and the API registration 86 | 87 | Now go back to the App Registration you created for the API. 88 | 89 | Click on Expose an API 90 | 91 | And add the UI app's client ID to the list of authorized Apps.' 92 | 93 | ### Blazor App 94 | 95 | From Nothing: 96 | 97 | * Create new VS Solution with a Blazor App with Microsoft Identity Provider Auth. 98 | ---- 99 | * Open the solution file 100 | * Edit the app-settings.json file with your client id and tenant 101 | EX (Note below values are not valid and need to be replaced with valid values 102 | ```json 103 | "APIBaseURL": "https://blazorgraphqlapi.azurewebsites.net", 104 | "APIScope": "api://1872d2/graphql.all", 105 | "AzureAd": { 106 | "Authority": "https://login.microsoftonline.com/5df988bf-86f1-41af-91ab-2d7cd011db47", 107 | "ClientId": "2c92f0fd-70bf-468a-83d7-94f8a3074650", 108 | "ValidateAuthority": true 109 | } 110 | } 111 | ``` 112 | 113 | * Run locally (Press F5) 114 | If your app runs on https://localhost:44362 then you should be able to login. If your app runs on another port or runs in http then please change the blazor-graphql app registration's reply_url.' 115 | 116 | * Create an Azure Static Blob site 117 | * Enable static website hosting: https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blob-static-website-how-to?tabs=azure-portal#enable-static-website-hosting 118 | * Configure the Azure Static Blob Site 119 | * Deploy to a static blob site 120 | 121 | ### Azure Storage Static Site 122 |
123 | Follow these instructions to create a static site: https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blob-static-website 124 | 125 | Example name used in this starter kit: _blazorgraphqlui_ 126 | 127 | 128 | ### Azure App Service (.NET Core, Windows) 129 |
130 | Follow these instructions to create a .NET Windows site: https://docs.microsoft.com/en-us/azure/app-service/quickstart-arm-template?pivots=platform-linux 131 | 132 | Example name used in this starter kit: _blazorgraphqlapi_ 133 | 134 | ### Azure Static Web App 135 |
136 | 137 | Azure Static Web Apps provides two options for deployment configuration: 138 | - Github 139 | - Other 140 | 141 | #### Github 142 | When choosing the 'Github' deployment option, Azure Static Web Apps will add a Github action to your selected repository. This will automatically build and deploy your site whenever a code change is pushed. 143 | 144 | Browse to the Azure Portal and create a new Azure Static Web App using this [quick start guide](https://docs.microsoft.com/en-us/azure/static-web-apps/get-started-portal?tabs=vanilla-javascript#create-a-static-web-app) 145 | 146 | > ** Note that you are not deploying an API to Azure Functions with this starter kit ** 147 | 148 | Your configuration should look similar to the following: 149 | 150 | ![Create Static WebApp](./docs/create_static_webapp.png) 151 | 152 | 1. Click "Review+Create" to review your settings 153 | 1. Click "Create" 154 | 155 | #### Other 156 | When choosing the 'Other' deployment option, Azure Static Web Apps will provide you with a Deployment Token. This can be used to establish a secure connection from other devops systems. 157 | 158 | In this example, we will be using Azure DevOps. 159 | 160 | Follow this guide to configure [Deployment from Azure DevOps](https://docs.microsoft.com/en-us/azure/static-web-apps/publish-devops#create-a-static-web-app) 161 | 162 | After step 4, your YAML should look like the following: 163 | 164 | ```YAML 165 | trigger: 166 | - main 167 | 168 | pool: 169 | vmImage: ubuntu-latest 170 | 171 | steps: 172 | - checkout: self 173 | submodules: true 174 | - task: AzureStaticWebApp@0 175 | inputs: 176 | app_location: 'blazorui' 177 | api_location: '' 178 | output_location: 'wwwroot' 179 | azure_static_web_apps_api_token: $(deployment_token) 180 | ``` 181 | 182 |
183 | 184 | * Use Azure Active Directory (AAD) for authentication: https://docs.microsoft.com/en-us/aspnet/core/blazor/security/webassembly/standalone-with-azure-active-directory?view=aspnetcore-5.0 185 | 186 | ### .Net Core Api (with GraphQL) 187 | 188 | * Create new VS Solution with a .Net Core Api with Microsoft Identity Provider Auth. 189 | ---- 190 | * Open the solution file 191 | * Edit the app-settings.json file with your client id and tenant 192 | EX (Note below values are not valid and need to be replaced with valid values 193 | ```json 194 | { 195 | "AzureAd": { 196 | "Instance": "https://login.microsoftonline.com/", 197 | "Domain": ".onmicrosoft.com", 198 | "TenantId": "", 199 | "ClientId": "", 200 | "ClientSecret": "" 201 | } 202 | } 203 | ``` 204 | ## Additional Resources 205 | * What is Blazor - https://docs.microsoft.com/en-us/aspnet/core/blazor/?view=aspnetcore-5.0 206 | 207 | * Build your first Blazor app - https://dotnet.microsoft.com/learn/aspnet/blazor-tutorial/intro 208 | 209 | ## Contributing 210 | 211 | This project welcomes contributions and suggestions. Most contributions require you to agree to a 212 | Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us 213 | the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com. 214 | 215 | When you submit a pull request, a CLA bot will automatically determine whether you need to provide 216 | a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions 217 | provided by the bot. You will only need to do this once across all repos using our CLA. 218 | 219 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 220 | For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or 221 | contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. 222 | 223 | ## Trademarks 224 | 225 | This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft 226 | trademarks or logos is subject to and must follow 227 | [Microsoft's Trademark & Brand Guidelines](https://www.microsoft.com/en-us/legal/intellectualproperty/trademarks/usage/general). 228 | Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship. 229 | Any use of third-party trademarks or logos are subject to those third-party's policies. 230 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Security 4 | 5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). 6 | 7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)), please report it to us as described below. 8 | 9 | ## Reporting Security Issues 10 | 11 | **Please do not report security vulnerabilities through public GitHub issues.** 12 | 13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report). 14 | 15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc). 16 | 17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc). 18 | 19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: 20 | 21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) 22 | * Full paths of source file(s) related to the manifestation of the issue 23 | * The location of the affected source code (tag/branch/commit or direct URL) 24 | * Any special configuration required to reproduce the issue 25 | * Step-by-step instructions to reproduce the issue 26 | * Proof-of-concept or exploit code (if possible) 27 | * Impact of the issue, including how an attacker might exploit the issue 28 | 29 | This information will help us triage your report more quickly. 30 | 31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://microsoft.com/msrc/bounty) page for more details about our active programs. 32 | 33 | ## Preferred Languages 34 | 35 | We prefer all communications to be in English. 36 | 37 | ## Policy 38 | 39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd). 40 | 41 | -------------------------------------------------------------------------------- /SUPPORT.md: -------------------------------------------------------------------------------- 1 | # TODO: The maintainer of this repo has not yet edited this file 2 | 3 | **REPO OWNER**: Do you want Customer Service & Support (CSS) support for this product/project? 4 | 5 | - **No CSS support:** Fill out this template with information about how to file issues and get help. 6 | - **Yes CSS support:** Fill out an intake form at [aka.ms/spot](https://aka.ms/spot). CSS will work with/help you to determine next steps. More details also available at [aka.ms/onboardsupport](https://aka.ms/onboardsupport). 7 | - **Not sure?** Fill out a SPOT intake as though the answer were "Yes". CSS will help you decide. 8 | 9 | *Then remove this first heading from this SUPPORT.MD file before publishing your repo.* 10 | 11 | # Support 12 | 13 | ## How to file issues and get help 14 | 15 | This project uses GitHub Issues to track bugs and feature requests. Please search the existing 16 | issues before filing new issues to avoid duplicates. For new issues, file your bug or 17 | feature request as a new Issue. 18 | 19 | For help and questions about using this project, please **REPO MAINTAINER: INSERT INSTRUCTIONS HERE 20 | FOR HOW TO ENGAGE REPO OWNERS OR COMMUNITY FOR HELP. COULD BE A STACK OVERFLOW TAG OR OTHER 21 | CHANNEL. WHERE WILL YOU HELP PEOPLE?**. 22 | 23 | ## Microsoft Support Policy 24 | 25 | Support for this **PROJECT or PRODUCT** is limited to the resources listed above. 26 | -------------------------------------------------------------------------------- /appsettings.secret.json: -------------------------------------------------------------------------------- 1 | { 2 | /* 3 | The following identity settings need to be configured 4 | before the project can be successfully executed. 5 | For more info see https://aka.ms/dotnet-template-ms-identity-platform 6 | */ 7 | "APIBaseURL": "https://motherboxapi.azurewebsites.net", 8 | "oldAPIBaseURL": "https://blazorgraphqlapi.azurewebsites.net", 9 | "APIScope": "api://45f2de13-6574-4b0b-b3eb-c94ee2e731de/access.data", 10 | "oldAPIScope": "api://1872d2/graphql.all", 11 | "AzureAd": { 12 | "Authority": "https://login.microsoftonline.com/72f988bf-86f1-41af-91ab-2d7cd011db47", 13 | "ClientId": "2b92f0fd-70bf-468a-83d7-94f8a3074650", 14 | "ValidateAuthority": true 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /blazor-graphql.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.31424.327 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "blazorui", "blazorui\blazorui.csproj", "{D9CCE19A-A3DD-4DFF-8588-372FB9CA5F3E}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{4A0F6DD7-AD3B-467C-9588-52BC0AB0AA9D}" 9 | ProjectSection(SolutionItems) = preProject 10 | .gitignore = .gitignore 11 | README.md = README.md 12 | EndProjectSection 13 | EndProject 14 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "graphqlapi", "graphqlapi\graphqlapi.csproj", "{91E8F377-83D4-4E3D-95FC-CF49CCBCBE1F}" 15 | EndProject 16 | Global 17 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 18 | Debug|Any CPU = Debug|Any CPU 19 | Release|Any CPU = Release|Any CPU 20 | EndGlobalSection 21 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 22 | {D9CCE19A-A3DD-4DFF-8588-372FB9CA5F3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {D9CCE19A-A3DD-4DFF-8588-372FB9CA5F3E}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {D9CCE19A-A3DD-4DFF-8588-372FB9CA5F3E}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {D9CCE19A-A3DD-4DFF-8588-372FB9CA5F3E}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {91E8F377-83D4-4E3D-95FC-CF49CCBCBE1F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {91E8F377-83D4-4E3D-95FC-CF49CCBCBE1F}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {91E8F377-83D4-4E3D-95FC-CF49CCBCBE1F}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {91E8F377-83D4-4E3D-95FC-CF49CCBCBE1F}.Release|Any CPU.Build.0 = Release|Any CPU 30 | EndGlobalSection 31 | GlobalSection(SolutionProperties) = preSolution 32 | HideSolutionNode = FALSE 33 | EndGlobalSection 34 | GlobalSection(ExtensibilityGlobals) = postSolution 35 | SolutionGuid = {2A9AF6D5-8250-4F2E-A51A-04B0202CF79F} 36 | EndGlobalSection 37 | EndGlobal 38 | -------------------------------------------------------------------------------- /blazorui/App.razor: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | @if (!context.User.Identity.IsAuthenticated) 7 | { 8 | 9 | } 10 | else 11 | { 12 |

You are not authorized to access this resource.

13 | } 14 |
15 |
16 |
17 | 18 | 19 |

Sorry, there's nothing at this address.

20 |
21 |
22 |
23 |
24 | -------------------------------------------------------------------------------- /blazorui/GraphQLAPIClient.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components.WebAssembly.Authentication; 2 | using System.Net.Http; 3 | using System.Net.Http.Json; 4 | using System.Text; 5 | using System.Text.Json; 6 | using System.Threading.Tasks; 7 | 8 | namespace blazorui 9 | { 10 | public class GraphQLAPIClient 11 | { 12 | private readonly HttpClient _httpClient; 13 | 14 | public GraphQLAPIClient(HttpClient httpClient) 15 | { 16 | _httpClient = httpClient; 17 | } 18 | 19 | public async Task GetHelloworld() 20 | { 21 | GraphQLRequest request = new GraphQLRequest(_httpClient) 22 | { 23 | OperationName = "welcome", 24 | Query = @"{ 25 | welcome{} 26 | }" 27 | }; 28 | 29 | string response = (await request.PostAsync()).RootElement.GetProperty("welcome").GetString(); 30 | 31 | return response; 32 | } 33 | 34 | } 35 | } -------------------------------------------------------------------------------- /blazorui/GraphQLRequest.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components.WebAssembly.Authentication; 2 | using System.Collections.Generic; 3 | using System.Net.Http; 4 | using System.Text; 5 | using System.Text.Json; 6 | using System.Text.Json.Serialization; 7 | using System.Threading.Tasks; 8 | 9 | namespace blazorui 10 | { 11 | internal class GraphQLRequest 12 | { 13 | private HttpClient _httpClient; 14 | 15 | [JsonPropertyName("OperationName")] 16 | public string OperationName { get; set; } 17 | 18 | [JsonPropertyName("query")] 19 | public string Query { get; set; } 20 | 21 | [JsonPropertyName("variables")] 22 | public Dictionary Variables { get; set; } 23 | 24 | public GraphQLRequest(HttpClient httpClient) 25 | { 26 | _httpClient = httpClient; 27 | } 28 | 29 | public async Task PostAsync() 30 | { 31 | var query = new StringContent( 32 | JsonSerializer.Serialize(this), 33 | Encoding.UTF8, 34 | "application/json"); 35 | JsonDocument data = null; 36 | try 37 | { 38 | var response = await _httpClient.PostAsync("graphql", query); 39 | if (response.IsSuccessStatusCode) 40 | { 41 | var stream = await response.Content.ReadAsStreamAsync(); 42 | var gq = await JsonSerializer.DeserializeAsync(stream); 43 | data = gq.Data; 44 | 45 | 46 | } 47 | } 48 | catch (AccessTokenNotAvailableException exception) 49 | { 50 | exception.Redirect(); 51 | } 52 | 53 | 54 | return data; 55 | 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /blazorui/GraphQLResponse.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | using System.Text.Json; 3 | 4 | namespace blazorui 5 | { 6 | internal class GraphQLResponse 7 | { 8 | [JsonPropertyName("data")] 9 | public JsonDocument Data { get; set; } 10 | 11 | } 12 | } -------------------------------------------------------------------------------- /blazorui/Pages/Authentication.razor: -------------------------------------------------------------------------------- 1 | @page "/authentication/{action}" 2 | @using Microsoft.AspNetCore.Components.WebAssembly.Authentication 3 | 4 | 5 | @code{ 6 | [Parameter] public string Action { get; set; } 7 | } 8 | -------------------------------------------------------------------------------- /blazorui/Pages/GraphqlFetcher.razor: -------------------------------------------------------------------------------- 1 | @page "/call" 2 |

Access Token

3 |

@AccessToken

4 |

GraphqlFetcher

5 | @if (graphqlcallfinished) 6 | { 7 |

Done

8 | } 9 | else 10 | { 11 |

Still happening....

12 | } 13 | 14 | GraphQL Response: 15 |

16 | @graphqlresponse 17 | @if(Errors.Length > 0) { 18 | @Errors 19 | } 20 |

-------------------------------------------------------------------------------- /blazorui/Pages/GraphqlFetcher.razor.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components; 2 | using Microsoft.AspNetCore.Authorization; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | using Microsoft.AspNetCore.Components.WebAssembly.Authentication; 8 | 9 | namespace blazorui.Pages 10 | { 11 | [Authorize] 12 | public partial class GraphqlFetcher 13 | { 14 | [Inject] 15 | private GraphQLAPIClient graphqlclient { get; set; } 16 | [Inject] 17 | IAccessTokenProvider TokenProvider { get; set; } 18 | private string graphqlresponse { get; set; } 19 | private bool graphqlcallfinished { get; set; } 20 | private string Errors { get; set; } 21 | private string AccessToken { get; set; } 22 | 23 | protected override async Task OnInitializedAsync() 24 | { 25 | 26 | AccessToken = ""; 27 | Errors = ""; 28 | graphqlresponse = ""; 29 | var accessTokenResult = await TokenProvider.RequestAccessToken(); 30 | if (accessTokenResult.TryGetToken(out var token)) 31 | { 32 | AccessToken = token.Value; 33 | } 34 | 35 | 36 | graphqlcallfinished = false; 37 | try 38 | { 39 | graphqlresponse = await graphqlclient.GetHelloworld(); 40 | } 41 | catch (ApplicationException e) 42 | { 43 | Errors = e.Message; 44 | } 45 | graphqlcallfinished = true; 46 | 47 | } 48 | 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /blazorui/Pages/Index.razor: -------------------------------------------------------------------------------- 1 | @page "/" 2 | 3 |

Blaze ahead with GraphQL!

4 | 5 | Fetch Data from GraphQL 6 | 7 | 8 | -------------------------------------------------------------------------------- /blazorui/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components.WebAssembly.Authentication; 2 | using Microsoft.AspNetCore.Components.WebAssembly.Hosting; 3 | using Microsoft.Extensions.Configuration; 4 | using Microsoft.Extensions.DependencyInjection; 5 | using Microsoft.Extensions.Logging; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Net.Http; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | 12 | namespace blazorui 13 | { 14 | public class Program 15 | { 16 | public static async Task Main(string[] args) 17 | { 18 | var builder = WebAssemblyHostBuilder.CreateDefault(args); 19 | builder.RootComponents.Add("#app"); 20 | 21 | 22 | 23 | builder.Services.AddMsalAuthentication(options => 24 | { 25 | builder.Configuration.Bind("AzureAd", options.ProviderOptions.Authentication); 26 | options.ProviderOptions.LoginMode = "redirect"; 27 | options.ProviderOptions.DefaultAccessTokenScopes.Add("openid"); 28 | options.ProviderOptions.DefaultAccessTokenScopes.Add(builder.Configuration["APIScope"]); 29 | 30 | }); 31 | 32 | //builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) }); 33 | 34 | builder.Services.AddHttpClient( 35 | client => client.BaseAddress = new Uri(builder.Configuration["APIBaseURL"])) 36 | .AddHttpMessageHandler(sp => sp.GetRequiredService() 37 | .ConfigureHandler( 38 | authorizedUrls: new[] { builder.Configuration["APIBaseURL"] }, 39 | scopes: new[] { builder.Configuration["APIScope"] })); 40 | 41 | 42 | 43 | await builder.Build().RunAsync(); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /blazorui/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:41976", 7 | "sslPort": 44362 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | }, 17 | "jsWebView2Debugging": false, 18 | "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}" 19 | }, 20 | "blazorui": { 21 | "commandName": "Project", 22 | "launchBrowser": true, 23 | "environmentVariables": { 24 | "ASPNETCORE_ENVIRONMENT": "Development" 25 | }, 26 | "dotnetRunMessages": "true", 27 | "applicationUrl": "https://localhost:5001;http://localhost:5000", 28 | "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}" 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /blazorui/Shared/LoginDisplay.razor: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Components.Authorization 2 | @using Microsoft.AspNetCore.Components.WebAssembly.Authentication 3 | 4 | @inject NavigationManager Navigation 5 | @inject SignOutSessionStateManager SignOutManager 6 | 7 | 8 | 9 | Hello, @context.User.Identity.Name! 10 | 11 | 12 | 13 | Log in 14 | 15 | 16 | 17 | @code{ 18 | private async Task BeginLogout(MouseEventArgs args) 19 | { 20 | await SignOutManager.SetSignOutState(); 21 | Navigation.NavigateTo("authentication/logout"); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /blazorui/Shared/MainLayout.razor: -------------------------------------------------------------------------------- 1 | @inherits LayoutComponentBase 2 | 3 |
4 | 7 | 8 |
9 |
10 | 11 | About 12 |
13 | 14 |
15 | @Body 16 |
17 |
18 |
19 | -------------------------------------------------------------------------------- /blazorui/Shared/MainLayout.razor.css: -------------------------------------------------------------------------------- 1 | .page { 2 | position: relative; 3 | display: flex; 4 | flex-direction: column; 5 | } 6 | 7 | .main { 8 | flex: 1; 9 | } 10 | 11 | .sidebar { 12 | background-image: linear-gradient(180deg, rgb(5, 39, 103) 0%, #3a0647 70%); 13 | } 14 | 15 | .top-row { 16 | background-color: #f7f7f7; 17 | border-bottom: 1px solid #d6d5d5; 18 | justify-content: flex-end; 19 | height: 3.5rem; 20 | display: flex; 21 | align-items: center; 22 | } 23 | 24 | .top-row ::deep a, .top-row .btn-link { 25 | white-space: nowrap; 26 | margin-left: 1.5rem; 27 | } 28 | 29 | .top-row a:first-child { 30 | overflow: hidden; 31 | text-overflow: ellipsis; 32 | } 33 | 34 | @media (max-width: 640.98px) { 35 | .top-row:not(.auth) { 36 | display: none; 37 | } 38 | 39 | .top-row.auth { 40 | justify-content: space-between; 41 | } 42 | 43 | .top-row a, .top-row .btn-link { 44 | margin-left: 0; 45 | } 46 | } 47 | 48 | @media (min-width: 641px) { 49 | .page { 50 | flex-direction: row; 51 | } 52 | 53 | .sidebar { 54 | width: 250px; 55 | height: 100vh; 56 | position: sticky; 57 | top: 0; 58 | } 59 | 60 | .top-row { 61 | position: sticky; 62 | top: 0; 63 | z-index: 1; 64 | } 65 | 66 | .main > div { 67 | padding-left: 2rem !important; 68 | padding-right: 1.5rem !important; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /blazorui/Shared/NavMenu.razor: -------------------------------------------------------------------------------- 1 |  7 | 8 |
9 | 21 |
22 | 23 | @code { 24 | private bool collapseNavMenu = true; 25 | 26 | private string NavMenuCssClass => collapseNavMenu ? "collapse" : null; 27 | 28 | private void ToggleNavMenu() 29 | { 30 | collapseNavMenu = !collapseNavMenu; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /blazorui/Shared/NavMenu.razor.css: -------------------------------------------------------------------------------- 1 | .navbar-toggler { 2 | background-color: rgba(255, 255, 255, 0.1); 3 | } 4 | 5 | .top-row { 6 | height: 3.5rem; 7 | background-color: rgba(0,0,0,0.4); 8 | } 9 | 10 | .navbar-brand { 11 | font-size: 1.1rem; 12 | } 13 | 14 | .oi { 15 | width: 2rem; 16 | font-size: 1.1rem; 17 | vertical-align: text-top; 18 | top: -2px; 19 | } 20 | 21 | .nav-item { 22 | font-size: 0.9rem; 23 | padding-bottom: 0.5rem; 24 | } 25 | 26 | .nav-item:first-of-type { 27 | padding-top: 1rem; 28 | } 29 | 30 | .nav-item:last-of-type { 31 | padding-bottom: 1rem; 32 | } 33 | 34 | .nav-item ::deep a { 35 | color: #d7d7d7; 36 | border-radius: 4px; 37 | height: 3rem; 38 | display: flex; 39 | align-items: center; 40 | line-height: 3rem; 41 | } 42 | 43 | .nav-item ::deep a.active { 44 | background-color: rgba(255,255,255,0.25); 45 | color: white; 46 | } 47 | 48 | .nav-item ::deep a:hover { 49 | background-color: rgba(255,255,255,0.1); 50 | color: white; 51 | } 52 | 53 | @media (min-width: 641px) { 54 | .navbar-toggler { 55 | display: none; 56 | } 57 | 58 | .collapse { 59 | /* Never collapse the sidebar for wide screens */ 60 | display: block; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /blazorui/Shared/RedirectToLogin.razor: -------------------------------------------------------------------------------- 1 | @inject NavigationManager Navigation 2 | @using Microsoft.AspNetCore.Components.WebAssembly.Authentication 3 | @code { 4 | protected override void OnInitialized() 5 | { 6 | Navigation.NavigateTo($"authentication/login?returnUrl={Uri.EscapeDataString(Navigation.Uri)}"); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /blazorui/Shared/SurveyPrompt.razor: -------------------------------------------------------------------------------- 1 |  11 | 12 | @code { 13 | // Demonstrates how a parent component can supply parameters 14 | [Parameter] 15 | public string Title { get; set; } 16 | } 17 | -------------------------------------------------------------------------------- /blazorui/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using System.Net.Http 2 | @using System.Net.Http.Json 3 | @using Microsoft.AspNetCore.Components.Authorization 4 | @using Microsoft.AspNetCore.Components.Forms 5 | @using Microsoft.AspNetCore.Components.Routing 6 | @using Microsoft.AspNetCore.Components.Web 7 | @using Microsoft.AspNetCore.Components.Web.Virtualization 8 | @using Microsoft.AspNetCore.Components.WebAssembly.Http 9 | @using Microsoft.JSInterop 10 | @using blazorui 11 | @using blazorui.Shared 12 | -------------------------------------------------------------------------------- /blazorui/blazorui.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net5.0 5 | 341fcb12-d703-44d4-8d34-e1feb4f02bb1 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /blazorui/wwwroot/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | /* 3 | The following identity settings need to be configured 4 | before the project can be successfully executed. 5 | For more info see https://aka.ms/dotnet-template-ms-identity-platform 6 | */ 7 | "APIBaseURL": "https://blazorgraphqlapi.azurewebsites.net", 8 | "APIScope": "api://1872d2/graphql.all", 9 | "AzureAd": { 10 | "Authority": "https://login.microsoftonline.com/7f-86f1-41af-91ab-2d7cd0", 11 | "ClientId": "2b9-70bf-468a-83d7-94f8a3074650", 12 | "ValidateAuthority": true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /blazorui/wwwroot/css/app.css: -------------------------------------------------------------------------------- 1 | @import url('open-iconic/font/css/open-iconic-bootstrap.min.css'); 2 | 3 | html, body { 4 | font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; 5 | } 6 | 7 | a, .btn-link { 8 | color: #0366d6; 9 | } 10 | 11 | .btn-primary { 12 | color: #fff; 13 | background-color: #1b6ec2; 14 | border-color: #1861ac; 15 | } 16 | 17 | .content { 18 | padding-top: 1.1rem; 19 | } 20 | 21 | .valid.modified:not([type=checkbox]) { 22 | outline: 1px solid #26b050; 23 | } 24 | 25 | .invalid { 26 | outline: 1px solid red; 27 | } 28 | 29 | .validation-message { 30 | color: red; 31 | } 32 | 33 | #blazor-error-ui { 34 | background: lightyellow; 35 | bottom: 0; 36 | box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2); 37 | display: none; 38 | left: 0; 39 | padding: 0.6rem 1.25rem 0.7rem 1.25rem; 40 | position: fixed; 41 | width: 100%; 42 | z-index: 1000; 43 | } 44 | 45 | #blazor-error-ui .dismiss { 46 | cursor: pointer; 47 | position: absolute; 48 | right: 0.75rem; 49 | top: 0.5rem; 50 | } 51 | -------------------------------------------------------------------------------- /blazorui/wwwroot/css/open-iconic/FONT-LICENSE: -------------------------------------------------------------------------------- 1 | SIL OPEN FONT LICENSE Version 1.1 2 | 3 | Copyright (c) 2014 Waybury 4 | 5 | PREAMBLE 6 | The goals of the Open Font License (OFL) are to stimulate worldwide 7 | development of collaborative font projects, to support the font creation 8 | efforts of academic and linguistic communities, and to provide a free and 9 | open framework in which fonts may be shared and improved in partnership 10 | with others. 11 | 12 | The OFL allows the licensed fonts to be used, studied, modified and 13 | redistributed freely as long as they are not sold by themselves. The 14 | fonts, including any derivative works, can be bundled, embedded, 15 | redistributed and/or sold with any software provided that any reserved 16 | names are not used by derivative works. The fonts and derivatives, 17 | however, cannot be released under any other type of license. The 18 | requirement for fonts to remain under this license does not apply 19 | to any document created using the fonts or their derivatives. 20 | 21 | DEFINITIONS 22 | "Font Software" refers to the set of files released by the Copyright 23 | Holder(s) under this license and clearly marked as such. This may 24 | include source files, build scripts and documentation. 25 | 26 | "Reserved Font Name" refers to any names specified as such after the 27 | copyright statement(s). 28 | 29 | "Original Version" refers to the collection of Font Software components as 30 | distributed by the Copyright Holder(s). 31 | 32 | "Modified Version" refers to any derivative made by adding to, deleting, 33 | or substituting -- in part or in whole -- any of the components of the 34 | Original Version, by changing formats or by porting the Font Software to a 35 | new environment. 36 | 37 | "Author" refers to any designer, engineer, programmer, technical 38 | writer or other person who contributed to the Font Software. 39 | 40 | PERMISSION & CONDITIONS 41 | Permission is hereby granted, free of charge, to any person obtaining 42 | a copy of the Font Software, to use, study, copy, merge, embed, modify, 43 | redistribute, and sell modified and unmodified copies of the Font 44 | Software, subject to the following conditions: 45 | 46 | 1) Neither the Font Software nor any of its individual components, 47 | in Original or Modified Versions, may be sold by itself. 48 | 49 | 2) Original or Modified Versions of the Font Software may be bundled, 50 | redistributed and/or sold with any software, provided that each copy 51 | contains the above copyright notice and this license. These can be 52 | included either as stand-alone text files, human-readable headers or 53 | in the appropriate machine-readable metadata fields within text or 54 | binary files as long as those fields can be easily viewed by the user. 55 | 56 | 3) No Modified Version of the Font Software may use the Reserved Font 57 | Name(s) unless explicit written permission is granted by the corresponding 58 | Copyright Holder. This restriction only applies to the primary font name as 59 | presented to the users. 60 | 61 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font 62 | Software shall not be used to promote, endorse or advertise any 63 | Modified Version, except to acknowledge the contribution(s) of the 64 | Copyright Holder(s) and the Author(s) or with their explicit written 65 | permission. 66 | 67 | 5) The Font Software, modified or unmodified, in part or in whole, 68 | must be distributed entirely under this license, and must not be 69 | distributed under any other license. The requirement for fonts to 70 | remain under this license does not apply to any document created 71 | using the Font Software. 72 | 73 | TERMINATION 74 | This license becomes null and void if any of the above conditions are 75 | not met. 76 | 77 | DISCLAIMER 78 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 79 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 80 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 81 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE 82 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 83 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 84 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 85 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM 86 | OTHER DEALINGS IN THE FONT SOFTWARE. 87 | -------------------------------------------------------------------------------- /blazorui/wwwroot/css/open-iconic/ICON-LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Waybury 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /blazorui/wwwroot/css/open-iconic/README.md: -------------------------------------------------------------------------------- 1 | [Open Iconic v1.1.1](http://useiconic.com/open) 2 | =========== 3 | 4 | ### Open Iconic is the open source sibling of [Iconic](http://useiconic.com). It is a hyper-legible collection of 223 icons with a tiny footprint—ready to use with Bootstrap and Foundation. [View the collection](http://useiconic.com/open#icons) 5 | 6 | 7 | 8 | ## What's in Open Iconic? 9 | 10 | * 223 icons designed to be legible down to 8 pixels 11 | * Super-light SVG files - 61.8 for the entire set 12 | * SVG sprite—the modern replacement for icon fonts 13 | * Webfont (EOT, OTF, SVG, TTF, WOFF), PNG and WebP formats 14 | * Webfont stylesheets (including versions for Bootstrap and Foundation) in CSS, LESS, SCSS and Stylus formats 15 | * PNG and WebP raster images in 8px, 16px, 24px, 32px, 48px and 64px. 16 | 17 | 18 | ## Getting Started 19 | 20 | #### For code samples and everything else you need to get started with Open Iconic, check out our [Icons](http://useiconic.com/open#icons) and [Reference](http://useiconic.com/open#reference) sections. 21 | 22 | ### General Usage 23 | 24 | #### Using Open Iconic's SVGs 25 | 26 | We like SVGs and we think they're the way to display icons on the web. Since Open Iconic are just basic SVGs, we suggest you display them like you would any other image (don't forget the `alt` attribute). 27 | 28 | ``` 29 | icon name 30 | ``` 31 | 32 | #### Using Open Iconic's SVG Sprite 33 | 34 | Open Iconic also comes in a SVG sprite which allows you to display all the icons in the set with a single request. It's like an icon font, without being a hack. 35 | 36 | Adding an icon from an SVG sprite is a little different than what you're used to, but it's still a piece of cake. *Tip: To make your icons easily style able, we suggest adding a general class to the* `` *tag and a unique class name for each different icon in the* `` *tag.* 37 | 38 | ``` 39 | 40 | 41 | 42 | ``` 43 | 44 | Sizing icons only needs basic CSS. All the icons are in a square format, so just set the `` tag with equal width and height dimensions. 45 | 46 | ``` 47 | .icon { 48 | width: 16px; 49 | height: 16px; 50 | } 51 | ``` 52 | 53 | Coloring icons is even easier. All you need to do is set the `fill` rule on the `` tag. 54 | 55 | ``` 56 | .icon-account-login { 57 | fill: #f00; 58 | } 59 | ``` 60 | 61 | To learn more about SVG Sprites, read [Chris Coyier's guide](http://css-tricks.com/svg-sprites-use-better-icon-fonts/). 62 | 63 | #### Using Open Iconic's Icon Font... 64 | 65 | 66 | ##### …with Bootstrap 67 | 68 | You can find our Bootstrap stylesheets in `font/css/open-iconic-bootstrap.{css, less, scss, styl}` 69 | 70 | 71 | ``` 72 | 73 | ``` 74 | 75 | 76 | ``` 77 | 78 | ``` 79 | 80 | ##### …with Foundation 81 | 82 | You can find our Foundation stylesheets in `font/css/open-iconic-foundation.{css, less, scss, styl}` 83 | 84 | ``` 85 | 86 | ``` 87 | 88 | 89 | ``` 90 | 91 | ``` 92 | 93 | ##### …on its own 94 | 95 | You can find our default stylesheets in `font/css/open-iconic.{css, less, scss, styl}` 96 | 97 | ``` 98 | 99 | ``` 100 | 101 | ``` 102 | 103 | ``` 104 | 105 | 106 | ## License 107 | 108 | ### Icons 109 | 110 | All code (including SVG markup) is under the [MIT License](http://opensource.org/licenses/MIT). 111 | 112 | ### Fonts 113 | 114 | All fonts are under the [SIL Licensed](http://scripts.sil.org/cms/scripts/page.php?item_id=OFL_web). 115 | -------------------------------------------------------------------------------- /blazorui/wwwroot/css/open-iconic/font/css/open-iconic-bootstrap.min.css: -------------------------------------------------------------------------------- 1 | @font-face{font-family:Icons;src:url(../fonts/open-iconic.eot);src:url(../fonts/open-iconic.eot?#iconic-sm) format('embedded-opentype'),url(../fonts/open-iconic.woff) format('woff'),url(../fonts/open-iconic.ttf) format('truetype'),url(../fonts/open-iconic.otf) format('opentype'),url(../fonts/open-iconic.svg#iconic-sm) format('svg');font-weight:400;font-style:normal}.oi{position:relative;top:1px;display:inline-block;speak:none;font-family:Icons;font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.oi:empty:before{width:1em;text-align:center;box-sizing:content-box}.oi.oi-align-center:before{text-align:center}.oi.oi-align-left:before{text-align:left}.oi.oi-align-right:before{text-align:right}.oi.oi-flip-horizontal:before{-webkit-transform:scale(-1,1);-ms-transform:scale(-1,1);transform:scale(-1,1)}.oi.oi-flip-vertical:before{-webkit-transform:scale(1,-1);-ms-transform:scale(-1,1);transform:scale(1,-1)}.oi.oi-flip-horizontal-vertical:before{-webkit-transform:scale(-1,-1);-ms-transform:scale(-1,1);transform:scale(-1,-1)}.oi-account-login:before{content:'\e000'}.oi-account-logout:before{content:'\e001'}.oi-action-redo:before{content:'\e002'}.oi-action-undo:before{content:'\e003'}.oi-align-center:before{content:'\e004'}.oi-align-left:before{content:'\e005'}.oi-align-right:before{content:'\e006'}.oi-aperture:before{content:'\e007'}.oi-arrow-bottom:before{content:'\e008'}.oi-arrow-circle-bottom:before{content:'\e009'}.oi-arrow-circle-left:before{content:'\e00a'}.oi-arrow-circle-right:before{content:'\e00b'}.oi-arrow-circle-top:before{content:'\e00c'}.oi-arrow-left:before{content:'\e00d'}.oi-arrow-right:before{content:'\e00e'}.oi-arrow-thick-bottom:before{content:'\e00f'}.oi-arrow-thick-left:before{content:'\e010'}.oi-arrow-thick-right:before{content:'\e011'}.oi-arrow-thick-top:before{content:'\e012'}.oi-arrow-top:before{content:'\e013'}.oi-audio-spectrum:before{content:'\e014'}.oi-audio:before{content:'\e015'}.oi-badge:before{content:'\e016'}.oi-ban:before{content:'\e017'}.oi-bar-chart:before{content:'\e018'}.oi-basket:before{content:'\e019'}.oi-battery-empty:before{content:'\e01a'}.oi-battery-full:before{content:'\e01b'}.oi-beaker:before{content:'\e01c'}.oi-bell:before{content:'\e01d'}.oi-bluetooth:before{content:'\e01e'}.oi-bold:before{content:'\e01f'}.oi-bolt:before{content:'\e020'}.oi-book:before{content:'\e021'}.oi-bookmark:before{content:'\e022'}.oi-box:before{content:'\e023'}.oi-briefcase:before{content:'\e024'}.oi-british-pound:before{content:'\e025'}.oi-browser:before{content:'\e026'}.oi-brush:before{content:'\e027'}.oi-bug:before{content:'\e028'}.oi-bullhorn:before{content:'\e029'}.oi-calculator:before{content:'\e02a'}.oi-calendar:before{content:'\e02b'}.oi-camera-slr:before{content:'\e02c'}.oi-caret-bottom:before{content:'\e02d'}.oi-caret-left:before{content:'\e02e'}.oi-caret-right:before{content:'\e02f'}.oi-caret-top:before{content:'\e030'}.oi-cart:before{content:'\e031'}.oi-chat:before{content:'\e032'}.oi-check:before{content:'\e033'}.oi-chevron-bottom:before{content:'\e034'}.oi-chevron-left:before{content:'\e035'}.oi-chevron-right:before{content:'\e036'}.oi-chevron-top:before{content:'\e037'}.oi-circle-check:before{content:'\e038'}.oi-circle-x:before{content:'\e039'}.oi-clipboard:before{content:'\e03a'}.oi-clock:before{content:'\e03b'}.oi-cloud-download:before{content:'\e03c'}.oi-cloud-upload:before{content:'\e03d'}.oi-cloud:before{content:'\e03e'}.oi-cloudy:before{content:'\e03f'}.oi-code:before{content:'\e040'}.oi-cog:before{content:'\e041'}.oi-collapse-down:before{content:'\e042'}.oi-collapse-left:before{content:'\e043'}.oi-collapse-right:before{content:'\e044'}.oi-collapse-up:before{content:'\e045'}.oi-command:before{content:'\e046'}.oi-comment-square:before{content:'\e047'}.oi-compass:before{content:'\e048'}.oi-contrast:before{content:'\e049'}.oi-copywriting:before{content:'\e04a'}.oi-credit-card:before{content:'\e04b'}.oi-crop:before{content:'\e04c'}.oi-dashboard:before{content:'\e04d'}.oi-data-transfer-download:before{content:'\e04e'}.oi-data-transfer-upload:before{content:'\e04f'}.oi-delete:before{content:'\e050'}.oi-dial:before{content:'\e051'}.oi-document:before{content:'\e052'}.oi-dollar:before{content:'\e053'}.oi-double-quote-sans-left:before{content:'\e054'}.oi-double-quote-sans-right:before{content:'\e055'}.oi-double-quote-serif-left:before{content:'\e056'}.oi-double-quote-serif-right:before{content:'\e057'}.oi-droplet:before{content:'\e058'}.oi-eject:before{content:'\e059'}.oi-elevator:before{content:'\e05a'}.oi-ellipses:before{content:'\e05b'}.oi-envelope-closed:before{content:'\e05c'}.oi-envelope-open:before{content:'\e05d'}.oi-euro:before{content:'\e05e'}.oi-excerpt:before{content:'\e05f'}.oi-expand-down:before{content:'\e060'}.oi-expand-left:before{content:'\e061'}.oi-expand-right:before{content:'\e062'}.oi-expand-up:before{content:'\e063'}.oi-external-link:before{content:'\e064'}.oi-eye:before{content:'\e065'}.oi-eyedropper:before{content:'\e066'}.oi-file:before{content:'\e067'}.oi-fire:before{content:'\e068'}.oi-flag:before{content:'\e069'}.oi-flash:before{content:'\e06a'}.oi-folder:before{content:'\e06b'}.oi-fork:before{content:'\e06c'}.oi-fullscreen-enter:before{content:'\e06d'}.oi-fullscreen-exit:before{content:'\e06e'}.oi-globe:before{content:'\e06f'}.oi-graph:before{content:'\e070'}.oi-grid-four-up:before{content:'\e071'}.oi-grid-three-up:before{content:'\e072'}.oi-grid-two-up:before{content:'\e073'}.oi-hard-drive:before{content:'\e074'}.oi-header:before{content:'\e075'}.oi-headphones:before{content:'\e076'}.oi-heart:before{content:'\e077'}.oi-home:before{content:'\e078'}.oi-image:before{content:'\e079'}.oi-inbox:before{content:'\e07a'}.oi-infinity:before{content:'\e07b'}.oi-info:before{content:'\e07c'}.oi-italic:before{content:'\e07d'}.oi-justify-center:before{content:'\e07e'}.oi-justify-left:before{content:'\e07f'}.oi-justify-right:before{content:'\e080'}.oi-key:before{content:'\e081'}.oi-laptop:before{content:'\e082'}.oi-layers:before{content:'\e083'}.oi-lightbulb:before{content:'\e084'}.oi-link-broken:before{content:'\e085'}.oi-link-intact:before{content:'\e086'}.oi-list-rich:before{content:'\e087'}.oi-list:before{content:'\e088'}.oi-location:before{content:'\e089'}.oi-lock-locked:before{content:'\e08a'}.oi-lock-unlocked:before{content:'\e08b'}.oi-loop-circular:before{content:'\e08c'}.oi-loop-square:before{content:'\e08d'}.oi-loop:before{content:'\e08e'}.oi-magnifying-glass:before{content:'\e08f'}.oi-map-marker:before{content:'\e090'}.oi-map:before{content:'\e091'}.oi-media-pause:before{content:'\e092'}.oi-media-play:before{content:'\e093'}.oi-media-record:before{content:'\e094'}.oi-media-skip-backward:before{content:'\e095'}.oi-media-skip-forward:before{content:'\e096'}.oi-media-step-backward:before{content:'\e097'}.oi-media-step-forward:before{content:'\e098'}.oi-media-stop:before{content:'\e099'}.oi-medical-cross:before{content:'\e09a'}.oi-menu:before{content:'\e09b'}.oi-microphone:before{content:'\e09c'}.oi-minus:before{content:'\e09d'}.oi-monitor:before{content:'\e09e'}.oi-moon:before{content:'\e09f'}.oi-move:before{content:'\e0a0'}.oi-musical-note:before{content:'\e0a1'}.oi-paperclip:before{content:'\e0a2'}.oi-pencil:before{content:'\e0a3'}.oi-people:before{content:'\e0a4'}.oi-person:before{content:'\e0a5'}.oi-phone:before{content:'\e0a6'}.oi-pie-chart:before{content:'\e0a7'}.oi-pin:before{content:'\e0a8'}.oi-play-circle:before{content:'\e0a9'}.oi-plus:before{content:'\e0aa'}.oi-power-standby:before{content:'\e0ab'}.oi-print:before{content:'\e0ac'}.oi-project:before{content:'\e0ad'}.oi-pulse:before{content:'\e0ae'}.oi-puzzle-piece:before{content:'\e0af'}.oi-question-mark:before{content:'\e0b0'}.oi-rain:before{content:'\e0b1'}.oi-random:before{content:'\e0b2'}.oi-reload:before{content:'\e0b3'}.oi-resize-both:before{content:'\e0b4'}.oi-resize-height:before{content:'\e0b5'}.oi-resize-width:before{content:'\e0b6'}.oi-rss-alt:before{content:'\e0b7'}.oi-rss:before{content:'\e0b8'}.oi-script:before{content:'\e0b9'}.oi-share-boxed:before{content:'\e0ba'}.oi-share:before{content:'\e0bb'}.oi-shield:before{content:'\e0bc'}.oi-signal:before{content:'\e0bd'}.oi-signpost:before{content:'\e0be'}.oi-sort-ascending:before{content:'\e0bf'}.oi-sort-descending:before{content:'\e0c0'}.oi-spreadsheet:before{content:'\e0c1'}.oi-star:before{content:'\e0c2'}.oi-sun:before{content:'\e0c3'}.oi-tablet:before{content:'\e0c4'}.oi-tag:before{content:'\e0c5'}.oi-tags:before{content:'\e0c6'}.oi-target:before{content:'\e0c7'}.oi-task:before{content:'\e0c8'}.oi-terminal:before{content:'\e0c9'}.oi-text:before{content:'\e0ca'}.oi-thumb-down:before{content:'\e0cb'}.oi-thumb-up:before{content:'\e0cc'}.oi-timer:before{content:'\e0cd'}.oi-transfer:before{content:'\e0ce'}.oi-trash:before{content:'\e0cf'}.oi-underline:before{content:'\e0d0'}.oi-vertical-align-bottom:before{content:'\e0d1'}.oi-vertical-align-center:before{content:'\e0d2'}.oi-vertical-align-top:before{content:'\e0d3'}.oi-video:before{content:'\e0d4'}.oi-volume-high:before{content:'\e0d5'}.oi-volume-low:before{content:'\e0d6'}.oi-volume-off:before{content:'\e0d7'}.oi-warning:before{content:'\e0d8'}.oi-wifi:before{content:'\e0d9'}.oi-wrench:before{content:'\e0da'}.oi-x:before{content:'\e0db'}.oi-yen:before{content:'\e0dc'}.oi-zoom-in:before{content:'\e0dd'}.oi-zoom-out:before{content:'\e0de'} -------------------------------------------------------------------------------- /blazorui/wwwroot/css/open-iconic/font/fonts/open-iconic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/blazor-graphql-starter-kit/209c440fb98fbcede7a06d43c84c0a9dfa70f6de/blazorui/wwwroot/css/open-iconic/font/fonts/open-iconic.eot -------------------------------------------------------------------------------- /blazorui/wwwroot/css/open-iconic/font/fonts/open-iconic.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/blazor-graphql-starter-kit/209c440fb98fbcede7a06d43c84c0a9dfa70f6de/blazorui/wwwroot/css/open-iconic/font/fonts/open-iconic.otf -------------------------------------------------------------------------------- /blazorui/wwwroot/css/open-iconic/font/fonts/open-iconic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | Created by FontForge 20120731 at Tue Jul 1 20:39:22 2014 9 | By P.J. Onori 10 | Created by P.J. Onori with FontForge 2.0 (http://fontforge.sf.net) 11 | 12 | 13 | 14 | 27 | 28 | 30 | 32 | 34 | 36 | 38 | 40 | 42 | 45 | 47 | 49 | 51 | 53 | 55 | 57 | 59 | 61 | 63 | 65 | 67 | 69 | 71 | 74 | 76 | 79 | 81 | 84 | 86 | 88 | 91 | 93 | 95 | 98 | 100 | 102 | 104 | 106 | 109 | 112 | 115 | 117 | 121 | 123 | 125 | 127 | 130 | 132 | 134 | 136 | 138 | 141 | 143 | 145 | 147 | 149 | 151 | 153 | 155 | 157 | 159 | 162 | 165 | 167 | 169 | 172 | 174 | 177 | 179 | 181 | 183 | 185 | 189 | 191 | 194 | 196 | 198 | 200 | 202 | 205 | 207 | 209 | 211 | 213 | 215 | 218 | 220 | 222 | 224 | 226 | 228 | 230 | 232 | 234 | 236 | 238 | 241 | 243 | 245 | 247 | 249 | 251 | 253 | 256 | 259 | 261 | 263 | 265 | 267 | 269 | 272 | 274 | 276 | 280 | 282 | 285 | 287 | 289 | 292 | 295 | 298 | 300 | 302 | 304 | 306 | 309 | 312 | 314 | 316 | 318 | 320 | 322 | 324 | 326 | 330 | 334 | 338 | 340 | 343 | 345 | 347 | 349 | 351 | 353 | 355 | 358 | 360 | 363 | 365 | 367 | 369 | 371 | 373 | 375 | 377 | 379 | 381 | 383 | 386 | 388 | 390 | 392 | 394 | 396 | 399 | 401 | 404 | 406 | 408 | 410 | 412 | 414 | 416 | 419 | 421 | 423 | 425 | 428 | 431 | 435 | 438 | 440 | 442 | 444 | 446 | 448 | 451 | 453 | 455 | 457 | 460 | 462 | 464 | 466 | 468 | 471 | 473 | 477 | 479 | 481 | 483 | 486 | 488 | 490 | 492 | 494 | 496 | 499 | 501 | 504 | 506 | 509 | 512 | 515 | 517 | 520 | 522 | 524 | 526 | 529 | 532 | 534 | 536 | 539 | 542 | 543 | 544 | -------------------------------------------------------------------------------- /blazorui/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/blazor-graphql-starter-kit/209c440fb98fbcede7a06d43c84c0a9dfa70f6de/blazorui/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf -------------------------------------------------------------------------------- /blazorui/wwwroot/css/open-iconic/font/fonts/open-iconic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/blazor-graphql-starter-kit/209c440fb98fbcede7a06d43c84c0a9dfa70f6de/blazorui/wwwroot/css/open-iconic/font/fonts/open-iconic.woff -------------------------------------------------------------------------------- /blazorui/wwwroot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/blazor-graphql-starter-kit/209c440fb98fbcede7a06d43c84c0a9dfa70f6de/blazorui/wwwroot/favicon.ico -------------------------------------------------------------------------------- /blazorui/wwwroot/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | blazorui 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
Loading...
16 | 17 |
18 | An unhandled error has occurred. 19 | Reload 20 | 🗙 21 |
22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /blazorui/wwwroot/sample-data/weather.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "date": "2018-05-06", 4 | "temperatureC": 1, 5 | "summary": "Freezing" 6 | }, 7 | { 8 | "date": "2018-05-07", 9 | "temperatureC": 14, 10 | "summary": "Bracing" 11 | }, 12 | { 13 | "date": "2018-05-08", 14 | "temperatureC": -13, 15 | "summary": "Freezing" 16 | }, 17 | { 18 | "date": "2018-05-09", 19 | "temperatureC": -16, 20 | "summary": "Balmy" 21 | }, 22 | { 23 | "date": "2018-05-10", 24 | "temperatureC": -2, 25 | "summary": "Chilly" 26 | } 27 | ] 28 | -------------------------------------------------------------------------------- /docs/create_static_webapp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/blazor-graphql-starter-kit/209c440fb98fbcede7a06d43c84c0a9dfa70f6de/docs/create_static_webapp.png -------------------------------------------------------------------------------- /graphqlapi/.config/dotnet-tools.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "isRoot": true, 4 | "tools": { 5 | "microsoft.dotnet-msidentity": { 6 | "version": "1.0.0-preview.2.21253.1", 7 | "commands": [ 8 | "dotnet-msidentity" 9 | ] 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /graphqlapi/Models/BackboneElement.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Text.Json.Serialization; 3 | 4 | namespace graphqlapi.Models 5 | { 6 | public class BackboneElement : Element 7 | { 8 | [JsonPropertyName("modifierExtension")] 9 | public IList ModifierExtensions { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /graphqlapi/Models/Coding.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.Json.Serialization; 3 | 4 | namespace graphqlapi.Models 5 | { 6 | public class Coding 7 | { 8 | [JsonPropertyName("system")] 9 | public Uri System { get; set; } 10 | 11 | [JsonPropertyName("version")] 12 | public string Version { get; set; } 13 | 14 | [JsonPropertyName("code")] 15 | public string Code { get; set; } 16 | 17 | [JsonPropertyName("display")] 18 | public string Display { get; set; } 19 | 20 | [JsonPropertyName("userSelected")] 21 | public bool UserSelected { get; set; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /graphqlapi/Models/DomainResource.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace graphqlapi.Models 4 | { 5 | public class DomainResource : Resource 6 | { 7 | [JsonPropertyName("text")] 8 | public Narrative Text { get; set; } 9 | 10 | [JsonPropertyName("contained")] 11 | public Resource Contained { get; set; } 12 | 13 | [JsonPropertyName("extension")] 14 | public Extension Extension { get; set; } 15 | 16 | [JsonPropertyName("modifierExtension")] 17 | public Extension ModifierExtension { get; set; } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /graphqlapi/Models/Element.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | using System.Collections.Generic; 3 | 4 | namespace graphqlapi.Models 5 | { 6 | public class Element 7 | { 8 | [JsonPropertyName("id")] 9 | public string Id { get; set; } 10 | 11 | [JsonPropertyName("extension")] 12 | public IList Extensions { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /graphqlapi/Models/Extension.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace graphqlapi.Models 4 | { 5 | public class Extension : Element 6 | { 7 | public Uri Url { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /graphqlapi/Models/Identifier.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.Json.Serialization; 3 | 4 | namespace graphqlapi.Models 5 | { 6 | public class Identifier : Element 7 | { 8 | [JsonPropertyName("use")] 9 | public IdentifierUse Use { get; set; } 10 | 11 | [JsonPropertyName("type")] 12 | public IdentifierType Type { get; set; } 13 | 14 | [JsonPropertyName("system")] 15 | public Uri System { get; set; } 16 | 17 | [JsonPropertyName("value")] 18 | public string Value { get; set; } 19 | 20 | [JsonPropertyName("period")] 21 | public Period Period { get; set; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /graphqlapi/Models/IdentifierType.cs: -------------------------------------------------------------------------------- 1 | namespace graphqlapi.Models 2 | { 3 | public enum IdentifierType 4 | { 5 | DL, 6 | PPN, 7 | BRN, 8 | MR, 9 | MCN, 10 | EN, 11 | TAX, 12 | NIIP, 13 | PRN, 14 | MD, 15 | DR, 16 | ACSN, 17 | UDI, 18 | SNO, 19 | SB, 20 | PLAC, 21 | FILL, 22 | JHN 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /graphqlapi/Models/IdentifierUse.cs: -------------------------------------------------------------------------------- 1 | namespace graphqlapi.Models 2 | { 3 | public enum IdentifierUse 4 | { 5 | Usual, 6 | Official, 7 | Temp, 8 | Secondary, 9 | Old 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /graphqlapi/Models/Meta.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.Json.Serialization; 3 | 4 | namespace graphqlapi.Models 5 | { 6 | public class Meta : Element 7 | { 8 | [JsonPropertyName("versionId")] 9 | public string VersionId { get; set; } 10 | 11 | [JsonPropertyName("lastUpdated")] 12 | public DateTime LastUpdated { get; set; } 13 | 14 | [JsonPropertyName("source")] 15 | public Uri Source { get; set; } 16 | 17 | [JsonPropertyName("language")] 18 | public string Language { get; set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /graphqlapi/Models/Narrative.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace graphqlapi.Models 4 | { 5 | public class Narrative : Element 6 | { 7 | [JsonPropertyName("status")] 8 | public NarrativeStatus Status { get; set; } 9 | 10 | [JsonPropertyName("div")] 11 | public string Div { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /graphqlapi/Models/NarrativeStatus.cs: -------------------------------------------------------------------------------- 1 | namespace graphqlapi.Models 2 | { 3 | public enum NarrativeStatus 4 | { 5 | Generated, 6 | Extensions, 7 | Additional, 8 | Empty 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /graphqlapi/Models/Period.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.Json.Serialization; 3 | 4 | namespace graphqlapi.Models 5 | { 6 | public class Period : Element 7 | { 8 | [JsonPropertyName("start")] 9 | public DateTime Start { get; set; } 10 | 11 | [JsonPropertyName("end")] 12 | public DateTime End { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /graphqlapi/Models/PublicationStatus.cs: -------------------------------------------------------------------------------- 1 | namespace graphqlapi.Models 2 | { 3 | public enum PublicationStatus 4 | { 5 | Draft, 6 | Active, 7 | Retired, 8 | Unknown 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /graphqlapi/Models/Questionnaire.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text.Json.Serialization; 4 | 5 | namespace graphqlapi.Models 6 | { 7 | public class Questionnaire : DomainResource 8 | { 9 | [JsonPropertyName("url")] 10 | public Uri Url { get; set; } 11 | 12 | [JsonPropertyName("identifier")] 13 | public IList Identifier { get; set; } 14 | 15 | [JsonPropertyName("version")] 16 | public string Version { get; set; } 17 | 18 | [JsonPropertyName("name")] 19 | public string Name { get; set; } 20 | 21 | [JsonPropertyName("title")] 22 | public string Title { get; set; } 23 | 24 | [JsonPropertyName("status")] 25 | public PublicationStatus Status { get; set; } 26 | 27 | [JsonPropertyName("experimental")] 28 | public bool Experimental { get; set; } 29 | 30 | [JsonPropertyName("date")] 31 | public DateTime Date { get; set; } 32 | 33 | [JsonPropertyName("publisher")] 34 | public string Publisher { get; set; } 35 | 36 | [JsonPropertyName("description")] 37 | public string Description { get; set; } 38 | 39 | [JsonPropertyName("purpose")] 40 | public string Purpose { get; set; } 41 | 42 | [JsonPropertyName("copyright")] 43 | public string Copyright { get; set; } 44 | 45 | [JsonPropertyName("approvalDate")] 46 | public DateTime ApprovalDate { get; set; } 47 | 48 | [JsonPropertyName("lastReviewDate")] 49 | public DateTime LastReviewDate { get; set; } 50 | 51 | [JsonPropertyName("effectivePeriod")] 52 | public Period EffectivePeriod { get; set; } 53 | 54 | [JsonPropertyName("code")] 55 | public IList Code { get; set; } 56 | 57 | [JsonPropertyName("item")] 58 | public IList Items { get; set; } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /graphqlapi/Models/QuestionnaireItem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text.Json.Serialization; 4 | 5 | namespace graphqlapi.Models 6 | { 7 | public class QuestionnaireItem : BackboneElement 8 | { 9 | [JsonPropertyName("linkId")] 10 | public string LinkId { get; set; } 11 | 12 | [JsonPropertyName("definition")] 13 | public Uri Definition { get; set; } 14 | 15 | [JsonPropertyName("code")] 16 | public IList Code { get; set; } 17 | 18 | [JsonPropertyName("type")] 19 | public QuestionnaireItemType Type { get; set; } 20 | 21 | [JsonPropertyName("prefix")] 22 | public string Prefix { get; set; } 23 | 24 | [JsonPropertyName("text")] 25 | public string Text { get; set; } 26 | 27 | [JsonPropertyName("required")] 28 | public bool Required { get; set; } 29 | 30 | [JsonPropertyName("repeats")] 31 | public bool Repeats { get; set; } 32 | 33 | [JsonPropertyName("readOnly")] 34 | public bool ReadOnly { get; set; } 35 | 36 | [JsonPropertyName("maxLength")] 37 | public int MaxLength { get; set; } 38 | 39 | [JsonPropertyName("item")] 40 | public IList Items { get; set; } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /graphqlapi/Models/QuestionnaireItemType.cs: -------------------------------------------------------------------------------- 1 | namespace graphqlapi.Models 2 | { 3 | public enum QuestionnaireItemType 4 | { 5 | Group, 6 | Display, 7 | Question, 8 | Boolean, 9 | Decimal, 10 | Integer, 11 | Date, 12 | DateTime, 13 | Time, 14 | String, 15 | Text, 16 | Url, 17 | Choice, 18 | OpenChoice, 19 | Attachment, 20 | Reference, 21 | Quantity 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /graphqlapi/Models/Resource.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.Json.Serialization; 3 | 4 | namespace graphqlapi.Models 5 | { 6 | public class Resource 7 | { 8 | [JsonPropertyName("id")] 9 | public string Id { get; set; } 10 | 11 | [JsonPropertyName("meta")] 12 | public Meta Meta { get; set; } 13 | 14 | [JsonPropertyName("implicitRules")] 15 | public Uri ImplicitRules { get; set; } 16 | 17 | [JsonPropertyName("language")] 18 | public string Language { get; set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /graphqlapi/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Hosting; 2 | using Microsoft.Extensions.Configuration; 3 | using Microsoft.Extensions.Hosting; 4 | using Microsoft.Extensions.Logging; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Threading.Tasks; 9 | 10 | namespace graphqlapi 11 | { 12 | public class Program 13 | { 14 | public static void Main(string[] args) 15 | { 16 | CreateHostBuilder(args).Build().Run(); 17 | } 18 | 19 | public static IHostBuilder CreateHostBuilder(string[] args) => 20 | Host.CreateDefaultBuilder(args) 21 | .ConfigureWebHostDefaults(webBuilder => 22 | { 23 | webBuilder.UseStartup(); 24 | }); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /graphqlapi/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:5797", 7 | "sslPort": 44307 8 | } 9 | }, 10 | "$schema": "http://json.schemastore.org/launchsettings.json", 11 | "profiles": { 12 | "IIS Express": { 13 | "commandName": "IISExpress", 14 | "launchBrowser": true, 15 | "launchUrl": "graphql", 16 | "environmentVariables": { 17 | "ASPNETCORE_ENVIRONMENT": "Development" 18 | }, 19 | "ancmHostingModel": "InProcess" 20 | }, 21 | "graphqlapi": { 22 | "commandName": "Project", 23 | "launchBrowser": true, 24 | "launchUrl": "graphql", 25 | "environmentVariables": { 26 | "ASPNETCORE_ENVIRONMENT": "Development" 27 | }, 28 | "dotnetRunMessages": "true", 29 | "applicationUrl": "https://localhost:5001;http://localhost:5000" 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /graphqlapi/Properties/serviceDependencies.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "secrets1": { 4 | "type": "secrets" 5 | } 6 | } 7 | } -------------------------------------------------------------------------------- /graphqlapi/Properties/serviceDependencies.local.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "secrets1": { 4 | "type": "secrets.user" 5 | } 6 | } 7 | } -------------------------------------------------------------------------------- /graphqlapi/Resolvers/Query.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using System.Security.Claims; 4 | using HotChocolate; 5 | using HotChocolate.Types; 6 | using graphqlapi.Models; 7 | using System; 8 | 9 | namespace graphqlapi.Resolvers 10 | { 11 | public class Query 12 | { 13 | public string Welcome(ClaimsPrincipal claimsPrincipal) 14 | { 15 | return $"Congrats on making your first query!. You are authenticated as: {claimsPrincipal.Identity.Name}"; 16 | } 17 | 18 | public IList GetQuestionnairs() 19 | { 20 | return new List() 21 | { 22 | new Questionnaire() 23 | { 24 | Title="Sample 1", 25 | Date=DateTime.Now, 26 | }, 27 | new Questionnaire() 28 | { 29 | Title="Sample 2", 30 | Date=DateTime.Now, 31 | }, 32 | }; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /graphqlapi/Services/FhirServiceInMemory.cs: -------------------------------------------------------------------------------- 1 | using graphqlapi.Models; 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | namespace graphqlapi.Services 6 | { 7 | public class FhirServiceInMemory : IFhirService 8 | { 9 | private IList _questionnaires; 10 | 11 | public FhirServiceInMemory() 12 | { 13 | _questionnaires = LoadQuestionnaires(); 14 | } 15 | 16 | public IList GetQuestionnaires() 17 | { 18 | return _questionnaires; 19 | } 20 | 21 | private IList LoadQuestionnaires() 22 | { 23 | IList questionnaires = new List(); 24 | 25 | Questionnaire generalQuestionnaire = new Questionnaire() 26 | { 27 | Text = new Narrative() { 28 | Status = NarrativeStatus.Generated, 29 | Div = "
\n
\n            1.Comorbidity?\n              1.1 Cardial Comorbidity\n                1.1.1 Angina?\n                1.1.2 MI?\n              1.2 Vascular Comorbidity?\n              ...\n            Histopathology\n              Abdominal\n                pT category?\n              ...\n          
\n
" 30 | }, 31 | Url = new Uri("https://hl7.org/fhir/Questionnaire/3141"), 32 | Title = "Cancer Quality Forum Questionnaire 2012", 33 | Status = PublicationStatus.Draft, 34 | Date = new DateTime(2012, 1, 1), 35 | Items = new List() 36 | { 37 | new QuestionnaireItem() 38 | { 39 | LinkId = "1", 40 | Code = new List() 41 | { 42 | new Coding() 43 | { 44 | System = new Uri("http://example.org/system/code/sections"), 45 | Code = "COMORBIDITY" 46 | } 47 | }, 48 | Type = QuestionnaireItemType.Group, 49 | Items = new List() 50 | { 51 | new QuestionnaireItem() 52 | { 53 | LinkId = "1.1", 54 | Code = new List() 55 | { 56 | new Coding() 57 | { 58 | System = new Uri("http://example.org/system/code/questions"), 59 | Code = "COMORB" 60 | } 61 | }, 62 | Prefix = "1", 63 | Type = QuestionnaireItemType.Choice, 64 | Items = new List() 65 | { 66 | new QuestionnaireItem() 67 | { 68 | LinkId = "1.1.1", 69 | Code = new List() 70 | { 71 | new Coding() 72 | { 73 | System = new Uri("http://example.org/system/code/sections"), 74 | Code = "CARDIAL" 75 | } 76 | }, 77 | Type = QuestionnaireItemType.Group, 78 | Items = new List() 79 | { 80 | new QuestionnaireItem() 81 | { 82 | LinkId = "1.1.1.1", 83 | Code = new List() 84 | { 85 | new Coding() 86 | { 87 | System = new Uri("http://example.org/system/code/questions"), 88 | Code = "COMORBCAR" 89 | } 90 | }, 91 | Prefix = "1.1", 92 | Type = QuestionnaireItemType.Choice, 93 | Items = new List() 94 | { 95 | new QuestionnaireItem() 96 | { 97 | LinkId = "1.1.1.1.1", 98 | Code = new List() 99 | { 100 | new Coding() 101 | { 102 | System = new Uri("http://example.org/system/code/questions"), 103 | Code = "COMCAR00", 104 | Display = "Angina Pectoris" 105 | }, 106 | new Coding() 107 | { 108 | System = new Uri("http://snomed.info/sct"), 109 | Code = "194828000", 110 | Display = "Angina (disorder)" 111 | } 112 | }, 113 | Prefix = "1.1.1", 114 | Type = QuestionnaireItemType.Choice 115 | }, 116 | new QuestionnaireItem() 117 | { 118 | LinkId = "1.1.1.1.2", 119 | Code = new List() 120 | { 121 | new Coding() 122 | { 123 | System = new Uri("http://snomed.info/sct"), 124 | Code = "22298006", 125 | Display = "Myocardial infraction (disorder)" 126 | } 127 | }, 128 | Prefix = "1.1.2", 129 | Type = QuestionnaireItemType.Choice 130 | } 131 | } 132 | }, 133 | new QuestionnaireItem() 134 | { 135 | LinkId = "1.1.1.2", 136 | Code = new List() 137 | { 138 | new Coding() 139 | { 140 | System = new Uri("http://example.org/system/code/questions"), 141 | Code = "COMORBVAS" 142 | } 143 | }, 144 | Prefix = "1.2", 145 | Type = QuestionnaireItemType.Choice 146 | } 147 | } 148 | } 149 | } 150 | } 151 | } 152 | }, 153 | new QuestionnaireItem() 154 | { 155 | LinkId = "2", 156 | Code = new List() 157 | { 158 | new Coding() 159 | { 160 | System = new Uri("http://example.org/system/code/sections"), 161 | Code = "HISTOPATHOLOGY" 162 | } 163 | }, 164 | Type = QuestionnaireItemType.Group, 165 | Items = new List() 166 | { 167 | new QuestionnaireItem() 168 | { 169 | LinkId = "2.1", 170 | Code = new List() 171 | { 172 | new Coding() 173 | { 174 | System = new Uri("http://example.org/system/code/sections"), 175 | Code = "ABDOMINAL" 176 | } 177 | }, 178 | Type = QuestionnaireItemType.Group, 179 | Items = new List() 180 | { 181 | new QuestionnaireItem() 182 | { 183 | LinkId = "2.1.2", 184 | Code = new List() 185 | { 186 | new Coding() 187 | { 188 | System = new Uri("http://example.org/system/code/questions"), 189 | Code = "STADPT", 190 | Display = "pT category" 191 | } 192 | }, 193 | Type = QuestionnaireItemType.Choice 194 | } 195 | } 196 | } 197 | } 198 | } 199 | } 200 | }; 201 | 202 | questionnaires.Add(generalQuestionnaire); 203 | 204 | return questionnaires; 205 | } 206 | } 207 | } 208 | -------------------------------------------------------------------------------- /graphqlapi/Services/IFhirService.cs: -------------------------------------------------------------------------------- 1 | using graphqlapi.Models; 2 | using System.Collections.Generic; 3 | 4 | namespace graphqlapi.Services 5 | { 6 | public interface IFhirService 7 | { 8 | public IList GetQuestionnaires(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /graphqlapi/Startup.cs: -------------------------------------------------------------------------------- 1 | using graphqlapi.Resolvers; 2 | using Microsoft.AspNetCore.Authentication; 3 | using Microsoft.AspNetCore.Authentication.JwtBearer; 4 | using Microsoft.AspNetCore.Builder; 5 | using Microsoft.AspNetCore.Hosting; 6 | using Microsoft.AspNetCore.HttpsPolicy; 7 | using Microsoft.AspNetCore.Mvc; 8 | using Microsoft.Extensions.Configuration; 9 | using Microsoft.Extensions.DependencyInjection; 10 | using Microsoft.Extensions.Hosting; 11 | using Microsoft.Extensions.Logging; 12 | using Microsoft.Identity.Web; 13 | using Microsoft.OpenApi.Models; 14 | using System; 15 | using System.Collections.Generic; 16 | using System.Linq; 17 | using System.Threading.Tasks; 18 | 19 | namespace graphqlapi 20 | { 21 | public class Startup 22 | { 23 | public Startup(IConfiguration configuration) 24 | { 25 | Configuration = configuration; 26 | } 27 | 28 | public IConfiguration Configuration { get; } 29 | 30 | // This method gets called by the runtime. Use this method to add services to the container. 31 | public void ConfigureServices(IServiceCollection services) 32 | { 33 | services.AddCors(o => o.AddDefaultPolicy(b => 34 | b.AllowAnyHeader() 35 | .AllowAnyMethod() 36 | .AllowAnyOrigin() 37 | ) 38 | ); 39 | 40 | services.AddMicrosoftIdentityWebApiAuthentication(Configuration, "AzureAd"); 41 | services.AddAuthorization(); 42 | 43 | services 44 | .AddGraphQLServer() 45 | .AddAuthorization() 46 | .AddQueryType(); 47 | 48 | } 49 | 50 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 51 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 52 | { 53 | if (env.IsDevelopment()) 54 | { 55 | app.UseDeveloperExceptionPage(); 56 | } 57 | 58 | app.UseCors(); 59 | 60 | app.UseHttpsRedirection(); 61 | 62 | app.UseRouting(); 63 | 64 | app.UseAuthentication(); 65 | app.UseAuthorization(); 66 | 67 | app.UseEndpoints(endpoints => 68 | { 69 | endpoints.MapGraphQL(); 70 | }); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /graphqlapi/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /graphqlapi/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | /* 3 | The following identity settings need to be configured 4 | before the project can be successfully executed. 5 | For more info see https://aka.ms/dotnet-template-ms-identity-platform 6 | */ 7 | "AzureAd": { 8 | "Instance": "https://login.microsoftonline.com/", 9 | "Domain": "qualified.domain.name", 10 | "TenantId": "22222222-2222-2222-2222-222222222222", 11 | "ClientId": "11111111-1111-1111-11111111111111111" 12 | }, 13 | "Logging": { 14 | "LogLevel": { 15 | "Default": "Information", 16 | "Microsoft": "Warning", 17 | "Microsoft.Hosting.Lifetime": "Information" 18 | } 19 | }, 20 | "AllowedHosts": "*" 21 | } 22 | -------------------------------------------------------------------------------- /graphqlapi/graphqlapi.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net5.0 5 | aspnet-graphqlapi-4BEFEC0E-E182-4F04-B97C-27D4D6466DF9 6 | true 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | --------------------------------------------------------------------------------