UNPKG

@adobe/generator-aio-app

Version:

Adobe I/O application yeoman code generator

208 lines (193 loc) 6.61 kB
/* <% if (false) { %> Copyright 2019 Adobe. All rights reserved. This file is licensed to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. <% } %> * <license header> */ import React, { useState } from 'react' import PropTypes from 'prop-types' import ErrorBoundary from 'react-error-boundary' import { Flex, Heading, Form, Picker, TextArea, Button, ActionButton, StatusLight, ProgressCircle, Item, Text, View } from '@adobe/react-spectrum' import Function from '@spectrum-icons/workflow/Function' import actions from '../config.json' import actionWebInvoke from '../utils' const ActionsForm = (props) => { const [state, setState] = useState({ actionSelected: null, actionResponse: null, actionResponseError: null, actionHeaders: null, actionHeadersValid: null, actionParams: null, actionParamsValid: null, actionInvokeInProgress: false, actionResult: '' }) return ( <View width="size-6000"> <Heading level={1}>Run your application backend actions</Heading> {Object.keys(actions).length > 0 && ( <Form necessityIndicator="label"> <Picker label="Actions" isRequired={true} placeholder="select an action" aria-label="select an action" items={Object.keys(actions).map((k) => ({ name: k }))} itemKey="name" onSelectionChange={(name) => setState({ ...state, actionSelected: name, actionResponseError: null, actionResponse: null }) } > {(item) => <Item key={item.name}>{item.name}</Item>} </Picker> <TextArea label="headers" placeholder='{ "key": "value" }' validationState={state.actionHeadersValid} onChange={(input) => setJSONInput(input, 'actionHeaders', 'actionHeadersValid') } /> <TextArea label="params" placeholder='{ "key": "value" }' validationState={state.actionParamsValid} onChange={(input) => setJSONInput(input, 'actionParams', 'actionParamsValid') } /> <Flex> <ActionButton variant="primary" type="button" onPress={invokeAction.bind(this)} isDisabled={!state.actionSelected} ><Function aria-label="Invoke" /><Text>Invoke</Text></ActionButton> <ProgressCircle aria-label="loading" isIndeterminate isHidden={!state.actionInvokeInProgress} marginStart="size-100" /> </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> )} {Object.keys(actions).length === 0 && <Text>You have no actions !</Text>} <TextArea label="results" isReadOnly={true} width="size-6000" height="size-6000" maxWidth="100%" value={state.actionResult} validationState={( !state.actionResponseError ) ? 'valid' : 'invalid'} /> </View> ) // Methods // parses a JSON input and adds it to the state async function setJSONInput (input, stateJSON, stateValid) { let content let validStr = null if (input) { try { content = JSON.parse(input) validStr = 'valid' } catch (e) { content = null validStr = 'invalid' } } setState({ ...state, [stateJSON]: content, [stateValid]: validStr }) } // invokes a the selected backend actions with input headers and params async function invokeAction () { setState({ ...state, actionInvokeInProgress: true, actionResult: 'calling action ... ' }) const actionName = state.actionSelected 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