diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..f6b35a0 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,15 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "chrome", + "request": "launch", + "name": "Launch Chrome against localhost", + "url": "http://localhost:3000", + "webRoot": "${workspaceFolder}" + } + ] +} \ No newline at end of file diff --git a/README.md b/README.md index 523d9c6..385559b 100644 --- a/README.md +++ b/README.md @@ -17,8 +17,10 @@ This is a simple react js hooks starter project that is using Azure AD to authen ```text // .env.development.local REACT_APP_ID={Application (client) ID created above} + REACT_APP_AUTHORITY=https://login.microsoftonline.com/{Azure tenant id that will match the tenant you created the app registration in} REACT_APP_REDIRECT_URL=http://localhost:3000 - REACT_APP_API_BASE_URL=https://lws-lagoonapis-fa-sbx.azurewebsites.net/api/ + REACT_APP_API_BASE_URL=https://jsonplaceholder.typicode.com/ + ``` 4. Run the following commands @@ -26,4 +28,12 @@ This is a simple react js hooks starter project that is using Azure AD to authen ```bash $npm install $npm start - ``` \ No newline at end of file + ``` + +5. Login and start clicking + +## Additional Info + +This project is using the JSONPlaceHolder API, which can be found here https://jsonplaceholder.typicode.com, to pull in random sample data to play with. A couple of important things to note about this data source: + 1. It's read-only. It will provide fakes for inserts and updates, but you aren't really changing the source. For example, if you create a new post and then try to edit that post, it will fail since the post you created was just a fake. + 2. Actually there was only one important thing to note about using this data... \ No newline at end of file diff --git a/package.json b/package.json index 04a1678..94eadee 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "reactstrap": "^8.4.1" }, "scripts": { - "start": "react-scripts start", + "start": "PORT=3000 react-scripts start", "build": "react-scripts build", "test": "react-scripts test", "eject": "react-scripts eject", diff --git a/public/index.html b/public/index.html index 4cdf1e0..964a633 100644 --- a/public/index.html +++ b/public/index.html @@ -2,7 +2,7 @@ - + - Lagoon WES + React Azure Starter diff --git a/src/components/app/app.js b/src/components/app/app.js index 5e4ca61..47b8568 100644 --- a/src/components/app/app.js +++ b/src/components/app/app.js @@ -10,7 +10,6 @@ import { UserAgentApplication } from 'msal'; import { getUserDetails, getUserPhoto, getUserGroups } from '../utils/graph-service'; import Calendar from '../calendar/calendar'; import Posts from '../posts/post'; -import Facility from '../facility/facility'; import { library } from '@fortawesome/fontawesome-svg-core'; import { faCheckCircle, faQuestionCircle, faExclamationCircle } from '@fortawesome/free-solid-svg-icons' @@ -85,7 +84,10 @@ class App extends Component { } isUserInAdminRole(userRoles) { - return userRoles.some(userRole => userRole.id === config.isAdminGroupId); + //this is the check for user groups, but it is commented out so we can make the buttons work for this sample, in the event that you use this code, + //you will need to create a group for admin access and grant admin consent to the group.read.all scope for the app in azure AD + //return userRoles.some(userRole => userRole.id === config.isAdminGroupId); + return true; } async getUserProfile() { @@ -150,21 +152,15 @@ class App extends Component { user={this.state.user}/> {notify} - - - } /> - - - } /> - } /> - } /> + + + } /> + + + } /> + + + } /> diff --git a/src/components/facility/facility-upsert.js b/src/components/facility/facility-upsert.js deleted file mode 100644 index 4187dff..0000000 --- a/src/components/facility/facility-upsert.js +++ /dev/null @@ -1,133 +0,0 @@ -import React, {useState} from 'react'; -import {Button,Form,FormGroup,Label,Input,FormFeedback} from 'reactstrap'; -import NotifyUser from '../packages/notify-user'; -import { upsertFacilities } from '../utils/api-service'; - -const UpsertFacility = (props) => { - const [error,setError] = useState(null); - const [facility, setFacility] = useState(props.facility); - const [validFields, setValidFields] = useState({facilityName:true,operator:true}); - - const onChange = (event) => { - const value = event.target.type === "checkbox" ? event.target.checked : event.target.value; - const name = event.target.name; - const optionSelectText = event.target.type === "select-one" ? event.target.options[event.target.selectedIndex].text : ''; - - //special logic for system object - if (name === "system") { - var systemObj = {systemId: value, systemName: optionSelectText}; - setFacility({...facility, system: systemObj}); - } else { - setFacility({...facility, [name]: value}); - } - checkInputValidity(name,value); - } - - const callUpsertFacilitiesApi = async() => { - try { - if (props.isAuthenticated) { - var facilities = [facility]; - var results = await upsertFacilities(facilities); - - //check results and close modal - if (results.HasErrors) { - setError({message: JSON.stringify(results.Message)}); - return false; - } else { - //if edit - if (props.editFacility) { - props.editFacility(facility); - } - //if new - if (props.addFacility) { - props.addFacility(facility); - } - props.showNotify('success', facility.facilityName + ' successfully updated', JSON.stringify(results.Messages)); - return true; - } - } else { - setError({message: 'User not Authenticated. Please sign in to view this page'}); - } - } catch (e) { - console.log('callUpsertFacilities',e); - setError({message: 'ERROR Occurred: ', debug: JSON.stringify(e).length === 0 ? e : JSON.stringify(e)}); - return false; - } - } - - const submitForm = async(item) => { - var isUpdateSuccessful = await callUpsertFacilitiesApi(); - if (isUpdateSuccessful) { - props.toggleModal(); - } - } - - const checkInputValidity = (inputName, value) => { - switch(inputName) { - case 'facilityName': - value.trim().length === 0 ? setValidFields({...validFields, facilityName:false}) : setValidFields({...validFields, facilityName:true}); - break; - case 'operator': - value.trim().length === 0 ? setValidFields({...validFields, operator:false}) : setValidFields({...validFields, operator:true}); - break; - default: - break - } - } - - const checkIsFormValid = () => { - var validFieldsPropertyArray = Object.keys(validFields); - return !validFieldsPropertyArray.every((item) => {return validFields[item] === true}); - } - - let errorElement = null; - if (error) { - errorElement = ; - } - - const systemOptions = props.systems.map(system => { - return ( - - ); - }); - - return ( -
- {errorElement} -
- - - - - - - - You must enter a facility name to save this record - - - - - You must enter a operator to save this record - - - - - {systemOptions} - - - - - -
-
- - -
-
-
- ) -}; - -export default UpsertFacility; \ No newline at end of file diff --git a/src/components/facility/facility.js b/src/components/facility/facility.js deleted file mode 100644 index 272e142..0000000 --- a/src/components/facility/facility.js +++ /dev/null @@ -1,124 +0,0 @@ -import React, {useState, useEffect} from 'react' -import {Table, - ButtonGroup, - Container } from 'reactstrap'; -import moment from 'moment'; -import { getFacilities, getPipelineSystems } from '../utils/api-service'; -import Loader from '../packages/loader'; -import ModalForm from '../packages/modal-form'; -import UpsertFacility from './facility-upsert'; - -//Helper function to format Graph date/time -function formatDateTime(dateTime) { - return moment.utc(dateTime).local().format('M/D/YY h:mm A'); -} - -const Facility = (props) => { - const [facilities, setFacilities] = useState([]); - const [systems, setSystems] = useState([]); - const [isLoading, setIsLoading] = useState(true); - - useEffect(() => { - const fetchData = async () => { - try { - if (props.isAuthenticated) { - //Get the user's events - var [facilities, systems] = await Promise.all([ getFacilities(), getPipelineSystems() ]); - //Update the array of events in state - setFacilities(facilities); - setSystems(systems); - setIsLoading(false); - } else { - props.showNotify('danger', 'User not Authenticated', 'Please sign in to view this page') - } - } - catch (err) { - props.showNotify('danger', 'ERROR', JSON.stringify(err)); - } - } - fetchData(); - }, []); - - const editFacility = (facility) => { - setIsLoading(true); - setFacilities(facilities.map(item => (item.facilityId === facility.facilityId ? facility : item))); - setIsLoading(false); - } - - const addFacility = (facility) => { - setIsLoading(true); - setFacilities(prevArray => [...prevArray, facility]); - setIsLoading(false); - } - - if (props.isAuthenticated) { - - if (isLoading) { - return ( - - ); - } - - const facilitiesRender = facilities.map(facility => { - return ( - - {facility.facilityId} - {facility.facilityName} - {facility.operator} - {facility.system?.systemName} - {formatDateTime(facility.modifiedTimestamp)} - {facility.isFacilityActive ? 'Yes' : 'No'} - - - ( )} /> - - - - ) - }); - - const nextFacilityId = 1+Math.max.apply(Math, facilities.map(function(o) { return o.facilityId; })); - var newFacility = { - facilityId: nextFacilityId, - facilityName: '', - operator: '', - system: systems[0], - isFacilityActive: true - }; - - return ( -
- -
- ( )}/> -
-

Facilities

- - - - - - - - - - - - - - {facilitiesRender} - -
Facility IdFacility NameOperatorSystemLast Modified DateIs Active?Actions
-
-
- ); - } else { - return (
); - } -} - -export default Facility; \ No newline at end of file diff --git a/src/components/facility/index.js b/src/components/facility/index.js deleted file mode 100644 index 120fff0..0000000 --- a/src/components/facility/index.js +++ /dev/null @@ -1 +0,0 @@ -export {default} from './facility'; \ No newline at end of file diff --git a/src/components/packages/loader.js b/src/components/packages/loader.js index 4966418..82acee7 100644 --- a/src/components/packages/loader.js +++ b/src/components/packages/loader.js @@ -1,12 +1,12 @@ import React from 'react'; import { Spinner } from 'reactstrap'; -export default class Loader extends React.Component { - render() { - return ( -
- {Loading {this.props.name}...} -
- ); - } -} \ No newline at end of file +const Loader = (props) => { + return ( +
+ {Loading {props.name}...} +
+ ); +} + +export default Loader \ No newline at end of file diff --git a/src/components/packages/modal-from-button.js b/src/components/packages/modal-from-button.js new file mode 100644 index 0000000..8b5784d --- /dev/null +++ b/src/components/packages/modal-from-button.js @@ -0,0 +1,39 @@ +import React, { useState } from 'react' +import { Button, Modal, ModalHeader, ModalBody } from 'reactstrap' + +const ModalFromButton = (props) => { + const [modal, setModal] = useState(false); + + const toggle = () => { + setModal(!modal); + } + + const closeBtn = + + const label = props.buttonLabel + + let button = '' + let title = '' + + if(label === 'Edit'){ + button = + title = 'Edit Item' + } else { + button = + title = 'Add New Item' + } + + return ( +
+ {button} + + {title} + + {props.render(modal, toggle)} + + +
+ ) +} + +export default ModalFromButton; \ No newline at end of file diff --git a/src/components/packages/navbar.js b/src/components/packages/navbar.js index 52e7fbd..592fb4e 100644 --- a/src/components/packages/navbar.js +++ b/src/components/packages/navbar.js @@ -1,4 +1,4 @@ -import React from 'react'; +import React, {useState} from 'react'; import { NavLink as RouterNavLink } from 'react-router-dom'; import { Collapse, @@ -16,7 +16,7 @@ import { Button } from 'reactstrap'; import '@fortawesome/fontawesome-free/css/all.css'; -function UserAvatar(props) { +const UserAvatar = (props) => { // If a user avatar is available, return an img tag with the pic if (props.user.avatar) { return ; } -function AuthNavItem(props) { +const AuthNavItem = (props) => { // If authenticated, return a dropdown with the user's info and a // sign out button if (props.isAuthenticated) { @@ -63,76 +63,55 @@ function AuthNavItem(props) { ); } -export default class NavBar extends React.Component { - constructor(props) { - super(props); +const NavBar = (props) => { - this.toggle = this.toggle.bind(this); - this.state = { - isOpen: false - }; - } + const [isOpen, setIsOpen] = useState(false); - toggle() { - this.setState({ - isOpen: !this.state.isOpen - }); + const toggle = () => { + setIsOpen({isOpen: !isOpen}); } - render() { - // Only following nav item if logged in - let calendarLink = null; - let postsLink = null; - let facilityLink = null; - if (this.props.isAuthenticated) { - calendarLink = ( - - Calendar - - ); - postsLink = ( - - Postss - - ); - facilityLink = ( - - Facilities - - ) - } - - return ( -
- - - Well Management System - - - - - - - -
+ // Only following nav item if logged in + let calendarLink = null; + let postsLink = null; + if (props.isAuthenticated) { + calendarLink = ( + + Calendar + + ); + postsLink = ( + + Posts + ); } -} \ No newline at end of file + + return ( +
+ + + React Azure Starter + + + + + + + +
+ ); +} + +export default NavBar; \ No newline at end of file diff --git a/src/components/pipeline-system/index.js b/src/components/pipeline-system/index.js deleted file mode 100644 index 9702300..0000000 --- a/src/components/pipeline-system/index.js +++ /dev/null @@ -1 +0,0 @@ -export {default} from './pipeline-system'; \ No newline at end of file diff --git a/src/components/pipeline-system/pipeline-system-upsert.js b/src/components/pipeline-system/pipeline-system-upsert.js deleted file mode 100644 index 9ad8ad7..0000000 --- a/src/components/pipeline-system/pipeline-system-upsert.js +++ /dev/null @@ -1,106 +0,0 @@ -import React, {useState} from 'react' -import {Button,Form,FormGroup,Label,Input,FormFeedback} from 'reactstrap'; -import NotifyUser from '../packages/notify-user'; -import { upsertPipelineSystem } from '../utils/api-service'; - -const UpsertPipelineSystem = (props) => { - const [error, setError] = useState(null); - const [system, setSystem] = useState(props.system); - const [validFields, setValidFields] = useState({systemName:true}); - - const onChange = (event) => { - const value = event.target.type === "checkbox" ? event.target.checked : event.target.value; - const name = event.target.name; - - setSystem({...system, [name]: value}); - checkInputValidity(name,value); - } - - const callUpsertSystemsApi = async() => { - try { - if (props.isAuthenticated) { - var systems = [system]; - var results = await upsertPipelineSystem(systems); - - //check results and close modal - if (results.HasErrors) { - setError({message: JSON.stringify(results.Message)}); - return false; - } else { - //if edit - if (props.editSystem) { - props.editSystem(system); - } - //if new - if (props.addSystem) { - props.addSystem(system); - } - props.showNotify('success', system.systemName + ' successfully updated', JSON.stringify(results.Messages)); - return true; - } - } else { - setError({message: 'User not Authenticated. Please sign in to view this page'}); - } - } catch (e) { - console.log('callUpsertSystemsApi',e); - setError({message: 'ERROR Occurred: ', debug: JSON.stringify(e).length === 0 ? e : JSON.stringify(e)}); - return false; - } - } - - const submitForm = async(item) => { - var isUpdateSuccessful = await callUpsertSystemsApi(); - if (isUpdateSuccessful) { - //props.toggleModal(); - } - } - - const checkInputValidity = (inputName, value) => { - switch(inputName) { - case 'systemName': - value.trim().length === 0 ? setValidFields({...validFields, systemName:false}) : setValidFields({...validFields, systemName:true}); - break; - default: - break - } - } - - const checkIsFormValid = () => { - var validFieldsPropertyArray = Object.keys(validFields); - return !validFieldsPropertyArray.every((item) => {return validFields[item] === true}); - } - - let errorElement = null; - if (error) { - errorElement = ; - } - - return ( -
- {errorElement} -
- - - - - - - - You must enter a system name to save this record - - - - -
-
- - -
-
-
- ) -} - -export default UpsertPipelineSystem; \ No newline at end of file diff --git a/src/components/pipeline-system/pipeline-system.js b/src/components/pipeline-system/pipeline-system.js deleted file mode 100644 index 49dd143..0000000 --- a/src/components/pipeline-system/pipeline-system.js +++ /dev/null @@ -1,116 +0,0 @@ -import React, {useState, useEffect} from 'react'; -import {Table, - ButtonGroup, - Container } from 'reactstrap'; -import moment from 'moment'; -import { getPipelineSystems } from '../utils/api-service'; -import Loader from '../packages/loader'; -import ModalForm from '../packages/modal-form'; -import UpsertPipelineSystem from './pipeline-system-upsert'; - -//Helper function to format Graph date/time -function formatDateTime(dateTime) { - return moment.utc(dateTime).local().format('M/D/YY h:mm A'); -} - -const PipelineSystem = (props) => { - const [systems,setSystems] = useState([]); - const [isLoading,setIsLoading] = useState(true); - - useEffect(() => { - const fetchData = async () => { - try { - if (props.isAuthenticated) { - //Get the user's events - var [systems] = await Promise.all([ getPipelineSystems() ]); - //Update the array of events in state - setSystems(systems); - setIsLoading(false); - } else { - props.showNotify('danger', 'User not Authenticated', 'Please sign in to view this page') - } - } - catch (err) { - props.showNotify('danger', 'ERROR', JSON.stringify(err)); - } - } - fetchData(); - }, []); - - const editSystem = (system) => { - setIsLoading(true); - setSystems(systems.map(item => (item.systemId === system.systemId ? system : item))); - setIsLoading(false); - } - - const addSystem = (system) => { - setIsLoading(true); - setSystems(prevArray => [...prevArray, system]); - setIsLoading(false); - } - - if (props.isAuthenticated) { - - if (isLoading) { - return ( - - ); - } - - const pipelineSystems = systems.map(system => { - return ( - - {system.systemId} - {system.systemName} - {formatDateTime(system.modifiedTimestamp)} - {system.isSystemActive ? 'Yes' : 'No'} - - - ( )} /> - - - - ) - }); - - const nextSystemId = 1+Math.max.apply(Math, systems.map(function(o) { return o.systemId; })); - var newSystem = { - systemId: nextSystemId, - systemName: '', - isSystemActive: true - }; - - return ( -
- -
- ( )}/> -
-

Pipeline Systems

- - - - - - - - - - - - {pipelineSystems} - -
System IdSystem NameLast Modified DateIs Active?Actions
-
-
- ); - } else { - return (
); - } -} - -export default PipelineSystem; \ No newline at end of file diff --git a/src/components/posts/post-upsert.js b/src/components/posts/post-upsert.js new file mode 100644 index 0000000..7de28e7 --- /dev/null +++ b/src/components/posts/post-upsert.js @@ -0,0 +1,134 @@ +import React, {useState} from 'react' +import {Button,Form,FormGroup,Label,Input,FormFeedback,Spinner} from 'reactstrap'; +import NotifyUser from '../packages/notify-user'; +import { createPost, updatePost } from '../utils/api-service'; + +const UpsertPost = (props) => { + const [error, setError] = useState(null); + const [post, setPost] = useState(props.post); + const [isLoading, setIsLoading] = useState(false); + const [validFields, setValidFields] = useState({title:true,body:true}); + + const onChange = (event) => { + const value = event.target.type === "checkbox" ? event.target.checked : event.target.value; + const name = event.target.name; + const optionSelectText = event.target.type === "select-one" ? event.target.options[event.target.selectedIndex].text : ''; + + //special logic for system object + if (name === "user") { + var userObj = {id: value, name: optionSelectText}; + setPost({...post, user: userObj}); + } else { + setPost({...post, [name]: value}); + } + checkInputValidity(name,value); + } + + const callUpsertPostApi = async() => { + try { + if (props.isAuthenticated) { + var results; + if (props.editPost) { + //process edit logic + results = await updatePost(post); + props.editPost(post); + } else if(props.addPost) { + //process add logic + console.log('callUpsertPostAPI','add post') + results = await createPost(post); + props.addPost(post); + } + + props.showNotify('success', post.id + ' successfully updated', JSON.stringify(results)); + return true; + + } else { + setError({message: 'User not Authenticated. Please sign in to view this page'}); + } + } catch (e) { + console.log('callUpsertPostApi',e); + setError({message: 'ERROR Occurred: ', debug: JSON.stringify(e).length === 0 ? e : JSON.stringify(e)}); + return false; + } + } + + const submitForm = async(item) => { + setIsLoading(true); + var isUpdateSuccessful = await callUpsertPostApi(); + setIsLoading(false); + if (isUpdateSuccessful) { + props.toggleModal(); + } + } + + const checkInputValidity = (inputName, value) => { + switch(inputName) { + case 'title': + value.trim().length === 0 ? setValidFields({...validFields, title:false}) : setValidFields({...validFields, title:true}); + break; + case 'body': + value.trim().length === 0 ? setValidFields({...validFields, body:false}) : setValidFields({...validFields, body:true}); + break; + default: + break + } + } + + const checkIsFormValid = () => { + var validFieldsPropertyArray = Object.keys(validFields); + return !validFieldsPropertyArray.every((item) => {return validFields[item] === true}); + } + + let errorElement = null; + if (error) { + errorElement = ; + } + + let saveButton = null; + if (isLoading) { + saveButton = ; + } else { + saveButton = ; + } + + const userOptions = props.users.map(user => { + return ( + + ); + }); + + return ( +
+ {errorElement} +
+ + + + + + + + You must enter a title to save this record + + + + + You must enter a body to save this record + + + + + {userOptions} + + +
+
+ {saveButton} + +
+
+
+ ) +} + +export default UpsertPost \ No newline at end of file diff --git a/src/components/posts/post.js b/src/components/posts/post.js index 55ae748..df5c189 100644 --- a/src/components/posts/post.js +++ b/src/components/posts/post.js @@ -3,10 +3,12 @@ import {Table, ButtonGroup, Container } from 'reactstrap'; import moment from 'moment'; -import { getPosts } from '../utils/api-service'; +import { getPosts, getUsers } from '../utils/api-service'; import Loader from '../packages/loader'; import ModalForm from '../packages/modal-form'; -import UpsertPipelineSystem from '../pipeline-system/pipeline-system-upsert'; +import UpsertPost from './post-upsert'; +import ModalFromButton from '../packages/modal-from-button'; +import { sortArrayByProperty } from '../utils/utils'; //Helper function to format Graph date/time function formatDateTime(dateTime) { @@ -15,6 +17,7 @@ function formatDateTime(dateTime) { const Posts = (props) => { const [allPosts,setAllPosts] = useState([]); + const [allUsers,setAllUsers] = useState([]); const [isLoading,setIsLoading] = useState(true); useEffect(() => { @@ -22,10 +25,10 @@ const Posts = (props) => { try { if (props.isAuthenticated) { //Get the user's events - var [posts] = await Promise.all([ getPosts() ]); - console.log('fetchData',posts); + var [posts, users] = await Promise.all([ getPosts(), getUsers() ]); //Update the array of events in state setAllPosts(posts); + setAllUsers(users); setIsLoading(false); } else { props.showNotify('danger', 'User not Authenticated', 'Please sign in to view this page') @@ -39,15 +42,11 @@ const Posts = (props) => { }, []); const editPost = (post) => { - setIsLoading(true); setAllPosts(allPosts.map(item => (item.id === post.id ? post : item))); - setIsLoading(false); } const addPost = (post) => { - setIsLoading(true); - setAllPosts(prevArray => [...prevArray, post]); - setIsLoading(false); + setAllPosts(prevArray => [...prevArray, {...post, userId:post.user.id}]); } if (props.isAuthenticated) { @@ -58,18 +57,18 @@ const Posts = (props) => { ); } - const postsToDisplay = allPosts.map(item => { + const postsToDisplay = sortArrayByProperty(allPosts,'title').map(item => { return ( {item.id} {item.title} - {item.title} {item.body} + {allUsers.find(x => x.id === parseInt(item.userId))?.name} ( )} /> + render={edit => ( )} /> @@ -80,16 +79,17 @@ const Posts = (props) => { var newPost = { id: nextId, title: '', - body: '' + body: '', + user: allUsers[0] }; return (
- ( )}/> + render={(modal,toggle) => ( )}/>

Posts

diff --git a/src/components/utils/api-service.js b/src/components/utils/api-service.js index 0d90022..975148e 100644 --- a/src/components/utils/api-service.js +++ b/src/components/utils/api-service.js @@ -1,39 +1,28 @@ import config from './config'; -export async function getPipelineSystems() { - var systems = []; - var url = config.lagoonApiUrl + 'enterprise/pipelinesystem?code=' + config.lagoonApiCode; - var resp = await fetch(url); - systems = await resp.json(); - return systems; -} - -export async function getFacilities() { - var facilities = []; - var url = config.lagoonApiUrl + 'enterprise/facility?code=' + config.lagoonApiCode; - var resp = await fetch(url); - facilities = await resp.json(); - return facilities; -} - export async function getPosts() { var posts = []; - console.log('url',config); - var url = config.jsonApiUrl + '/posts'; + var url = config.jsonApiUrl + 'posts'; var resp = await fetch(url); - console.log('getPosts',resp); posts = await resp.json(); - console.log('getPosts',posts); return posts; } -export async function upsertPipelineSystem(system) { +export async function getUsers() { + var users = []; + var url = config.jsonApiUrl + 'users'; + var resp = await fetch(url); + users = await resp.json(); + return users; +} + +export async function createPost(post) { const requestOptions = { method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(system) + headers: { 'Content-Type': 'application/json; charset=UTF-8' }, + body: JSON.stringify(post) }; - var url = config.lagoonApiUrl + 'enterprise/pipelinesystem?code=' + config.lagoonApiCode; + var url = config.jsonApiUrl + 'posts'; return fetch(url, requestOptions) .then(async response => { if (response.ok) { @@ -51,13 +40,13 @@ export async function upsertPipelineSystem(system) { }); } -export async function upsertFacilities(facilities) { +export async function updatePost(post) { const requestOptions = { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(facilities) + method: 'PUT', + headers: { 'Content-Type': 'application/json; charset=UTF-8' }, + body: JSON.stringify(post) }; - var url = config.lagoonApiUrl + 'enterprise/facility?code=' + config.lagoonApiCode; + var url = config.jsonApiUrl + 'posts/' + post.id; return fetch(url, requestOptions) .then(async response => { if (response.ok) { diff --git a/src/components/utils/utils.js b/src/components/utils/utils.js new file mode 100644 index 0000000..f982828 --- /dev/null +++ b/src/components/utils/utils.js @@ -0,0 +1,11 @@ +export function sortArrayByProperty(array, propName) { + return array.sort((obj1, obj2) => { + if (obj1[propName] < obj2[propName]) { + return -1; + } + if (obj1[propName] > obj2[propName]) { + return 1; + } + return 0; + }); +} \ No newline at end of file diff --git a/src/components/welcome/welcome.js b/src/components/welcome/welcome.js index b40ff87..c0cc278 100644 --- a/src/components/welcome/welcome.js +++ b/src/components/welcome/welcome.js @@ -22,9 +22,9 @@ export default class Welcome extends React.Component { render() { return ( -

Well Management System

+

React Azure Started

- This app allows you to manage the well/pad/facility/system information in the Lagoon environment + This app is a quickstart to get a react app pointed to Azure AD and a CRUD screen pointing to JSONPLaceholder API, https://jsonplaceholder.typicode.com/