Override a Page
Overview
This task will show you how to override the page used for the SignOn prompt.
Overriding a page
-
Open your <CustomerName>-React POS project in vscode editor.
-
Navigate to
/src-js/packages/<CustomerName>-ReactPOS/Components
folder -
Create a new folder called SignOn
-
Inside that folder create a new file called index.js
-
Add the following content in the index.js and save the file.
import React, { useEffect } from "react";
import { connect } from "react-redux";
import { getPageState } from "@enactor/redux-javascript-bridge";
import {
ResolvableMessage,
selectMessageHook,
} from "@enactor/react-javascript-bridge";
import {
POINTER,
ConnectedPosKeyboard,
defaultMapStateToProps,
defaultMapDispatchToProps,
SIGN_ON_BACKGROUND,
ConnectedTextInput,
pointAction,
inputStateCleanup,
getInputsForPromptUrl,
sendEventWithMultipleInputs,
hideKeyboard,
getCurrentDeviceResolution,
resolveClassName,
MOBILE_DEVICE,
} from "@enactor/react-base-components";
import { SignOnHeader, SignOnNumericKeypad } from "@enactor/react-pos";
const USERNAME = "username";
const PASSWORD = "password";
const SignOn = (props) => {
const handleOKPressed = () => {
let { promptUrl, onEvent } = props;
onEvent("OKPressed", promptUrl, {
userId: USERNAME,
pIN: PASSWORD,
});
};
const onEnterPressed = () => {
let {
inputState: { focussedElement },
promptUrl,
} = props;
if (focussedElement === USERNAME) {
props.onPoint({
promptUrl,
sourceDevice: POINTER,
inputName: PASSWORD,
cursorStartPosition: 0,
cursorEndPosition: 0,
});
} else {
handleOKPressed();
}
};
const handleKeyUp = (event) => {
let { key, target } = event;
if (key === "Enter") {
if (target.name === "username") {
props.onPoint({
promptUrl: props.promptUrl,
sourceDevice: POINTER,
inputName: PASSWORD,
cursorStartPosition: 0,
cursorEndPosition: 0,
});
} else {
handleOKPressed();
}
}
};
useEffect(() => {
window.document.body.classList.add("signon");
const {
eventHandlers: { changeBackground },
inputState: { focussedElement },
promptUrl,
} = props;
if (focussedElement !== USERNAME) {
props.onPoint({
promptUrl,
sourceDevice: POINTER,
inputName: USERNAME,
cursorStartPosition: 0,
cursorEndPosition: 0,
});
}
changeBackground(SIGN_ON_BACKGROUND);
return () => {
window.document.body.classList.remove("signon");
props.onUnmount(props.promptUrl);
};
}, []);
const {
eventHandlers,
promptInstanceId,
promptUrl,
context,
promptData,
deviceType,
} = props;
return (
<div className="signon">
<SignOnHeader eventHandlers={eventHandlers} />
<div
className={resolveClassName({
"body-area": true,
mobile: deviceType === MOBILE_DEVICE,
})}
>
<div className="signon-box" onKeyUp={handleKeyUp}>
<div className="signon-box-left">
<div className="signon-form-row">
<div className="signon-form-txt">
<ResolvableMessage
messageBase="Pos/SignOn/SignOnMessages"
messageId="USER_ID"
/>
</div>
<ConnectedTextInput
context={context}
promptUrl={promptUrl}
promptInstanceId={promptInstanceId}
className="signon-input"
name={USERNAME}
placeholder={selectMessageHook({
messageId: "ENTER_USER_NAME",
messageBase: "Pos/SignOn/SignOnMessages",
})}
test-component-id={"INPUT_TEXT_1"}
/>
<div className="signon-error" />
</div>
<div className="signon-form-row">
<div className="signon-form-txt">
<ResolvableMessage
messageBase="Pos/SignOn/SignOnMessages"
messageId="PASSWORD"
/>
</div>
<ConnectedTextInput
textType="password"
context={context}
promptUrl={promptUrl}
promptInstanceId={promptInstanceId}
className="signon-input"
name={PASSWORD}
placeholder={selectMessageHook({
messageId: "ENTER_PIN",
messageBase: "Pos/SignOn/SignOnMessages",
})}
test-component-id={"INPUT_TEXT_2"}
/>
<div className="signon-error" />
</div>
</div>
<div className="signon-box-numpad" keyboard-control-wrapper="true">
<SignOnNumericKeypad
context={context}
promptInstanceId={promptInstanceId}
promptUrl={promptUrl}
enterClickedHandler={onEnterPressed}
/>
</div>
</div>
<ConnectedPosKeyboard
promptInstanceId={promptInstanceId}
context={context}
onEnter={onEnterPressed}
/>
</div>
</div>
);
};
const mapStateToProps = (state, ownProps) => {
const { promptUrl } = getPageState(state, ownProps);
let inputState = getInputsForPromptUrl(state, promptUrl);
const deviceType = getCurrentDeviceResolution(state, ownProps);
return {
...defaultMapStateToProps(state, ownProps),
promptUrl,
inputState,
deviceType,
...ownProps,
};
};
const mapDispatchToProps = (dispatch, ownProps) => {
return {
...defaultMapDispatchToProps(dispatch, ownProps),
onEvent: (eventName, promptUrl, cacheValueAttributePayloadAttributeMap) =>
dispatch(
sendEventWithMultipleInputs(
eventName,
promptUrl,
cacheValueAttributePayloadAttributeMap
)
),
onPoint: ({
promptUrl,
sourceDevice,
inputName,
cursorStartPosition,
cursorEndPosition,
}) =>
dispatch(
pointAction({
promptUrls: [promptUrl],
sourceDevice,
focussedElement: inputName,
cursorStartPosition,
cursorEndPosition,
})
),
onUnmount: (promptUrl) => {
dispatch(
inputStateCleanup({
promptUrls: [promptUrl],
})
);
dispatch(hideKeyboard());
},
};
};
export default connect(mapStateToProps, mapDispatchToProps)(SignOn);
This is almost a copy of our existing implementation.
-
Line 37-53 -
onEnterPressed
function is defined and provided as a prop toKeypad
andConnectedPosKeyboard
components , as a callback function to be called when numer pad ENT or the Onscreen keyboard Enter button is pressed. -
Line 54-69 -
handleKeyUp
function is defined and passed as a callback function when physical keyboard Enter is pressed . -
Line 70-91 -
useEffect
hook with empty dependency array defined( means it will execute the logic when the component gets mounted) , we set the focus on the USERNAME field as well as doing some style related changes here. -
Here we use some of the existing components to build the UI.
-
SignOnNumericKeypad
- responsible for the onscreen keypad.
-
Line 226 -Connected our component to the redux store.
-
If you are not familiar with connect function and about extracting data and dispatching actions please refer the official documentation of react-redux
-
To get to know of the functions we passed as arguments to connect , please refer the following.
-
To let the application find this prompt, we need to add a route mapping for it:
-
Navigate to
/src-js/packages/<CustomerName>-ReactPOS/src/Configuration
folder. -
Open the <CustomerName>Routes.js file and add a route for the new component we created in index.js file as shown.
-
Add the following item to the routes array
"Pos/SignOn/EnterUser": {
promptUrl: "Pos/SignOn/EnterUser",
component: SignOn
}
Make sure to add an import for the SignOn component
The key here is the URL of the prompt state in the process
Now if you restart the ReactPos application it will show our overridden component for the SignOn page, by default no change will be visible however.
Therefore experiment by changing the text and adding or removing the components.
For example try replacing
<div className="signon-form-txt">
<ResolvableMessage
messageBase="Pos/SignOn/SignOnMessages"
messageId="USER_ID"
/>
</div>
with
<div className="signon-form-txt">Enter your user id here</div>