Created
October 1, 2021 16:29
-
-
Save naydav/bdd04c9ade77640e01bbb30b6e7b31f2 to your computer and use it in GitHub Desktop.
Customer App - ActionsForm.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* <license header> | |
*/ | |
import React, { useState } from 'react' | |
import PropTypes from 'prop-types' | |
import { | |
Flex, | |
Heading, | |
Form, | |
TextField, | |
Button, | |
StatusLight, | |
ProgressCircle, | |
Text, | |
View | |
} from '@adobe/react-spectrum' | |
import actions from '../config.json' | |
import actionWebInvoke from '../utils' | |
const ActionsForm = (props) => { | |
const [state, setState] = useState({ | |
formValid: null, | |
actionResponse: null, | |
actionResponseError: null, | |
parkingSpaceNumber: '', | |
parkingSpaceNumberValid: null, | |
orderNumber: '', | |
orderNumberValid: null, | |
customerEmail: '', | |
customerEmailValid: null, | |
actionImHereInProgress: false, | |
actionResult: '' | |
}) | |
return ( | |
<View width="size-6000"> | |
<Heading level={1}>Run your application backend actions</Heading> | |
<Form necessityIndicator="label"> | |
<TextField | |
label="Parking space #" | |
placeholder='your parking space number' | |
validationState={state.parkingSpaceNumberValid} | |
isRequired | |
onChange={(input) => | |
setNumberInput(input, 'parkingSpaceNumber', 'parkingSpaceNumberValid') | |
} | |
/> | |
<TextField | |
label="Order #" | |
placeholder='your order number' | |
validationState={state.orderNumberValid} | |
isRequired | |
onChange={(input) => | |
setNumberInput(input, 'orderNumber', 'orderNumberValid') | |
} | |
/> | |
<TextField | |
type="email" | |
label="Email" | |
placeholder='customer email' | |
validationState={state.customerEmailValid} | |
isRequired | |
value={state.customerEmail} | |
onChange={(input) => | |
setEmailInput(input, 'customerEmail', 'customerEmailValid') | |
} | |
/> | |
<Flex> | |
<Button | |
variant="primary" | |
type="button" | |
onPress={invokeAction.bind(this)} | |
width="100%" | |
isDisabled={!formValid()} | |
><Text>I'm here</Text></Button> | |
</Flex> | |
</Form> | |
{state.actionResponseError && ( | |
<View padding={`size-100`} marginTop={`size-100`} marginBottom={`size-100`} borderRadius={`small `}> | |
<StatusLight variant="negative">Failure! See the complete error in your browser console.</StatusLight> | |
</View> | |
)} | |
{!state.actionResponseError && state.actionResponse && ( | |
<View padding={`size-100`} marginTop={`size-100`} marginBottom={`size-100`} borderRadius={`small `}> | |
<StatusLight variant="positive">Success! See the complete response in your browser console.</StatusLight> | |
</View> | |
)} | |
</View> | |
) | |
// Methods | |
// parses a number input and adds it to the state | |
async function setNumberInput (input, stateNumber, stateValid) { | |
let content | |
let validStr = null | |
if (input) { | |
content = parseInt(input) || input | |
validStr = Number.isInteger(content) ? 'valid' : 'invalid' | |
} | |
setState({ ...state, [stateNumber]: content, [stateValid]: validStr }) | |
} | |
// check the email input and adds it to the state | |
async function setEmailInput (input, stateName, stateValid) { | |
let validStr = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(input) ? 'valid' : 'invalid'; | |
setState({ ...state, [stateName]: input, [stateValid]: validStr }) | |
} | |
// checks if form is valid | |
function formValid () { | |
return !!(state.parkingSpaceNumberValid && state.orderNumberValid && state.customerEmailValid) | |
} | |
// invokes a the selected backend actions with input headers and params | |
async function invokeAction () { | |
setState({ ...state, actionInvokeInProgress: true, actionResult: 'calling action ... ' }) | |
const actionName = 'i-am-here' | |
const headers = state.actionHeaders || {} | |
const params = state.actionParams || {} | |
const startTime = Date.now() | |
// all headers to lowercase | |
Object.keys(headers).forEach((h) => { | |
const lowercase = h.toLowerCase() | |
if (lowercase !== h) { | |
headers[lowercase] = headers[h] | |
headers[h] = undefined | |
delete headers[h] | |
} | |
}) | |
// set the authorization header and org from the ims props object | |
if (props.ims.token && !headers.authorization) { | |
headers.authorization = `Bearer ${props.ims.token}` | |
} | |
if (props.ims.org && !headers['x-gw-ims-org-id']) { | |
headers['x-gw-ims-org-id'] = props.ims.org | |
} | |
let formattedResult = "" | |
try { | |
// invoke backend action | |
const actionResponse = await actionWebInvoke(actions[actionName], headers, params) | |
formattedResult = `time: ${Date.now() - startTime} ms\n` + JSON.stringify(actionResponse,0,2) | |
// store the response | |
setState({ | |
...state, | |
actionResponse, | |
actionResult:formattedResult, | |
actionResponseError: null, | |
actionInvokeInProgress: false | |
}) | |
console.log(`Response from ${actionName}:`, actionResponse) | |
} catch (e) { | |
// log and store any error message | |
formattedResult = `time: ${Date.now() - startTime} ms\n` + e.message | |
console.error(e) | |
setState({ | |
...state, | |
actionResponse: null, | |
actionResult:formattedResult, | |
actionResponseError: e.message, | |
actionInvokeInProgress: false | |
}) | |
} | |
} | |
} | |
ActionsForm.propTypes = { | |
runtime: PropTypes.any, | |
ims: PropTypes.any | |
} | |
export default ActionsForm |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment