Connect Salesforce from LWC Open Source Application

Please complete the previous tutorial about building a simple application by LWC Open Source.

Our object is that customer-service-app will show the Case records from Salesforce. Already, we have created customer-service-app as per the previous tutorial. Now, we have to connect to Salesforce to get the Case records and we have to upgrade the UI layer for our customer-service-app.

Step 1: Please open the customer-service-app in VS Code and you will get this type of project structure.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Step 2: Before updating any file, let’s discuss the importance of some existing files.

  • api.js: We can see the api.js in this path src/server. This js file helps to execute this customer service application in the localhost or event in a specific port.
  • lwc-services.config.js: We can see this file in the root directory of this project. This file defines the path for the resources, sourceDir, moduleDir. So, system will understand the executable files.
  • index.html:  We can see the index.html page in this path src/client. This html is the starter page of the application. From this html file we will call our lwc template by index.js.
  • index.js: We can see the index.js in this path src/client.  This js file helps to call our lwc template named “app” during running of the application.
  • app folder: We can get this folder in this path src/client/modules/my. This folder contains app.html and app .js file where we will write our business logic.
  • greeting folder: We can also get this folder in this path src/client/modules/my. This is invoked from app.html file. This folder contains greeting.html and greeting.js file to show the greeting message by default.
  • package.json: At last, we can see the information related to installed node modules in dependencies and devDependencies tag and how can we run the application using npm run watch.

Take time. No hurry. I would like to request you please see the above-mentioned files carefully before we will change the code to fulfill the business objective of our customer-service-app.

Step 3: First we will create a folder named “data” under this path src/client/modules. In this data folder, please create another folder called “caseServices“.  In this “caseServices” folder, please create a caseServices.js file. So, now, the module looks like:

 

 

 

 

 

Step 4: Please update the following code snippet for the customerServices.js file.

const URL = '/api/cases';
let cases = [];
export const getCases = () => fetch(URL)
  .then(response => {
    if (!response.ok) {
      throw new Error('No response from server');
    }
    return response.json();
  })
  .then(result => {
    cases = result.data;
    return cases;
  });

Step 5: Please execute this command from the terminal of the VS Code.

npm install jsforce dotenv

This will help to install the jsforce node modules to build communication with Salesforce and dotenv node modules to work with environment files. After successful execution, you can see the dependencies of package.json file looks like:

 

 

 

 

 

Step 6: Please create a new file named “.env” in the root directory of the project just like

SF_LOGIN_URL=LOGIN_URL
SF_USERNAME=YOUR_USERNAME
SF_PASSWORD=YOUR_PASSWORD  
SF_TOKEN=YOUR_SECURITY_TOKEN

This “.env” files contains credential information to log into Salesforce Instance. So, please fill up the correct information.

Step 7: Now, we will update the api.js file under the path src/server. So, please update the api.js file in this following code snippet.

// Simple Express server setup to serve for local testing/dev API server
const compression = require('compression');
const helmet = require('helmet');
const express = require('express');

const jsforce = require('jsforce');
require('dotenv').config();
const { SF_USERNAME, SF_PASSWORD, SF_TOKEN, SF_LOGIN_URL } = process.env;
if (!(SF_USERNAME && SF_PASSWORD && SF_TOKEN && SF_LOGIN_URL)) {
    console.error(
        'Cannot start app: missing mandatory configuration. Check your .env file.'
    );
    process.exit(-1);
}
const conn = new jsforce.Connection({
    loginUrl: SF_LOGIN_URL
});
conn.login(SF_USERNAME, SF_PASSWORD + SF_TOKEN, err => {
    if (err) {
        console.error(err);
        process.exit(-1);
    }
});


const app = express();
app.use(helmet());
app.use(compression());

const HOST = process.env.API_HOST || 'localhost';
const PORT = process.env.API_PORT || 3002;

app.get('/api/cases', (req, res) => {
    const soql = `SELECT Id, CaseNumber, Subject, Status, Priority, format(CreatedDate) formattedCreatedDate, format(ClosedDate) formattedClosedDate FROM Case`;
    
    conn.query(soql, (err, result) => {
        if (err) {
            res.sendStatus(500);
        } else if (result.records.length === 0) {
            res.status(404).send('Session not found.');
        } else {
            const formattedData = result.records.map(caseRecord => {
                let cases = [];
                return {
                    id: caseRecord.Id,
                    CaseNumber: caseRecord.CaseNumber,
                    Subject: caseRecord.Subject,
                    Status: caseRecord.Status,
                    Priority: caseRecord.Priority,
                    CreatedDate: caseRecord.formattedCreatedDate,
                    ClosedDate: caseRecord.formattedClosedDate,
                    cases
                };
            });
            res.send({ data: formattedData });
        }
    });
});

app.listen(PORT, () =>
    console.log(
        `✅  API Server started: http://${HOST}:${PORT}/api/v1/endpoint`
    )
);

Step 8: Now, we will update the app.html,app.js and app.css files under this path src/client/modules/my/app.
So, update the app.js file first:

app.js

import { LightningElement, track } from 'lwc';
import { getCases } from 'data/caseServices';

export default class App extends LightningElement {
    @track cases = [];

   connectedCallback() {
        getCases().then(result => {
        this.cases = result;
        });
    }

}

app.html

<template>
    <header>
        <img src="resources/lwc.png" alt="App logo">
        <h2>Customer Service Application</h2>
    </header>
    <!-- Page code -->
    <main class="content">      
            <table>
                <thead>
                    <tr>
                        <th scope="col">
                            <div>
                                <input type="checkbox"></input>
                            </div>
                        </th>
                        <th scope="col">
                            <div title="Name">Case Number</div>
                        </th>
                        <th scope="col">
                            <div title="Subject">Subject</div>
                        </th>
                        <th scope="col">
                            <div title="Status">Status</div>
                        </th>
                        <th scope="col">
                            <div title="Priority">Priority</div>
                        </th>
                        <th scope="col">
                            <div title="Created Date">Created Date</div>
                        </th>
                        <th scope="col">
                            <div title="Closed Date">Closed Date</div>
                        </th>
                    </tr>
                </thead>
                <tbody>
                    <template for:each={cases} for:item="cs">                        
                            <tr key={cs.id}>
                                    <th scope="col">
                                        <div>
                                            <input type="checkbox" value={cs.CaseNumber} data-id={cs.id}></input>
                                        </div>
                                    </th>
                                    <th scope="col">
                                        <div>{cs.CaseNumber}</div>
                                    </th>
                                    <th scope="col">
                                        <div>{cs.Subject}</div>
                                    </th>
                                    <th scope="col">
                                        <div>{cs.Status}</div>
                                    </th>
                                    <th scope="col">
                                        <div>{cs.Priority}</div>
                                    </th>
                                    <th scope="col">
                                        <div>{cs.CreatedDate}</div>
                                    </th>
                                    <th scope="col">
                                        <div>{cs.ClosedDate}</div>
                                    </th>
                                </tr>
                    </template>
                </tbody>
            </table>       
    </main>
</template>

app.css

.content {
    padding-top: 2rem;
    padding-left: 2rem;
    padding-right: 2rem;
    padding-bottom: 2rem;
}
header {
    padding: 1rem;
    display: flex;
    color: #ffffff;
    background: #0288d1;
    box-shadow: 0 4px 3px rgba(1, 87, 155, 0.5);
    align-items: center;
}
header img {
    height: 3rem;
    margin-right: 0.3rem;
}
header h2 {
    font-size: 1.75rem;
    font-weight: 300;
}

Step 9: Now, we will delete the unused folder or files. We can delete greeting folder as there is no dependency on this folder for our customer-service-app. We can delete “__tests__” folder as we will not work on this at this moment. So, the entire src structure looks like:

 

 

 

 

 

 

 

Step 10: Now, run the command

npm run watch 

from the terminal of VS Code and you will get the output at http://localhost:3001

 

Fantastic! you have successfully communicated with Salesforce for this LWC Open Source app.

In this example, we can see all the Case records into our own customer-service-app, but the UI doesn’t look good. Something is missing. Yes, you are right. Still, we have not applied Salesforce Lightning Design Styles. Let’s focus this into the next tutorial.

696 total views, 3 views today

No votes yet.
Please wait...

You may also like...