BookmarkSubscribeRSS Feed

Develop web applications series: Creating the React based application

Started ‎05-17-2021 by
Modified ‎01-10-2022 by
Views 9,651

In the first article of the Develop web applications series, I've described the different options to get data from SAS Viya environment to hydrate your web application. Before we implement the different options, we need to build an application that will be the canvas for the different pages.

 

This article is the second one in the Develop web applications series:

 

 

The application

To demonstrate the different options, I've created a simple web application using React JavaScript library. Writing this I already imagine you, thinking: why React? I prefer Angular. Can it be done using jQuery? Vue is far better than React ...

 

I prefer to stop here the fight between Angular, React, Vue, jQuery and the other JavaScript libraries and frameworks. I've chosen React because it is well documented, it is used by many large companies and more importantly, the code is easy to read and to understand which is I think the most important point as the objective is to learn about developing web applications that use SAS REST APIs as their data source.

 

With that being said, React is designed to create single page applications (SPA). This means that when the end-user connects to the application, the architecture of the page is loaded and then when the user navigates to the different pages, there is no need to query the back-end server except to get data. It makes a clear separation of concerns between the client application and the back-end server. Which is really nice because we will be using REST APIs to get data from the CAS server, the Compute server, the Viya Job and from MAS. If you need more information about React and how to use it, please refer to this tutorial page.

 

The application, in this example, has different pages. Each page represents a specific option and reuse the same components a form to select the data to be displayed and a table to display the data retrieved from the REST APIs. The form and the table will be covered in the remaining series. In this article, we will concentrate on building the structure of the application.

 

 

xab_1_ViyaApp_finalLookDetailed-1024x344.png

Select any image to see a larger version.
Mobile users: To view the images, select the "Full" version at the bottom of the page.

 

In addition to the four pages (CAS, Jobs, Compute and MAS), the application has two other pages: Logon and Home. The Home page is the first one that the user will see.

 

xab_2_ViyaApp_homePage-1024x560.png

 

And the Logon page is used to authenticate the user.

 

xab_3_ViyaApp_logonPage-1024x296.png

 

 

Behind the scenes, the application will use Axios to call the SAS REST APIs. If you want more information about using React and Axios, please have a look at this tutorial page.

 

Configure the development environment

At this stage, you might wonder how this all fits together. Here are the steps to create the common architecture:

  • Install nodeJS and node package manager (npm) on your machine.
  • In a terminal, navigate to the location where you want to create the project.
  • Execute the command below. It will create the project structure in a folder named viya_app and install the needed components to develop a react application
npx create-react-app viya_app
  • You can then launch the application using the following command
npm start

This will start the default application that has been generated by the create-react-app tool. It should also start a browser with the following content:

 

xab_4_ViyaApp_reactdefault-300x251.png

 

 

You can stop the application by running the following command:

 

npm stop

 

  • Before we can start developing the application there are still some node modules that need to be installed. Execute the following commands to install the modules.
/* react-router-dom to handle routing */
npm install --save react-router-dom@5.2.0

/* react-bootstrap for the UI elements */
npm install -pm stop-save react-bootstrap@1.5.2 bootstrap@4.6.0

/* Axios for the REST APIs calls */
npm install --save axios@0.21.1 /* Font Awesome for specific icons */ npm install --save @fortawesome/fontawesome-svg-core@1.2.35 npm install --save @fortawesome/free-solid-svg-icons@5.15.3 npm install --save @fortawesome/react-fontawesome@0.1.14
  • As we will connect later to a SAS Viya environment and authenticate, this is important to configure HTTPS on the development server. Within package.json file, update the command to start the server as indicated in the create-react-app documentation.
/* On Windows */
set HTTPS=true&&npm start

/* On Linux or MacOS */
HTTPS=true npm start

Now that we have everything installed, we need to make some changes to the application that was created by the create-react-app. 

Customize the application

Even though you can develop your application using any text editor, I suggest you use an application that is targeted to developers. I will use Visual Studio Code because it is a nice and easy tool to write any kind of code and it has a lot functionalities that makes your life easier when developing web pages.

  1. Open the viya_app directory in Visual Studio Code.
  2. Create a folder structure for the application. Under src directory, create the following directories:
    • apis: store the connection information to the SAS Viya environment.
    • components: store the custom components that will make the user interface.
    • data: store the data that will not be retrieved from the SAS environment.
    • pages: store the different pages that will make the application.
    The directory structure should look like this:xab_5_ViyaApp_directoryStructure-210x300.png

     

  3. Integrate Bootstrap and Fontawesome in the application. These modules will help with the visuals of the application. The integration can be done directly on the index.js in the src directory. You should add the following lines at the top of the file with the other import statements:
    import 'bootstrap/dist/css/bootstrap.min.css';
    
    import { library } from '@fortawesome/fontawesome-svg-core';
    import { faHome } from '@fortawesome/free-solid-svg-icons';
    
    library.add(faHome);
    The index.js file will now look like this:xab_6_ViyaApp_indexJS.png

     

  4. Create an axios instance to store information about the connection to the SAS Viya Environment. Under apis, create a file named Instance.js with the following content. Please make sure that the baseURL points to your SAS environment.
    import axios from 'axios';
    
    const Instance = axios.create({
        baseURL: "https://live.lts.gel.race.sas.com",
        headers:{}
    });
    
    export default Instance;
    
  5. Define the information about the different pages that will be used in the application. Under data, create a file names PAGES.js with the following content.
    const PAGES = [
        { label: 'CAS', 
          href: "/cas", 
          description: "This page demonstrates how to retrieve 
              data from a CAS table by selecting a global CASLib 
              and the required table."},
        { label: 'Compute', 
          href: "/compute", 
          description: "This page demonstrates how to start 
              a computer server session to execute SAS code 
              that retrieves a selected CAS table." },
        { label: 'Jobs', 
          href: "/jobs", 
          description: "This page demonstrates how to call 
             a SAS Viya Job that retrieves a selected CAS 
             table." },
        { label: 'MAS', 
          href: "/mas",
          description: "This page demonstrates how to call 
             a decision that has been published to the MAS 
             destination."}
    ]
    
    export default PAGES;
    
    The label will be used in the navigation bar as well as the href to build the link to the page. The description will be used in the Home page to give the user an idea about the content of each page.
  6. Create the different pages used in the application. Under pages, create the following files:
    • Cas.js : hold the page structure for the components related to the data coming from the CAS server.
    • Compute.js : hold the page structure for the components related to data coming from the Compute server.
    • Home.js : hold the welcome page for the web application.
    • Jobs.js : hold the page structure for the components related to the data coming from a SAS Viya Job.
    • Logon.js : hold the components for authentication against the SAS Viya environment.
    • Mas.js : hold the page structure for the components related to data coming from the Micro Analytic server.
    Within each file under pages, add the following JavaScript code. This is just a placeholder to identify the page we are displaying. We will add more interesting content for each page later.
    function Compute (){
        return (
            <h2>Compute page</h2>
        );
    }
    export default Compute;
    Please change the Compute occurrences with the name of the page you are currently updating: CAS, Jobs and MAS .
  7. Update the App.js to include what we have created so far. Under src, open App.js file and change the content to this.
    import React from 'react';
    import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
    
    import Container from 'react-bootstrap/Container';
    
    import HeaderBar from './components/HeaderBar';
    
    import Home from './pages/Home';
    import Logon from './pages/Logon';
    import Cas from './pages/Cas';
    import Compute from './pages/Compute';
    import Jobs from './pages/Jobs';
    import Mas from './pages/Mas';
    
    function App() {
        return (
            <Router>
                <Container>
                    <HeaderBar/>
                    <Switch>
                        <Route path="/" exact component={Home}/>
                        <Route path="/cas"exact component={Cas}/>
                        <Route path="/jobs" exact component={Jobs}/>
                        <Route path="/compute" exact component={Compute}/>
                        <Route path="/mas" exact component={Mas}/>
                        <Route path="/logon" exact component={Logon}/>
                    </Switch>
               </Container>
            </Router>
        );
    }
    
    export default App;
    
    As you can see in the code, the App.js imports the different pages you have created. It also defines the routing that is responsible to make the link between the URL and the page that is displayed.
  8. Create the HeaderBar component to navigate between the pages. Under components, create a file named HeaderBar.js with the following content.
    import React from 'react';
    import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
    import { Navbar, Nav } from 'react-bootstrap';
    import { NavLink } from 'react-router-dom';
    import PAGES from '../data/PAGES';
    
    function HeaderBar() {
        const navItems = PAGES.map((item, index) =>
            <Nav.Link to={item.href} as={NavLink} style={{ color:'white', textDecoration:'none' }} key={index}>
                {item.label}
            </Nav.Link>
        );
        return (
            <Navbar bg="primary">
                <Navbar.Collapse>
                    <Nav.Link to='/' as={NavLink}>
                        <FontAwesomeIcon icon="home" color="white" size="lg"/>
                    </Nav.Link>
                    {navItems}
               </Navbar.Collapse>
            </Navbar>
       );
    }
    export default HeaderBar;
  9. Start the application and click around to check that everything works fine.

xab_7_ViyaApp_checkNavigation.png

 

Connect the application to SAS

At this stage, our application can navigate between pages. It might be good to add some logic to it. The objective is now to display the description of the different pages on the Home page. As soon as we click on one of the page description, it should open the link but this can only be done for the authenticated users. So, we will update the content of the Home.js file to this:

import { Card, Row, Col } from 'react-bootstrap';
import { useHistory } from 'react-router-dom';

import PAGES from '../data/PAGES';

function Home() {
    const history = useHistory();
    function handleClick(href) {
        history.push(href);
    }
    return (
        <Row>
            {PAGES.map((page, index) =>
            <Col key={index} xs={6} style={{ padding:10 }}>
                <Card onClick={() =>handleClick(page.href)}>
                    <Card.Header style={{ padding:20 }}>
                        {page.label}
                    </Card.Header>
                    <Card.Body>
                        {page.description}
                    </Card.Body>
                </Card>
            </Col>
       )}
       </Row>
    )
}

export default Home;

As mentioned, the user needs to be authenticated to access the other pages. This means that we need first to get an authentication token from the SAS Viya Environment. This can be done by updating the Logon.js page like below:

import React, { useContext } from 'react';
import { useHistory } from 'react-router-dom';

import Instance from '../apis/Instance';

import { AuthContext } from '../contexts';

import Form from 'react-bootstrap/Form';
import Button from 'react-bootstrap/Button';
import Col from 'react-bootstrap/Col';

function Logon() {
    const { authInfo, setAuthInfo } = useContext(AuthContext);
    const history = useHistory();
    let userInput = React.createRef();
    let passwordInput = React.createRef();
    const authenticate = (event) => {
        event.preventDefault();
        const endpoint = "/SASLogon/oauth/token";
        const user = userInput.current.value;
        const password = passwordInput.current.value;
        const data = {
            grant_type:"password",
            response_type:"bearer",
            username:user,
            password:password
        };

        const headers = {
            'Authorization':"Basic " + btoa('gel_app:gel_secret'),
            'Content-Type':'application/x-www-form-urlencoded'
        };
        Instance.post(endpoint, new URLSearchParams(data), { headers:headers })
            .then(response => {
                if (response.status === 200) {
                    Instance.defaults.headers.common['Authorization'] = `${response.data.token_type} ${response.data.access_token}`;
                } else {
                    Instance.defaults.headers.common['Authorization'] = null;
                }
                setAuthInfo({ ...authInfo,
                    authenticated:true,
                    user:user,
                    tokenInfo:response.data });
                history.goBack();
                return null;
            });
          }
          return (
             <Form onSubmit={authenticate}>
                 <Form.Row>
                     <Col className='col-6'>
                         <Form.Control ref={userInput}
                             type="input"
                             placeholder="Login"/>
                     </Col>
                     <Col className="col-4">
                         <Form.Control ref={passwordInput}
                             type="password"
                             placeholder="Password"/>
                     </Col>
                     <Col>
                         <Button variant="primary" type="submit">
                             Logon
                         </Button>
                     </Col>
                 </Form.Row>
             </Form>
          )
}

export default Logon;

As you see in the code, we are importing a context. In React, contexts are used to pass data from a parent component to all its descendants. As we will reuse the username and the token in nearly all the components, this is the right time to create an AuthContext to store the authentication information. Let's create a contexts.js under src. The file should contain the following code:

import { createContext } from 'react';

export const AuthContext = createContext({});

Now that we have defined the context, we need to assign some value to it and make sure it is passed to all the components. This can be done in App.js. You can add an import for the context at the top of the file:

import { AuthContext } from './contexts';

In the App function, we should create a new variable and a setter function for it with the following code:

const [authInfo, setAuthInfo] = useState({
    authenticated:false,
    user:"",
    tokenInfo: {},
    session: {},
    csrf : {}
});

And finally, wrap all the returned components with the context:

<AuthContext.Provider value={{ authInfo, setAuthInfo }}>
...
</AuthContext.Provider>

The App.js should now look like:

xab_8_ViyaApp_appJS.png

 

 

After saving all the files, if you open https://localhost:3000/logon page, you should see a form. If you submit the form with a username and a password, it will authenticate against SAS Viya environment and store the token in the AuthContext object. In order to check that the user has been authenticated and that the AuthContext has been updated properly, we will display the username in the HeaderBar. To achieve this, add the the lines of code that are highlighted in the HeaderBar.js file.

 

xab_9_ViyaApp_headerBarUpdated.png

 

As mentioned in the objective, a user should not be able to access the different pages if he is not authenticated. We will now force the application to route the user to the Logon page if the user is not yet authenticated. We will do it in the Cas.js file but it should be done in the different pages (Compute.js, Jobs.js, Mas.js). Here is the code:

 

xab_10_ViyaApp_pageWithAuthentication.png

 

 

Test the application

Now that we have done all these changes, we can save them and test the application. You can execute "npm start" command.

 

   

 

The application works now as expected. We can just improve a bit the look and feel of the HeaderBar. In fact, we don't want the user to interact with the navigation bar unless he is authenticated. We will just add this condition to the Headerbar function.

xab_11_ViyaApp_headerBarFinal.png

 

 

Here is the new look of the Home page:

xab_12_ViyaApp_homePage-1024x560.png

 

 

Conclusion

Using React, we have created a web application which displays different pages. The application also handles authentication against SAS Viya. The application is structured in such a way that we don't redundant code and that each component has a well defined role. From here, we can build the different pages to access CAS, MAS, Compute Server or Viya Jobs. And this is what we will see in the next article of this series. The code for this article can be downloaded here. This article is the second one in the Develop web applications series:

 

 

Find more articles from SAS Global Enablement and Learning here.

Version history
Last update:
‎01-10-2022 07:57 AM
Updated by:
Contributors

sas-innovate-2024.png

Available on demand!

Missed SAS Innovate Las Vegas? Watch all the action for free! View the keynotes, general sessions and 22 breakouts on demand.

 

Register now!

Free course: Data Literacy Essentials

Data Literacy is for all, even absolute beginners. Jump on board with this free e-learning  and boost your career prospects.

Get Started

Article Tags