102 |
107 |
108 | );
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Getting Started
2 |
3 | In the root directory of the project...
4 |
5 | 1. Install node modules `yarn install` or `npm install`.
6 | 2. Start development server `yarn start` or `npm start`.
7 |
8 | ## Next Steps
9 |
10 | ### Sample Data
11 |
12 | Replace the sample data stored in /server/sampleData.js.
13 | Replace the default images stored in /src/images.
14 |
15 | ### Adding a New Page
16 |
17 | 1. Create a folder in `/src/components` with your react components.
18 | 2. Add a route for your page to `/src/App.js`.
19 | 3. Add a button to the navigation bar in `/src/components/NavBar/index.js`.
20 |
21 | ### Deployment
22 |
23 | If you selected Azure App Service when creating your project, follow these steps:
24 |
25 | 1. Press `Ctrl + Shift + P` in Windows/Linux or `Shift ⇧ + Command ⌘ + P` in Mac and type/select `Web Template Studio: Deploy App` to start deploying your app.
26 | 2. Once the deployment is done, click "Browse website" in the notification window on the lower right corner to check out your newly deployed app.
27 |
28 | If you did not select Azure App Service and want to create a new Azure App Service web app, follow these steps:
29 |
30 | 1. Press `Ctrl + Shift + P` in Windows/Linux or `Shift ⇧ + Command ⌘ + P` in Mac and type/select `Azure App Service: Create New Web App...` to create a new web app.
31 | - Select your subscription
32 | - Enter your web app name
33 | - Select Linux as your OS
34 | - Select Node.js 10.14 for a Node/Express application, Python 3.7 for a Flask application
35 | 2. Press `Ctrl + Shift + P` in Windows/Linux or `Shift ⇧ + Command ⌘ + P` in Mac and type/select `Web Template Studio: Deploy App` to start deploying your app.
36 | - You will have to select the same subscription again
37 | - Find the web app that you've just created
38 | - Click "Yes" in the notification window on the lower right corner (build prompt)
39 | - Click "Deploy" on the window pop-up (deploy window)
40 | - Click "Yes" on the notification window on the lower right corner (default prompt)
41 | 3. Once the deployment is done, click "Browse website" in the notification window on the lower right corner to check out your newly deployed app.
42 |
43 | Consider adding authentication and securing back-end API's by following [Azure App Service Security](https://docs.microsoft.com/en-us/azure/app-service/overview-security).
44 |
45 | Full documentation for deployment to Azure App Service can be found here: [Deployment Docs](https://github.com/Microsoft/WebTemplateStudio/blob/dev/docs/deployment.md).
46 |
47 | ## File Structure
48 |
49 | The front-end is based on [create-react-app](https://github.com/facebook/create-react-app).
50 |
51 | The back-end is based on [Express Generator](https://expressjs.com/en/starter/generator.html).
52 |
53 | The front-end is served on http://localhost:3000/ and the back-end on http://localhost:3001/.
54 |
55 | ```
56 | .
57 | ├── server/ - Express server that provides API routes and serves front-end
58 | │ ├── routes/ - Handles API calls for routes
59 | │ ├── app.js - Adds middleware to the express server
60 | │ ├── sampleData.js - Contains all sample text data for generate pages
61 | │ ├── constants.js - Defines the constants for the endpoints and port
62 | │ └── server.js - Configures Port and HTTP Server
63 | ├── src - React front-end
64 | │ ├── components - React components for each page
65 | │ ├── App.jsx - React routing
66 | │ └── index.jsx - React root component
67 | └── README.md
68 | ```
69 |
70 | ## Additional Documentation
71 |
72 | - React - https://reactjs.org/
73 | - React Router - https://reacttraining.com/react-router/
74 |
75 | - Bootstrap CSS - https://getbootstrap.com/
76 | - Express - https://expressjs.com/
77 |
78 |
79 |
--------------------------------------------------------------------------------
/server/sampleData.js:
--------------------------------------------------------------------------------
1 | const shortLoremIpsum = `Lorem id sint aliqua tempor tempor sit. Ad dolor dolor ut nulla mollit dolore non eiusmod Lorem tempor nisi cillum.`;
2 | const sampleData = {};
3 | const longLoremIpsum = `Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
4 | tempor incididunt ut labore et dolore magna aliqua. Rhoncus dolor purus
5 | non enim praesent elementum facilisis leo vel. Risus at ultrices mi
6 | tempus imperdiet. Semper risus in hendrerit gravida rutrum quisque non
7 | tellus. Convallis convallis tellus id interdum velit laoreet id donec
8 | ultrices. Odio morbi quis commodo odio aenean sed adipiscing. Amet nisl
9 | suscipit adipiscing bibendum est ultricies integer quis. Cursus euismod
10 | quis viverra nibh cras. Metus vulputate eu scelerisque felis imperdiet
11 | proin fermentum leo. Mauris commodo quis imperdiet massa tincidunt. Cras
12 | tincidunt lobortis feugiat vivamus at augue. At augue eget arcu dictum
13 | varius duis at consectetur lorem. Velit sed ullamcorper morbi tincidunt.
14 | Lorem donec massa sapien faucibus et molestie ac.`;
15 |
16 | // This class holds sample data used by some generated pages to show how they can be used.
17 | // TODO: Delete this file once your app is using real data.
18 | sampleData.textAssets = [
19 | {
20 | shortDescription: shortLoremIpsum,
21 | longDescription: longLoremIpsum,
22 | title: 'Company A',
23 | status: 'Closed',
24 | shipTo: 'Francisco Pérez-Olaeta',
25 | orderTotal: 2490.0,
26 | orderDate: new Date(2017, 5, 24).toDateString(),
27 | id: 1
28 | },
29 | {
30 | shortDescription: shortLoremIpsum,
31 | longDescription: longLoremIpsum,
32 | title: 'Company B',
33 | status: 'Closed',
34 | shipTo: 'Soo Jung Lee',
35 | orderTotal: 1760.0,
36 | orderDate: new Date(2017, 5, 24).toDateString(),
37 | id: 2
38 | },
39 | {
40 | shortDescription: shortLoremIpsum,
41 | longDescription: longLoremIpsum,
42 | title: 'Company C',
43 | status: 'Shipped',
44 | shipTo: 'Run Liu',
45 | orderTotal: 665.0,
46 | orderDate: new Date(2017, 6, 3).toDateString(),
47 | id: 3
48 | },
49 | {
50 | shortDescription: shortLoremIpsum,
51 | longDescription: longLoremIpsum,
52 | title: 'Company D',
53 | status: 'Shipped',
54 | shipTo: 'Soo Jung Lee',
55 | orderTotal: 560.0,
56 | orderDate: new Date(2017, 6, 5).toDateString(),
57 | id: 4
58 | },
59 | {
60 | shortDescription: shortLoremIpsum,
61 | longDescription: longLoremIpsum,
62 | title: 'Company E',
63 | status: 'New',
64 | shipTo: 'John Rodman',
65 | orderTotal: 810.0,
66 | orderDate: new Date(2017, 6, 7).toDateString(),
67 | id: 5
68 | },
69 | {
70 | shortDescription: shortLoremIpsum,
71 | longDescription: longLoremIpsum,
72 | title: 'Company F',
73 | status: 'New',
74 | shipTo: 'Elizabeth Andersen',
75 | orderTotal: 196.5,
76 | orderDate: new Date(2017, 6, 7).toDateString(),
77 | id: 6
78 | },
79 | {
80 | shortDescription: shortLoremIpsum,
81 | longDescription: longLoremIpsum,
82 | title: 'Company G',
83 | status: 'Closed',
84 | shipTo: 'Peter Krschne',
85 | orderTotal: 270.0,
86 | orderDate: new Date(2017, 6, 11).toDateString(),
87 | id: 7
88 | },
89 | {
90 | shortDescription: shortLoremIpsum,
91 | longDescription: longLoremIpsum,
92 | title: 'Company H',
93 | status: 'Closed',
94 | shipTo: 'Sven Mortensen',
95 | orderTotal: 736.0,
96 | orderDate: new Date(2017, 6, 14).toDateString(),
97 | id: 8
98 | },
99 | {
100 | shortDescription: shortLoremIpsum,
101 | longDescription: longLoremIpsum,
102 | title: 'Company I',
103 | status: 'Shipped',
104 | shipTo: 'Anna Bedecs',
105 | orderTotal: 800.0,
106 | orderDate: new Date(2017, 6, 18).toDateString(),
107 | id: 9
108 | }
109 | ]
110 |
111 |
112 | module.exports = sampleData
113 |
--------------------------------------------------------------------------------
/src/registerServiceWorker.js:
--------------------------------------------------------------------------------
1 | // In production, we register a service worker to serve assets from local cache.
2 |
3 | // This lets the app load faster on subsequent visits in production, and gives
4 | // it offline capabilities. However, it also means that developers (and users)
5 | // will only see deployed updates on the "N+1" visit to a page, since previously
6 | // cached resources are updated in the background.
7 |
8 | // To learn more about the benefits of this model, read https://goo.gl/KwvDNy.
9 | // This link also includes instructions on opting out of this behavior.
10 |
11 | const isLocalhost = Boolean(
12 | window.location.hostname === 'localhost' ||
13 | // [::1] is the IPv6 localhost address.
14 | window.location.hostname === '[::1]' ||
15 | // 127.0.0.1/8 is considered localhost for IPv4.
16 | window.location.hostname.match(
17 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
18 | )
19 | )
20 |
21 | export default function register() {
22 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
23 | // The URL constructor is available in all browsers that support SW.
24 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location)
25 | if (publicUrl.origin !== window.location.origin) {
26 | // Our service worker won't work if PUBLIC_URL is on a different origin
27 | // from what our page is served on. This might happen if a CDN is used to
28 | // serve assets; see https://github.com/facebookincubator/create-react-app/issues/2374
29 | return
30 | }
31 |
32 | window.addEventListener('load', () => {
33 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`
34 |
35 | if (!isLocalhost) {
36 | // Is not local host. Just register service worker
37 | registerValidSW(swUrl)
38 | } else {
39 | // This is running on localhost. Lets check if a service worker still exists or not.
40 | checkValidServiceWorker(swUrl)
41 | }
42 | })
43 | }
44 | }
45 |
46 | function registerValidSW(swUrl) {
47 | navigator.serviceWorker
48 | .register(swUrl)
49 | .then(registration => {
50 | registration.onupdatefound = () => {
51 | const installingWorker = registration.installing;
52 | installingWorker.onstatechange = () => {
53 | if (installingWorker.state === 'installed') {
54 | if (navigator.serviceWorker.controller) {
55 | // At this point, the old content will have been purged and
56 | // the fresh content will have been added to the cache.
57 | // It's the perfect time to display a "New content is
58 | // available; please refresh." message in your web app.
59 | console.log('New content is available; please refresh.')
60 | } else {
61 | // At this point, everything has been precached.
62 | // It's the perfect time to display a
63 | // "Content is cached for offline use." message.
64 | console.log('Content is cached for offline use.')
65 | }
66 | }
67 | }
68 | }
69 | })
70 | .catch(error => {
71 | console.error('Error during service worker registration:', error)
72 | })
73 | }
74 |
75 | function checkValidServiceWorker(swUrl) {
76 | // Check if the service worker can be found. If it can't reload the page.
77 | fetch(swUrl)
78 | .then(response => {
79 | // Ensure service worker exists, and that we really are getting a JS file.
80 | if (
81 | response.status === 404 ||
82 | response.headers.get('content-type').indexOf('javascript') === -1
83 | ) {
84 | // No service worker found. Probably a different app. Reload the page.
85 | navigator.serviceWorker.ready.then(registration => {
86 | registration.unregister().then(() => {
87 | window.location.reload()
88 | })
89 | })
90 | } else {
91 | // Service worker found. Proceed as normal.
92 | registerValidSW(swUrl)
93 | }
94 | })
95 | .catch(() => {
96 | console.log(
97 | 'No internet connection found. App is running in offline mode.'
98 | )
99 | })
100 | }
101 |
102 | export function unregister() {
103 | if ('serviceWorker' in navigator) {
104 | navigator.serviceWorker.ready.then(registration => {
105 | registration.unregister()
106 | })
107 | }
108 | }
109 |
--------------------------------------------------------------------------------