UUpdated all goals, removed original site
This commit is contained in:
Родитель
d7e4a0e24b
Коммит
a13edcd352
|
@ -1,5 +0,0 @@
|
|||
.DS_Store
|
||||
node_modules
|
||||
/.svelte-kit
|
||||
/build
|
||||
/functions
|
1
.npmrc
1
.npmrc
|
@ -1 +0,0 @@
|
|||
engine-strict=true
|
|
@ -4,5 +4,11 @@
|
|||
"azureFunctions.projectLanguage": "JavaScript",
|
||||
"azureFunctions.projectRuntime": "~3",
|
||||
"debug.internalConsoleOptions": "neverOpen",
|
||||
"azureFunctions.preDeployTask": "npm prune"
|
||||
"azureFunctions.preDeployTask": "npm prune",
|
||||
"markdownlint.config": {
|
||||
"MD028": false,
|
||||
"MD025": {
|
||||
"front_matter_title": ""
|
||||
}
|
||||
}
|
||||
}
|
47
README.md
47
README.md
|
@ -2,22 +2,22 @@
|
|||
|
||||
According to the American Society for the Prevention of Cruelty to Animals (ASPCA), animal shelters receive about 3 million dogs annually - about 6 dogs per minute! While euthanasia rates have dropped, over 500,000 dogs are euthanized because they could not be matched with their original owners or an adoptive family.
|
||||
|
||||
Your team will aid a fictional adoption agency with deploying their website to the cloud. The application is designed to raise awareness of different dog breeds. A potential adopter can use the app to flip through pictures of various dogs and come up with potential names for each dog. This can be a great way to get a family excited about the possibility of adopting a new pet!
|
||||
|
||||
The agency has already created the website using [Svelte](https://svelte.dev/) and [Svelte Kit](https://kit.svelte.dev/) for the front end, [Azure Functions](https://docs.microsoft.com/azure/azure-functions/functions-overview?WT.mc_id=academic-28005-chrhar) and a [MongoDB API database](https://docs.mongodb.com/drivers/node/current/) for the back-end. They have provided documentation your team can review to gain an understanding of how it works, and run it locally for testing purposes.
|
||||
Your team will assist a fictional pet adoption agency in creating a website. To start they would like to provide a tool where a user could create a list of all the tasks they need to perform when they adopt a pet, like schedule their first vet appointment or apply for a dog license. Your team will do so by using [Azure Static Web Apps](https://docs.microsoft.com/azure/static-web-apps/overview?WT.mc_id=academic-28005-chrhar) for hosting and an already created template.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
### Azure account
|
||||
|
||||
Each team member will need an Azure account. With [Azure for Students](https://aka.ms/a4s?WT.mc_id=academic-28005-chrhar), you can access $100 in free credit, and a large suite of free services!
|
||||
|
||||
Your team should be familiar with the following:
|
||||
### Skills
|
||||
|
||||
- HTML, CSS and JavaScript
|
||||
- Git and GitHub
|
||||
- [Forking](https://docs.github.com/github/getting-started-with-github/quickstart/fork-a-repo) and [cloning](https://docs.github.com/github/creating-cloning-and-archiving-repositories/cloning-a-repository-from-github/cloning-a-repository) repositories
|
||||
- [Creating and managing branches](https://docs.github.com/en/desktop/contributing-and-collaborating-using-github-desktop/making-changes-in-a-branch/managing-branches)
|
||||
- HTML, CSS and JavaScript
|
||||
|
||||
Each member of your team will also need the following software installed:
|
||||
### Software
|
||||
|
||||
- [Git](https://git-scm.com/downloads)
|
||||
- [Install git on macOS](https://git-scm.com/download/mac)
|
||||
|
@ -37,41 +37,28 @@ Each member of your team will also need the following software installed:
|
|||
|
||||
A series of resources will be provided to help your team determine the appropriate steps for completion. The resources provided should provide your team with enough information to achieve each goal. If you get stuck, you can always ask a mentor for additional help.
|
||||
|
||||
A [sample of the site](https://calm-glacier-0b7804d10.azurestaticapps.net/) has been deployed so you can see how it looks in action.
|
||||
|
||||
## Exploring the source code
|
||||
|
||||
There are two key folders for the application: [src/routes](../src/routes), which contains the Svelte files used for the front-end, and [api](../api), which contains the Azure Functions used for the back-end. The flow of the application is as follows:
|
||||
|
||||
1. A user navigates to the page and is presented with the option to login (and sees a picture of a cute dog)
|
||||
1. User authenticates using their GitHub credentials
|
||||
1. After authenticating, the user can now name dogs. Each time they name a dog, it's saved to a Mongo API database.
|
||||
1. The user can click on the "named dogs" link to review the list of dogs they've named
|
||||
|
||||
> **Note**: No updates to the application code will be made during this workshop. Your team will be able to successfully complete the workshop without any experience with Svelte. The only file your team will modify is *staticwebapp.config.json*.
|
||||
|
||||
![Flow of the app](./goals/media/app-flow.svg)
|
||||
A [sample of the site](https://kind-beach-04aea671e.azurestaticapps.net/) has been deployed so you can see how it looks in action.
|
||||
|
||||
## Goals
|
||||
|
||||
Your team will obtain the starter, deploy the application to the cloud, enable authentication, and create and configure the database.
|
||||
Your team will obtain the starter, deploy the application to the cloud, download and run the source code locally, and make modifications to the site.
|
||||
|
||||
1. [Obtain the source code](./goals/0-obtain-source.md):
|
||||
The first step when working with any codebase is to download it. Your team's first goal will be to obtain the code from GitHub.
|
||||
1. [Deploy to the cloud](./goals/1-deploy.md):
|
||||
1. [Obtain and deploy the template to the cloud](./goals/1-deploy.md):
|
||||
Because the pet shelter wants the application to be publicly available, your team will need to deploy the application. For this workshop, your team will use Azure Static Web Apps, which is able to host the application and run the Azure Functions.
|
||||
1. [Enable authentication](./goals/2-authentication.md):
|
||||
A key component of the app is allowing users to name dogs and have the names saved to a list. This requires authentication, which is built-in to Azure Static Web Apps. To achieve this goal, your team will configure the application so *only* GitHub authentication is enabled.
|
||||
1. [Add a database](./goals/3-database.md):
|
||||
Saving information typically requires a database, and this application is no different. The code has already been added to use a Mongo API database, which is available through Cosmos DB on Azure. Your team will create a Cosmos DB account, and then update the application on Azure Static Web Apps to use your newly created database.
|
||||
1. [Download and run the application locally](./goals/2-local.md):
|
||||
After creating the project on GitHub and deploying it to Azure Static Web Apps, each member of your team will download the project and run it locally for development purposes.
|
||||
1. [Modify the site and push updates](./goals/3-modify.md):
|
||||
The template uses a relatively generic example of a task management system. You want to update the landing page to display a proper welcome message and update the verbiage to include the suggested usage - tracking what the pet adopter needs to do post adoption.
|
||||
|
||||
## Validation
|
||||
|
||||
This workshop is designed to be a goal-oriented self-exploration of Azure and related technologies. Your team can use the [validation tool](https://ashy-mushroom-0609d7c10.azurestaticapps.net/) to confirm the *Deploy to the cloud* and *Enable authentication* goals have been met. Validating the final goal of *Add a database* will be manual - you'll use the application your team deployed and confirm it works as expected.
|
||||
This workshop is designed to be a goal-oriented self-exploration of Azure and related technologies. Your team can use the [validation tool](https://ashy-mushroom-0609d7c10.azurestaticapps.net/) to confirm the site has been deployed correctly and updates pushed.
|
||||
|
||||
## Where do we go from here?
|
||||
|
||||
This project is designed as a potential seed for future development. If you were to continue with this idea, your team could potentially:
|
||||
This project is designed as a potential seed for future development. From a technical perspective, you can begin to incorporate whatever frameworks or technologies you wish to use. This could include [React](https://docs.microsoft.com/learn/paths/react?WT.mc_id=academic-28005-chrhar) or [Vue](https://docs.microsoft.com/learn/paths/vue-first-steps/?WT.mc_id=academic-28005-chrhar).
|
||||
|
||||
If you were to continue with this idea, your team could potentially:
|
||||
|
||||
- Use the [Petfinder API](https://www.petfinder.com/developers/) to create an application to match potential adopters with dogs
|
||||
- Use the [Bing Maps API](https://docs.microsoft.com/bingmaps/getting-started/?WT.mc_id=academic-28005-chrhar) to search based on location
|
||||
|
|
25
SUPPORT.md
25
SUPPORT.md
|
@ -1,25 +0,0 @@
|
|||
# TODO: The maintainer of this repo has not yet edited this file
|
||||
|
||||
**REPO OWNER**: Do you want Customer Service & Support (CSS) support for this product/project?
|
||||
|
||||
- **No CSS support:** Fill out this template with information about how to file issues and get help.
|
||||
- **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).
|
||||
- **Not sure?** Fill out a SPOT intake as though the answer were "Yes". CSS will help you decide.
|
||||
|
||||
*Then remove this first heading from this SUPPORT.MD file before publishing your repo.*
|
||||
|
||||
# Support
|
||||
|
||||
## How to file issues and get help
|
||||
|
||||
This project uses GitHub Issues to track bugs and feature requests. Please search the existing
|
||||
issues before filing new issues to avoid duplicates. For new issues, file your bug or
|
||||
feature request as a new Issue.
|
||||
|
||||
For help and questions about using this project, please **REPO MAINTAINER: INSERT INSTRUCTIONS HERE
|
||||
FOR HOW TO ENGAGE REPO OWNERS OR COMMUNITY FOR HELP. COULD BE A STACK OVERFLOW TAG OR OTHER
|
||||
CHANNEL. WHERE WILL YOU HELP PEOPLE?**.
|
||||
|
||||
## Microsoft Support Policy
|
||||
|
||||
Support for this **PROJECT or PRODUCT** is limited to the resources listed above.
|
|
@ -1,7 +0,0 @@
|
|||
*.js.map
|
||||
*.ts
|
||||
.git*
|
||||
.vscode
|
||||
local.settings.json
|
||||
test
|
||||
tsconfig.json
|
|
@ -1,94 +0,0 @@
|
|||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# TypeScript v1 declaration files
|
||||
typings/
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
.env.test
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
|
||||
# next.js build output
|
||||
.next
|
||||
|
||||
# nuxt.js build output
|
||||
.nuxt
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
# TypeScript output
|
||||
dist
|
||||
out
|
||||
|
||||
# Azure Functions artifacts
|
||||
bin
|
||||
obj
|
||||
appsettings.json
|
||||
local.settings.json
|
|
@ -1,19 +0,0 @@
|
|||
module.exports = {
|
||||
getUserId(req) {
|
||||
if (!req) throw 'req parameter is required';
|
||||
const header = req.headers['x-ms-client-principal'];
|
||||
const encoded = Buffer.from(header, 'base64');
|
||||
const decoded = encoded.toString('ascii');
|
||||
const clientPrincipal = JSON.parse(decoded);
|
||||
return clientPrincipal.userId;
|
||||
},
|
||||
getMongoClient() {
|
||||
const { MongoClient } = require("mongodb");
|
||||
const uri = process.env.MONGO_CONNECTION_STRING;
|
||||
const client = new MongoClient(uri, {
|
||||
useNewUrlParser: true,
|
||||
useUnifiedTopology: true,
|
||||
});
|
||||
return client;
|
||||
}
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
{
|
||||
"version": "2.0",
|
||||
"logging": {
|
||||
"applicationInsights": {
|
||||
"samplingSettings": {
|
||||
"isEnabled": true,
|
||||
"excludedTypes": "Request"
|
||||
}
|
||||
}
|
||||
},
|
||||
"extensionBundle": {
|
||||
"id": "Microsoft.Azure.Functions.ExtensionBundle",
|
||||
"version": "[1.*, 2.0.0)"
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
{
|
||||
"bindings": [
|
||||
{
|
||||
"authLevel": "anonymous",
|
||||
"type": "httpTrigger",
|
||||
"direction": "in",
|
||||
"name": "req",
|
||||
"methods": [
|
||||
"get",
|
||||
"post"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "http",
|
||||
"direction": "out",
|
||||
"name": "res"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
module.exports = async function (context, req) {
|
||||
const {getUserId, getMongoClient} = require('../helpers.js')
|
||||
|
||||
const userId = getUserId(req);
|
||||
const client = getMongoClient();
|
||||
|
||||
try {
|
||||
client.connect();
|
||||
const database = client.db('loved-mutt');
|
||||
const collection = database.collection('dogs');
|
||||
const namedDogs = await collection.find({userId}).toArray();
|
||||
context.res.body = {namedDogs};
|
||||
} catch (ex) {
|
||||
context.res = {
|
||||
body: ex,
|
||||
status: 500
|
||||
}
|
||||
} finally {
|
||||
client.close();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
{
|
||||
"name": "Azure"
|
||||
}
|
|
@ -1,135 +0,0 @@
|
|||
{
|
||||
"name": "api",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"bl": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz",
|
||||
"integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==",
|
||||
"requires": {
|
||||
"readable-stream": "^2.3.5",
|
||||
"safe-buffer": "^5.1.1"
|
||||
}
|
||||
},
|
||||
"bson": {
|
||||
"version": "1.1.6",
|
||||
"resolved": "https://registry.npmjs.org/bson/-/bson-1.1.6.tgz",
|
||||
"integrity": "sha512-EvVNVeGo4tHxwi8L6bPj3y3itEvStdwvvlojVxxbyYfoaxJ6keLgrTuKdyfEAszFK+H3olzBuafE0yoh0D1gdg=="
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
||||
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
|
||||
},
|
||||
"denque": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/denque/-/denque-1.5.0.tgz",
|
||||
"integrity": "sha512-CYiCSgIF1p6EUByQPlGkKnP1M9g0ZV3qMIrqMqZqdwazygIA/YP2vrbcyl1h/WppKJTdl1F85cXIle+394iDAQ=="
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||
},
|
||||
"isarray": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
||||
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
|
||||
},
|
||||
"memory-pager": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz",
|
||||
"integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==",
|
||||
"optional": true
|
||||
},
|
||||
"mongodb": {
|
||||
"version": "3.6.6",
|
||||
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.6.tgz",
|
||||
"integrity": "sha512-WlirMiuV1UPbej5JeCMqE93JRfZ/ZzqE7nJTwP85XzjAF4rRSeq2bGCb1cjfoHLOF06+HxADaPGqT0g3SbVT1w==",
|
||||
"requires": {
|
||||
"bl": "^2.2.1",
|
||||
"bson": "^1.1.4",
|
||||
"denque": "^1.4.1",
|
||||
"optional-require": "^1.0.2",
|
||||
"safe-buffer": "^5.1.2",
|
||||
"saslprep": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"optional-require": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.0.3.tgz",
|
||||
"integrity": "sha512-RV2Zp2MY2aeYK5G+B/Sps8lW5NHAzE5QClbFP15j+PWmP+T9PxlJXBOOLoSAdgwFvS4t0aMR4vpedMkbHfh0nA=="
|
||||
},
|
||||
"process-nextick-args": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
||||
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "2.3.7",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
|
||||
"integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
|
||||
"requires": {
|
||||
"core-util-is": "~1.0.0",
|
||||
"inherits": "~2.0.3",
|
||||
"isarray": "~1.0.0",
|
||||
"process-nextick-args": "~2.0.0",
|
||||
"safe-buffer": "~5.1.1",
|
||||
"string_decoder": "~1.1.1",
|
||||
"util-deprecate": "~1.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
|
||||
},
|
||||
"saslprep": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz",
|
||||
"integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"sparse-bitfield": "^3.0.3"
|
||||
}
|
||||
},
|
||||
"sparse-bitfield": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz",
|
||||
"integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"memory-pager": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
||||
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
||||
"requires": {
|
||||
"safe-buffer": "~5.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
{
|
||||
"name": "api",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"scripts": {
|
||||
"start": "func start",
|
||||
"test": "echo \"No tests yet...\""
|
||||
},
|
||||
"dependencies": {
|
||||
"mongodb": "^3.6.6"
|
||||
}
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"$schema": "http://json.schemastore.org/proxies",
|
||||
"proxies": {}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
{
|
||||
"bindings": [
|
||||
{
|
||||
"authLevel": "anonymous",
|
||||
"type": "httpTrigger",
|
||||
"direction": "in",
|
||||
"name": "req",
|
||||
"methods": [
|
||||
"get",
|
||||
"post"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "http",
|
||||
"direction": "out",
|
||||
"name": "res"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
module.exports = async function (context, req) {
|
||||
const {getUserId, getMongoClient} = require('../helpers')
|
||||
const client = getMongoClient();
|
||||
|
||||
try {
|
||||
await client.connect();
|
||||
const database = client.db('loved-mutt');
|
||||
const collection = database.collection('dogs');
|
||||
const doc = {
|
||||
imageUrl: req.body.imageUrl,
|
||||
dogType: req.body.dogType,
|
||||
name: req.body.name,
|
||||
userId: getUserId(req)
|
||||
};
|
||||
const result = await collection.insertOne(doc);
|
||||
context.res = {
|
||||
body: result
|
||||
};
|
||||
} catch (ex) {
|
||||
context.res = {
|
||||
body: ex,
|
||||
status: 500
|
||||
}
|
||||
} finally {
|
||||
client.close();
|
||||
}
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
{
|
||||
"name": "Azure"
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
{
|
||||
"IsEncrypted": false,
|
||||
"Values": {
|
||||
"AzureWebJobsStorage": "",
|
||||
"FUNCTIONS_WORKER_RUNTIME": "node",
|
||||
"MONGO_CONNECTION_STRING": "mongodb://localhost"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
# Goal 0: Obtain the source code
|
||||
|
||||
Whenever working on any project, step 0 is typically to fork and clone the repository, and install the necessary tooling. To streamline this process, The pet shelter has provided your team with step-by-step instructions.
|
||||
|
||||
## About the application
|
||||
|
||||
The front-end was created using [Svelte](https://svelte.dev) and [SvelteKit](https://kit.svelte.dev). No experience with Svelte is required.
|
||||
|
||||
The back-end uses [Azure Functions](https://docs.microsoft.com/azure/azure-functions/functions-overview?WT.mc_id=academic-28005-chrhar), the Azure serverless platform. Azure Functions are supported natively by Azure Static Web Apps, which is where your team will deploy the application. As your team gets to each goal, relevant notes about the application will be provided.
|
||||
|
||||
> Note: Your team does not have to run the application locally to complete this workshop. If you wish to configure your system for local development, [setup steps have been provided](./4-optional-run-locally).
|
||||
|
||||
## Generate the repository and obtain the source code
|
||||
|
||||
The starter repository (or repo) has been created as a [GitHub template](https://docs.github.com/github/creating-cloning-and-archiving-repositories/creating-a-repository-on-github/creating-a-repository-from-a-template). One member of your team will generate a repository from this template, while the remaining team members will fork it. All team members will clone the repository locally.
|
||||
|
||||
1. One team member: [generate the repository](https://github.com/login?return_to=https%3A%2F%2Fgithub.com%2Fgeektrainer%2Floved-mutt%2Fgenerate) by using the template. Your team can give the repository whatever name you like.
|
||||
1. All other team members will [fork](https://docs.github.com/github/getting-started-with-github/quickstart/fork-a-repo) the new repository.
|
||||
1. All team members will [clone the repository](https://docs.github.com/github/creating-cloning-and-archiving-repositories/cloning-a-repository-from-github/cloning-a-repository), which can be accomplished by running the following command.
|
||||
1. For all team members, after cloning the repository, open the local folder in Visual Studio Code
|
||||
|
||||
## Congratulations
|
||||
|
||||
Your team has successfully obtained the starter code and explored the app! Now it's time to [deploy the project to the cloud](1-deploy.md).
|
|
@ -1,56 +1,64 @@
|
|||
# Goal 1: Deploy to the cloud
|
||||
# Goal 1: Create cloud resources and deploy the website
|
||||
|
||||
The pet shelter's application is a full-stack application (or sometimes called a static web app). All the necessary code for both the client and server are contained inside one project, and the client uses a framework (Svelte in this case). The application also requires access to a database which uses Mongo DB APIs, and the ability to enable authentication.
|
||||
Many developers use templates or other samples to help bootstrap their projects. Rather than building from scratch, the pet shelter wants to minimize the startup steps as best as possible. Towards that end, they would like your team to use an [already built template](https://github.com/staticwebdev/mongoose-starter) for [Azure Static Web Apps](https://docs.microsoft.com/azure/static-web-apps/overview?WT.mc_id=academic-28005-chrhar). The template includes the following:
|
||||
|
||||
For this goal, your team will deploy the application to Azure. Future goals will focus on authentication and the database.
|
||||
- Client app written with HTML, CSS and vanilla JavaScript
|
||||
- Server-side code using [Azure Functions](https://docs.microsoft.com/azure/azure-functions/functions-overview?WT.mc_id=academic-28005-chrhar) and [Mongoose](https://mongoosejs.com/) to interact with the database
|
||||
|
||||
## The Azure Service
|
||||
## The goal
|
||||
|
||||
[Azure Static Web Apps](https://docs.microsoft.com/azure/static-web-apps/overview) is a service which builds and deploys full stack web apps to Azure from a code repository. It provides hosting for static files (HTML, CSS, JavaScript, etc.) and server-side code through serverless Azure Functions. Azure Static Web Apps can host applications written with any front-end framework, including React, Angular, Vue.js and Svelte. Azure Functions can be used to access server resources such as databases or other APIs. A site deployed to Azure Static Web Apps automatically scales, and can even have custom domains.
|
||||
For this goal, your team will deploy the sample to Azure. During the process, you will create the following resources:
|
||||
|
||||
- Azure Static Web App to host the project
|
||||
- [Azure Cosmos DB API for MongoDB](https://docs.microsoft.com/azure/cosmos-db/mongodb/mongodb-introduction?WT.mc_id=academic-28005-chrhar) to store the data
|
||||
|
||||
Additionally, you will configure the Static Web App with the correct connection string to the database.
|
||||
|
||||
## The Azure Services
|
||||
|
||||
[Azure Static Web Apps](https://docs.microsoft.com/azure/static-web-apps/overview?WT.mc_id=academic-28005-chrhar) is a service which builds and deploys full stack web apps to Azure from a code repository. It provides hosting for static files (HTML, CSS, JavaScript, etc.) and server-side code through serverless Azure Functions. Azure Static Web Apps can host applications written with any front-end framework, including React, Angular, Vue.js and Svelte. Azure Functions can be used to access server resources such as databases or other APIs. A site deployed to Azure Static Web Apps automatically scales, and can even have custom domains.
|
||||
|
||||
Deployment is managed through [GitHub actions](https://github.com/features/actions). When you create a static web app, Azure will automatically create a workflow file on your GitHub repository. This allows you to use GitHub just as you normally would, and updates to *main* or whatever branch you specify are automatically deployed to Azure.
|
||||
|
||||
Finally, [Azure Cosmos DB API for MongoDB](https://docs.microsoft.com/azure/cosmos-db/mongodb/mongodb-introduction?WT.mc_id=academic-28005-chrhar) will be the database for the project. Cosmos DB supports different APIs, including MongoDB API allowing for flexibility in application development. Because the database supports MongoDB API you can use a client such as [Mongoose](https://mongoosejs.com/) or the [MongoDB Node Driver](https://docs.mongodb.com/drivers/node/current/).
|
||||
|
||||
## Application notes
|
||||
|
||||
When deploying to Azure Static Web Apps, you will need to configure three key folders. These folder names may change based on the application or framework you're using. Defaults are provided when using common frameworks. You can consult the table below for a quick overview of these folders, and the setting necessary for this application.
|
||||
|
||||
Folder name | Description | Setting
|
||||
----------------|------------------------------------------------------------------------------------|-----------
|
||||
App location | Root of the application | **/**
|
||||
Output location | Name of any folders generated by the build process (like *build*, *lib* or *dist*) | **build**
|
||||
API location | Location of the API when using Azure Functions for server-side code | **api**
|
||||
Your team will use the [Static Web Apps - Mongoose starter](https://github.com/staticwebdev/mongoose-starter) as the base for the shelter's site. The template is documented and heavily commented.
|
||||
|
||||
## Success criteria
|
||||
|
||||
Your team will work together to deploy the application to Azure using Azure Static Web Apps. Your team will have achieved this goal when the following success criteria are met:
|
||||
|
||||
- The shelter's site has been successfully deployed to Azure Static Web Apps
|
||||
- You can open the index page on the newly created Azure Static Web App
|
||||
- The site has been successfully deployed to Azure Static Web Apps
|
||||
- You can open the index page, authenticate via GitHub, create a task and mark it as completed
|
||||
|
||||
## Validation
|
||||
## Tips
|
||||
|
||||
To validate your team's work with the [automated tool](https://ashy-mushroom-0609d7c10.azurestaticapps.net/), enter the newly created URL on Azure Static Web Apps into the tool.
|
||||
- **DO NOT** delete the resource group after walking through the tutorial; you'll be using the deployed project for the remainder of the workshop.
|
||||
|
||||
## Resources
|
||||
|
||||
Your team might find these resources helpful:
|
||||
|
||||
- [Tutorial: Access data in Cosmos DB using Mongoose with Azure Static Web Apps](https://docs.microsoft.com/azure/static-web-apps/add-mongoose?WT.mc_id=academic-28005-chrhar)
|
||||
- [What is Azure Static Web Apps](https://docs.microsoft.com/azure/static-web-apps/overview?WT.mc_id=academic-28005-chrhar)
|
||||
- [Quickstart: Create a static web app - Azure Portal](https://docs.microsoft.com/azure/static-web-apps/get-started-portal?tabs=vanilla-javascript#create-a-static-web-app?WT.mc_id=academic-28005-chrhar)
|
||||
- [Quickstart: Building your first static site - Visual Studio Code](https://docs.microsoft.com/azure/static-web-apps/getting-started?tabs=vanilla-javascript#create-a-static-web-app?WT.mc_id=academic-28005-chrhar)
|
||||
|
||||
## Tips
|
||||
## Validation
|
||||
|
||||
- After successfully deploying to Azure, run `git pull` to pull down the newly generated workflow file.
|
||||
- Your team may find the [Azure Static Web Apps Visual Studio Code extension](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-azurestaticwebapps) helpful
|
||||
- The login page **will not** work yet; your team will enable authentication for the next goal
|
||||
To validate your team's work with the [automated tool](https://ashy-mushroom-0609d7c10.azurestaticapps.net/), enter the newly created URL on Azure Static Web Apps into the tool.
|
||||
|
||||
## Final result
|
||||
|
||||
After you deploy and navigate to the site, you should see a page which looks like the following:
|
||||
After deploying the project you can now perform the following tasks:
|
||||
|
||||
![Screenshot of the starting page, showing a link to login, a picture of a dog with the heading Isn't this a cute Pekinese dog?](./media/starter-page.png)
|
||||
1. Navigate to the site
|
||||
1. Login using GitHub
|
||||
1. Add a new task (maybe named Test)
|
||||
1. Mark the task as completed
|
||||
|
||||
![Screenshot of the application after login with a username of GeekTrainer and a task of Test](./media/tasks.png)
|
||||
|
||||
## Next challenge
|
||||
|
||||
Once you've deployed your application, it's time to [add authentication](./2-authentication.md).
|
||||
Once you've deployed your application, it's time to [run the site locally](./2-local.md).
|
||||
|
|
|
@ -1,101 +0,0 @@
|
|||
# Goal 2 - Authentication
|
||||
|
||||
Your team should be proud! The application is now deployed an application to the cloud!
|
||||
|
||||
You may remember the primary workflow for the application is to allow users to come up with names for different dogs. Because users will want to see the names they create, your team will need a way to enable authentication.
|
||||
|
||||
## The Azure Service
|
||||
|
||||
[Authentication and authorization](https://docs.microsoft.com/azure/static-web-apps/authentication-authorization?WT.mc_id=academic-28005-chrhar) are built-in to Azure Static Web Apps. No additional configuration is required to allow users to login with Azure Active Directory, Twitter or GitHub authentication. You can add a link to the login page, and then add the necessary code to determine the name of the user and any additional actions you may wish to take.
|
||||
|
||||
## Application notes
|
||||
|
||||
Open *src/routes/index.svelte*, and notice the following JavaScript function:
|
||||
|
||||
```javascript
|
||||
async function getUserInfo() {
|
||||
// retrieve the current user from Azure Static Web Apps
|
||||
const response = await fetch("/.auth/me");
|
||||
// get the JSON
|
||||
const payload = await response.json();
|
||||
// clientPrincipal is the property with the information
|
||||
if (payload.clientPrincipal) {
|
||||
// user is authenticated
|
||||
// userDetails contains the username
|
||||
return payload.clientPrincipal.userDetails;
|
||||
} else {
|
||||
// if clientPrincipal is null, the session is anonymous
|
||||
return null;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This helper function is used to retrieve the current user. The key property is `clientPrincipal`. If `clientPrincipal` is `null`, it means the user is anonymous; if it contains a value the user has authenticated. The path */.auth/me* is built-in to Azure Static Web Apps to provide access to the current user.
|
||||
|
||||
Further down in *index.svelte*, you will notice the following code to display the user or a link to the login page:
|
||||
|
||||
```html
|
||||
{#await getUserInfo()}
|
||||
Getting user info...
|
||||
{:then username}
|
||||
{#if username}
|
||||
<div class="center">
|
||||
Welcome, {username}! See your
|
||||
<a href="named-dogs">named dogs</a>!
|
||||
</div>
|
||||
|
||||
<!-- snipped code to display buttons -->
|
||||
{:else}
|
||||
<div class="center">
|
||||
<a href="/login" class="center">Login to name the dogs!</a>
|
||||
</div>
|
||||
<!-- snipped code to display generic message -->
|
||||
{/if}
|
||||
{/await}
|
||||
```
|
||||
|
||||
The Svelte `await` is used to call `getUserInfo()`. After it's loaded, we look at the `username`. If a username exists, we display it and the buttons for naming dogs. If there is no `username`, the user is anonymous.
|
||||
|
||||
Notice the link to */login*. This will become **the key to this goal**. Your team will make the appropriate application updates to ensure */login* displays a login page.
|
||||
|
||||
> Note: The [await](https://svelte.dev/tutorial/await-blocks) and [if/else](https://svelte.dev/tutorial/if-blocks) blocks are part of [Svelte](https://svelte.dev). `await` allows you to display a loading message when making a potentially lengthy call (like accessing a server resource). `if/else` allows you to integrate logic into your HTML.
|
||||
|
||||
## Success criteria
|
||||
|
||||
Your team will make the necessary updates to the application to enable authentication. Your team will have achieved this goal when the following success criteria are met:
|
||||
|
||||
- The necessary updates have been applied to enable GitHub authentication via the path **/login**
|
||||
- After the updated site is deployed, a user can complete the following flow:
|
||||
- Navigate to the index page
|
||||
- Select the *Login to name the dogs!* link
|
||||
- Be redirected to the GitHub authentication page
|
||||
- Be redirected to the index page
|
||||
|
||||
## Validation
|
||||
|
||||
To validate your lab with the automated tool, enter the contents of *staticwebapp.config.json* into the [validation tool](https://ashy-mushroom-0609d7c10.azurestaticapps.net/).
|
||||
|
||||
## Resources resources
|
||||
|
||||
Your team might find these resources helpful:
|
||||
|
||||
- [Azure Static Web Apps - Login](https://docs.microsoft.com/azure/static-web-apps/authentication-authorization#login?WT.mc_id=academic-28005-chrhar)
|
||||
- [Configure Azure Static Web Apps](https://docs.microsoft.com/azure/static-web-apps/configuration?WT.mc_id=academic-28005-chrhar)
|
||||
- [Access user information in Azure Static Web Apps](https://docs.microsoft.com/azure/static-web-apps/user-information?tabs=javascript&WT.mc_id=academic-28005-chrhar)
|
||||
- [Troubleshooting deployment and runtime errors](https://docs.microsoft.com/azure/static-web-apps/troubleshooting?WT.mc_id=academic-28005-chrhar)
|
||||
|
||||
## Tips
|
||||
|
||||
- The only file which needs to be modified is *staticwebapp.config.json*
|
||||
- Remember to push updates to the main branch to redeploy to Azure Static Web Apps
|
||||
- Naming dogs **will not** work yet; your team will enable the database for the next goal
|
||||
|
||||
## Final result
|
||||
|
||||
After enabling authentication and logging in via GitHub, the page should look like this:
|
||||
|
||||
![Screenshot of the starting page, showing a textbox where you can name the dog, and the header What would you call this cute Pyrenees dog?](./media/authentication.png)
|
||||
|
||||
## Next challenge
|
||||
|
||||
Once your team has configured authentication and authorization, you can [add a database](./3-database.md).
|
|
@ -0,0 +1,51 @@
|
|||
# Goal 2 - Local development
|
||||
|
||||
Your team should be proud! You've deployed the site to the cloud, created a database, and made the appropriate updates to get everything connected.
|
||||
|
||||
Of course, you typically want to develop locally rather than on a production site in the cloud. As a result, the next goal is to setup local development.
|
||||
|
||||
## The goal
|
||||
|
||||
Each member of your team will now clone the project and run it locally. You will use Git and GitHub to clone the project, install any required software, and run the appropriate scripts to start the site.
|
||||
|
||||
## Application notes
|
||||
|
||||
The template uses the [Azure Static Web Apps CLI](https://techcommunity.microsoft.com/t5/apps-on-azure/introducing-the-azure-static-web-apps-cli/ba-p/2257581?WT.mc_id=academic-28005-chrhar) to emulate Azure Static Web Apps. The Azure Static Web Apps CLI handles integration between the client and Azure Functions running locally on your system, and emulates authentication. When you run the site locally and login, you will be presented with a screen asking you to provide a user ID, username and roles. You can use whatever values you wish for testing locally.
|
||||
|
||||
For the local database [MongoDB In-Memory Server](https://github.com/nodkz/mongodb-memory-server) is used. This means whenever you restart the project any data in the database is removed. If you wish you can install [MongoDB](https://www.mongodb.com/try/download/community) locally and update [local.settings.json](https://docs.microsoft.com/azure/azure-functions/functions-run-local?tabs=v3%2Cwindows%2Cnode%2Cportal%2Cbash%2Ckeda&WT.mc_id=academic-28005-chrhar#local-settings) with the appropriate connection string. **PLEASE NOTE**, for purposes of this workshop, you are **NOT** required to setup MongoDB locally.
|
||||
|
||||
## Success criteria
|
||||
|
||||
Your team will have successfully completed this goal when everyone can:
|
||||
|
||||
- Run the project locally
|
||||
- Login to the site running locally with a test account
|
||||
- Create and mark tasks as complete
|
||||
|
||||
## Resources resources
|
||||
|
||||
Your team might find these resources helpful:
|
||||
|
||||
- [Azure Static Web Apps CLI](https://techcommunity.microsoft.com/t5/apps-on-azure/introducing-the-azure-static-web-apps-cli/ba-p/2257581?WT.mc_id=academic-28005-chrhar)
|
||||
- [Local Setup - Static Web Apps - Mongoose starter](https://github.com/staticwebdev/mongoose-starter/blob/main/local-setup.md)
|
||||
|
||||
## Validation
|
||||
|
||||
To validate you have successfully setup the project locally, walk through the following steps:
|
||||
|
||||
1. Navigate to [http://localhost:4280](http://localhost:4280)
|
||||
1. Login to the site to see the list of tasks
|
||||
1. Provide a username and select **Login**
|
||||
1. Ensure the username displays
|
||||
1. Add a new task and select **Add task**
|
||||
1. Notice the page updates with the new task
|
||||
|
||||
## Final result
|
||||
|
||||
After enabling authentication and logging in via GitHub, the page should look like this:
|
||||
|
||||
![Screenshot of the project with GeekTrainer as the username and a task named Test](./media/tasks.png)
|
||||
|
||||
## Next challenge
|
||||
|
||||
Once your team has setup the project for local development, it's time to start [making changes](3-modify.md)!
|
|
@ -1,63 +0,0 @@
|
|||
# Goal 3: Create and configure a cloud-based database
|
||||
|
||||
Congratulations on enabling authentication for the application! Authentication commonly a key component to any web project.
|
||||
|
||||
Similarly, almost every web application will need some form of a database. If you remember the primary workflow again, the goal is to have users create names for the dogs, which will then be saved to a database. The time has come for your team to create and configure the database.
|
||||
|
||||
## The Azure Service
|
||||
|
||||
[Azure Cosmos DB](https://docs.microsoft.com/azure/cosmos-db/introduction?WT.mc_id=academic-28005-chrhar) is a document or [NoSQL](https://en.wikipedia.org/wiki/NoSQL) database service. Cosmos DB provides different APIs you can use to access it, including an [API for MongoDB](https://docs.microsoft.com/azure/cosmos-db/introduction?WT.mc_id=academic-28005-chrhar), which allows the Node.js MongoDB client to interact with it. Most recently, [Cosmos DB serverless](https://docs.microsoft.com/azure/cosmos-db/serverless?WT.mc_id=academic-28005-chrhar) was released, which similar to other serverless products charges are based on usage. Your team will create a Cosmos DB account and configure the application to use your new Cosmos DB deployment.
|
||||
|
||||
## Application notes
|
||||
|
||||
Open */api/helpers.js*. This file contains a couple of functions to aid the development of the server-side portion of this project. The key function is `getMongoClient`.
|
||||
|
||||
```javascript
|
||||
getMongoClient() {
|
||||
const { MongoClient } = require("mongodb");
|
||||
const uri = process.env.MONGO_CONNECTION_STRING;
|
||||
const client = new MongoClient(uri, {
|
||||
useNewUrlParser: true,
|
||||
useUnifiedTopology: true,
|
||||
});
|
||||
return client;
|
||||
}
|
||||
```
|
||||
|
||||
`getMongoClient` contains the code to connect to the database. Notice `process.env.MONGO_CONNECTION_STRING`, which is using [process.env](https://nodejs.org/dist/latest-v14.x/docs/api/process.html#process_process_env) to read an environment variable. After creating the database on Azure, your team will need to ensure the environment variable is set correctly on the static web app in Azure.
|
||||
|
||||
When creating your team's instance of Cosmos DB, use the Serverless option. This will allow you to pay for usage rather than a fix fee. For this sample application, the costs will be extremely cheap (under $1 US). Fortunately, since you will be using [Azure for Students](https://aka.ms/a4s), you have free credit!
|
||||
|
||||
## Success criteria
|
||||
|
||||
Your team will create the necessary resources and make the necessary updates in Azure to enable the application to access a Cosmos DB database. Your team will have achieved this goal when the following success criteria are met:
|
||||
|
||||
- A Cosmos DB Account has been created
|
||||
- The static web app configuration has been updated in Azure
|
||||
- In the website, you are able to perform the following tasks:
|
||||
- Login to the site
|
||||
- Name a dog
|
||||
- Navigate to the favorites page by selecting *review the list* to see the dogs you named
|
||||
|
||||
## Validation
|
||||
|
||||
Have a mentor check your site to ensure everything has been completed!
|
||||
|
||||
## Resources
|
||||
|
||||
Your team might find these resources helpful:
|
||||
|
||||
- [Create an Azure Cosmos DB account](https://docs.microsoft.com/azure/cosmos-db/create-cosmosdb-resources-portal#create-an-azure-cosmos-db-account?WT.mc_id=academic-28005-chrhar)
|
||||
- [Get the MongoDB connection string by using the quick start](https://docs.microsoft.com/azure/cosmos-db/connect-mongodb-account#get-the-mongodb-connection-string-by-using-the-quick-start?WT.mc_id=academic-28005-chrhar)
|
||||
- [Configure application settings for Azure Static Web Apps](https://docs.microsoft.com/azure/static-web-apps/application-settings?WT.mc_id=academic-28005-chrhar)
|
||||
- [Troubleshooting deployment and runtime errors](https://docs.microsoft.com/azure/static-web-apps/troubleshooting?WT.mc_id=academic-28005-chrhar)
|
||||
|
||||
## Tips
|
||||
|
||||
- The application will automatically create a database and collection to store data; the only resource your team needs to [create is an Azure Cosmos DB account](https://docs.microsoft.com/azure/cosmos-db/create-cosmosdb-resources-portal#create-an-azure-cosmos-db-accoun?WT.mc_id=academic-28005-chrhart)
|
||||
|
||||
## Final result
|
||||
|
||||
After creating database and configuring the application, you should now be able to login, name a dog, and see the list of all dogs you've named.
|
||||
|
||||
![Screenshot of the named dogs page, showing the list of named dogs with a Pyrenees named as Steve](./media/named-dogs.png)
|
|
@ -0,0 +1,46 @@
|
|||
# Goal 3 - Modifying the site
|
||||
|
||||
Congratulations on setting up the project for local development! Now that you've got it locally it's time to start making changes.
|
||||
|
||||
Because the shelter wants to allow adopters to use the site to manage tasks related to pet adoption, they would like to update the header and push those changes to the cloud.
|
||||
|
||||
## The goal
|
||||
|
||||
Your team will finish by making a change to the site. Your team will update the header text to read "Pet Adoption Tasks", and redeploy the site.
|
||||
|
||||
## The Azure Service
|
||||
|
||||
Azure Static Web Apps uses [GitHub Actions](https://docs.microsoft.com/azure/static-web-apps/build-configuration?tabs=github-actions&WT.mc_id=academic-28005-chrhar) to manage deployment. Whenever a pull request (PR) or merge is made into the main branch the action is triggered and a new deployment starts. If code is merged into the branch, the deployment is pushed to the production site; PRs [generate a new staging environment](https://docs.microsoft.com/azure/static-web-apps/review-publish-pull-requests?WT.mc_id=academic-28005-chrhar).
|
||||
|
||||
## Application notes
|
||||
|
||||
The client files are contained in the **public** folder. **index.html** is the HTML used to display the index page on the site.
|
||||
|
||||
## Success criteria
|
||||
|
||||
To successfully complete this goal, your team will:
|
||||
|
||||
- Update the `h1` header on the index page to read **Pet Adoption Tasks**
|
||||
- Redeploy the site to Azure Static Web Apps
|
||||
|
||||
## Tips
|
||||
|
||||
A good habit to get into when modifying code is to create a new branch, make modifications, create a PR into the main branch, and then merge. However, for this workshop you can push straight to main.
|
||||
|
||||
## Resources
|
||||
|
||||
Your team might find these resources helpful:
|
||||
|
||||
- [Review pull requests in pre-production environments in Azure Static Web Apps](https://docs.microsoft.com/azure/static-web-apps/review-publish-pull-requests?WT.mc_id=academic-28005-chrhar)
|
||||
|
||||
## Validation
|
||||
|
||||
To validate your team's work with the [automated tool](https://ashy-mushroom-0609d7c10.azurestaticapps.net/), re-enter the URL on Azure Static Web Apps into the tool.
|
||||
|
||||
## Congratulations
|
||||
|
||||
Congratulations on successfully completing the workshop! Your team now has a template and deployment model to use for creating a website. If you wish to continue to explore Azure Static Web Apps:
|
||||
|
||||
- [Set up a custom domain with free certificate in Azure Static Web Apps](https://docs.microsoft.com/azure/static-web-apps/custom-domain?tabs=azure-dns?WT.mc_id=academic-28005-chrhar)
|
||||
- [Troubleshooting deployment and runtime errors](https://docs.microsoft.com/azure/static-web-apps/troubleshooting?WT.mc_id=academic-28005-chrhar)
|
||||
- [Publish an Angular, React, Svelte, or Vue JavaScript app with Azure Static Web Apps](https://docs.microsoft.com/learn/modules/publish-app-service-static-web-app-api?WT.mc_id=academic-28005-chrhar)
|
|
@ -1,47 +0,0 @@
|
|||
# Running the application locally
|
||||
|
||||
As highlighted, your team does not have to run the application locally to successfully complete the workshop. However, if you want to setup your system, you'll need to perform one local install, and make a note about
|
||||
|
||||
## Install MongoDB
|
||||
|
||||
The workshop application uses MongoDB API. To perform local development, you will need MongoDB installed.
|
||||
|
||||
- [MongoDB Community Server](https://www.mongodb.com/try/download/community)
|
||||
- [Install MongoDB Community Server on Windows](https://docs.mongodb.com/manual/tutorial/install-mongodb-on-windows/)
|
||||
- [Install MongoDB Community Server on macOS with Brew](https://docs.mongodb.com/manual/tutorial/install-mongodb-on-os-x/)
|
||||
- [Install MongoDB Community Server on Linux](https://docs.mongodb.com/manual/tutorial/install-mongodb-on-ubuntu/)
|
||||
- Note: If you are using Windows Subsystem for Linux (WSL) with Ubuntu, you can install MongoDB using the following commands
|
||||
|
||||
```bash
|
||||
sudo apt-get install mongodb
|
||||
service mongodb start # Start mongodb
|
||||
```
|
||||
|
||||
> **IMPORTANT**: Make sure MongoDB is started after you install the service.
|
||||
|
||||
## Starting the application
|
||||
|
||||
After you have downloaded the source code locally, you are all set to run it! You'll rename one settings file, and then start the server!
|
||||
|
||||
1. Inside Visual Studio Code, locate the file named *starter-settings.json*. Rename the file to *local.settings.json*.
|
||||
|
||||
*local.settings.json* contains environmental variables used by Azure Functions. For the starter project, it contains the connection string to the database, MongoDB running locally on your machine.
|
||||
|
||||
1. Inside Visual Studio Code, open a new terminal by selecting *Terminal* > *New Terminal*.
|
||||
1. Run the following commands to change to install the packages for both the api and client, and start the development server:
|
||||
|
||||
```bash
|
||||
cd api
|
||||
npm install
|
||||
cd ..
|
||||
npm install
|
||||
npm run dev
|
||||
```
|
||||
|
||||
After the scripts have run, your dev server will be started
|
||||
|
||||
1. Open the website by navigating to [http://localhost:4280](http://localhost:4280)
|
||||
|
||||
![Screenshot of the starting page, showing a link to login, a picture of a dog with the heading Isn't this a cute Pekinese dog?](./media/starter-page.png)
|
||||
|
||||
> A note about authentication: The project uses the [Azure Static Web Apps CLI](https://github.com/Azure/static-web-apps-cli#azure-static-web-apps-cli-preview) to host the application. When you click "login", you will be presented with a page where you can provide your own username and ID. This allows you to simulate authentication without having to actually login to GitHub or another provider.
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
До Ширина: | Высота: | Размер: 428 KiB |
Двоичные данные
goals/media/authentication.png
Двоичные данные
goals/media/authentication.png
Двоичный файл не отображается.
До Ширина: | Высота: | Размер: 271 KiB |
Двоичные данные
goals/media/named-dogs.png
Двоичные данные
goals/media/named-dogs.png
Двоичный файл не отображается.
До Ширина: | Высота: | Размер: 8.6 KiB |
Двоичные данные
goals/media/starter-page.png
Двоичные данные
goals/media/starter-page.png
Двоичный файл не отображается.
До Ширина: | Высота: | Размер: 453 KiB |
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 5.6 KiB |
|
@ -1,9 +0,0 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"$lib/*": ["src/lib/*"]
|
||||
}
|
||||
},
|
||||
"include": ["src/**/*.d.ts", "src/**/*.js", "src/**/*.svelte"]
|
||||
}
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
16
package.json
16
package.json
|
@ -1,16 +0,0 @@
|
|||
{
|
||||
"name": "the-loved-mutt",
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"dev": "svelte-kit dev & swa start http://localhost:3000 --api ./api",
|
||||
"build": "svelte-kit build",
|
||||
"preview": "svelte-kit preview"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@azure/static-web-apps-cli": "^0.4.0",
|
||||
"@sveltejs/adapter-static": "^1.0.0-next.13",
|
||||
"@sveltejs/kit": "next",
|
||||
"svelte": "^3.34.0"
|
||||
},
|
||||
"type": "module"
|
||||
}
|
14
src/app.html
14
src/app.html
|
@ -1,14 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<script src="https://kit.fontawesome.com/adcb63a956.js" crossorigin="anonymous"></script>
|
||||
<link rel="stylesheet" href="/style.css">
|
||||
%svelte.head%
|
||||
</head>
|
||||
<body>
|
||||
<div id="svelte">%svelte.body%</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1 +0,0 @@
|
|||
/// <reference types="@sveltejs/kit" />
|
|
@ -1,157 +0,0 @@
|
|||
<script>
|
||||
let imageUrl = '';
|
||||
let dogType = '';
|
||||
let message = '';
|
||||
let name = '';
|
||||
|
||||
import { onMount } from "svelte";
|
||||
|
||||
// Load first dog for display
|
||||
onMount(loadDog);
|
||||
|
||||
async function loadDog() {
|
||||
const result = await fetch(
|
||||
"https://dog.ceo/api/breeds/image/random/1/alt"
|
||||
);
|
||||
const imageInfo = (await result.json()).message[0];
|
||||
imageUrl = imageInfo.url;
|
||||
dogType = imageInfo.altText;
|
||||
if (dogType.endsWith("dog dog")) // removes dog dog
|
||||
dogType = imageInfo.altText.substring(
|
||||
0, imageInfo.altText.lastIndexOf(" ")
|
||||
);
|
||||
}
|
||||
|
||||
async function nameDog() {
|
||||
message = 'Saving dog...';
|
||||
const result = await fetch("/api/save-dog", {
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
method: "POST",
|
||||
body: JSON.stringify({ imageUrl, dogType, name }),
|
||||
});
|
||||
const json = await result.json();
|
||||
message = `Saved ${dogType} as ${name}`;
|
||||
name = '';
|
||||
await loadDog();
|
||||
}
|
||||
|
||||
async function nextDog() {
|
||||
message = "They're all good dogs";
|
||||
await loadDog();
|
||||
}
|
||||
|
||||
async function getUserInfo() {
|
||||
// retrieve the current user from Azure Static Web Apps
|
||||
const response = await fetch("/.auth/me");
|
||||
// get the JSON
|
||||
const payload = await response.json();
|
||||
// clientPrincipal is the property with the information
|
||||
if (payload.clientPrincipal) {
|
||||
// user is authenticated
|
||||
// userDetails contains the username
|
||||
return payload.clientPrincipal.userDetails;
|
||||
} else {
|
||||
// if clientPrincipal is null, the session is anonymous
|
||||
return null;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Dog shelter sample site</title>
|
||||
</svelte:head>
|
||||
<article class="index">
|
||||
<h2>Name dogs!</h2>
|
||||
<p>
|
||||
One way families can begin to get excited about adopting a dog is to
|
||||
begin thinking of possible names. After logging in, you can come up with
|
||||
names you think would work! Later on, you can <a href="named-dogs"
|
||||
>review the list</a
|
||||
> of names you came up with.
|
||||
</p>
|
||||
|
||||
{#if message}
|
||||
<div class="message">{message}</div>
|
||||
{/if}
|
||||
|
||||
{#await getUserInfo()}
|
||||
Getting user info...
|
||||
{:then username}
|
||||
{#if username}
|
||||
<div class="center">
|
||||
Welcome, {username}! See your
|
||||
<a href="named-dogs">named dogs</a>!
|
||||
</div>
|
||||
|
||||
<div class="header center">
|
||||
What would you call this cute {dogType}?
|
||||
</div>
|
||||
|
||||
<div class="vote-button-container center">
|
||||
<input class="name-input" type="text" bind:value={name} />
|
||||
<button class="vote-button" on:click={nameDog}>
|
||||
<span class="fas fa-vote-yea icon" />
|
||||
Save name!
|
||||
</button>
|
||||
<button class="vote-button" on:click={nextDog}>
|
||||
<span class="fas fa-forward icon" />
|
||||
Cute dog! But but best for someone else.
|
||||
</button>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="center">
|
||||
<a href="/.auth/login/github" class="center">Login to name the dogs!</a>
|
||||
</div>
|
||||
<div class="header center">
|
||||
Isn't this a cute {dogType}?
|
||||
</div>
|
||||
{/if}
|
||||
{/await}
|
||||
<div>
|
||||
<img src={imageUrl} alt={dogType} />
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<style>
|
||||
img {
|
||||
width: 90%;
|
||||
margin: auto;
|
||||
}
|
||||
.message {
|
||||
border-radius: 5px;
|
||||
border-style: solid;
|
||||
border-color: black;
|
||||
border-width: 2px;
|
||||
margin-bottom: 10px;
|
||||
padding: 5px;
|
||||
background-color: lightgreen;
|
||||
text-align: center;
|
||||
}
|
||||
.icon {
|
||||
display: block;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
.vote-button {
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
display: flexbox;
|
||||
vertical-align: top;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.vote-button-container {
|
||||
vertical-align: middle;
|
||||
}
|
||||
.header {
|
||||
font-size: 1.5rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
.center {
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.name-input {
|
||||
font-size: 1.8em;
|
||||
}
|
||||
</style>
|
|
@ -1,23 +0,0 @@
|
|||
<svelte:head>
|
||||
<title>Dog shelter sample site</title>
|
||||
</svelte:head>
|
||||
|
||||
<script>
|
||||
async function loadNamedDogs() {
|
||||
const response = await fetch('/api/named-dogs');
|
||||
return (await response.json()).namedDogs;
|
||||
}
|
||||
</script>
|
||||
|
||||
<h1>Your named dogs</h1>
|
||||
<div>Here's the list of all the dog names you've created</div>
|
||||
|
||||
{#await loadNamedDogs()}
|
||||
...loading named dogs
|
||||
{:then namedDogs}
|
||||
<ul>
|
||||
{#each namedDogs as dog}
|
||||
<li><a href={dog.imageUrl}>{dog.dogType} as {dog.name}</a></li>
|
||||
{/each}
|
||||
</ul>
|
||||
{/await}
|
Двоичные данные
static/favicon.ico
Двоичные данные
static/favicon.ico
Двоичный файл не отображается.
До Ширина: | Высота: | Размер: 1.1 KiB |
|
@ -1,5 +0,0 @@
|
|||
body {
|
||||
font-family: "Lucida Sans", "Lucida Sans Regular", "Lucida Grande",
|
||||
"Lucida Sans Unicode", Geneva, Verdana, sans-serif;
|
||||
margin: 0 5%;
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
{
|
||||
"routes": [
|
||||
{
|
||||
"route": "/logout",
|
||||
"redirect": "/.auth/logout"
|
||||
},
|
||||
{
|
||||
"route": "/named-dogs",
|
||||
"allowedRoles": [
|
||||
"authenticated"
|
||||
]
|
||||
},
|
||||
{
|
||||
"route": "/api/named-dogs",
|
||||
"allowedRoles": [
|
||||
"authenticated"
|
||||
]
|
||||
}
|
||||
],
|
||||
"responseOverrides": {
|
||||
"401": {
|
||||
"statusCode": 302,
|
||||
"redirect": "/login"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
// svelte.config.js
|
||||
import adapter from '@sveltejs/adapter-static';
|
||||
|
||||
export default {
|
||||
kit: {
|
||||
adapter: adapter({
|
||||
// default options are shown
|
||||
pages: 'build',
|
||||
assets: 'build',
|
||||
fallback: null
|
||||
}),
|
||||
files: {
|
||||
assets: 'static'
|
||||
},
|
||||
router: false,
|
||||
}
|
||||
};
|
Загрузка…
Ссылка в новой задаче