Skip to content

Commit

Permalink
Updated dependencies and moved to ES6 syntax
Browse files Browse the repository at this point in the history
  • Loading branch information
pozil committed Nov 10, 2021
1 parent a9eefae commit 06ac60b
Show file tree
Hide file tree
Showing 17 changed files with 4,406 additions and 3,221 deletions.
13 changes: 0 additions & 13 deletions .editorconfig

This file was deleted.

6 changes: 6 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# List files or directories below to ignore them when running prettier
# More information: https://prettier.io/docs/en/ignore.html
#

package-lock.json
public/**
6 changes: 6 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"trailingComma": "none",
"singleQuote": true,
"tabWidth": 2,
"printWidth": 200
}
45 changes: 28 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,36 +1,47 @@
# Salesforce React.js integration
# Salesforce React integration

## About
Sample integration project between Salesforce and a React.js application.

This application demonstrates the following concepts:
Sample integration project between Salesforce and a React application.

This app demonstrates the following concepts:

- using [JSforce](https://jsforce.github.io) as a Salesforce client
- authenticating with OAuth 2.0 (login, logout, retrieving session info)
- using the REST API to run a SOQL query
- using the [Salesforce Lightning Design System](https://www.lightningdesignsystem.com) (SLDS) in a web application (all the CSS is provided by SLDS)
- authenticating with OAuth 2.0 (login, logout, retrieving session info)
- using the REST API to run a SOQL query
- using the [Lightning Design System](https://www.lightningdesignsystem.com) (LDS) in a React application (all the CSS and icons of this app are provided by LDS)

The source code of this app is structured in the following way:

- the `client` directory holds the React app
- the `server` directory holds the node.js app that acts as a middleware with the Salesforce Platform

If you are building a React app with LDS, consider using the [React LDS base components](https://react.lightningdesignsystem.com/).

## Installation

1. Create a [Connected App](https://help.salesforce.com/articleView?id=connected_app_create.htm) in Salesforce.

1. Create a `.env` file in the root directory with this content (make sure to replace the values):
```
domain='https://login.salesforce.com'
callbackUrl='http://localhost:8080/auth/callback'
consumerKey='YOUR_CLIENT_KEY'
consumerSecret='YOUR_CLIENT_SECRET'
apiVersion='48.0'
1. Create a `.env` file in the root directory of this project and add this content (make sure to replace the values):

```
loginUrl='https://login.salesforce.com'
callbackUrl='http://localhost:8080/auth/callback'
consumerKey='YOUR_CLIENT_KEY'
consumerSecret='YOUR_CLIENT_SECRET'
apiVersion='53.0'
isHttps='false'
sessionSecretKey='A_SECRET_STRING'
```
isHttps='false'
sessionSecretKey='A_SECRET_STRING'
```

1. Run `npm run build` to build the app.

1. Run `npm start` to start the app.

## Screenshots
<div style="text-align:center;">

<div align="center">
<img src="screenshots/login.png" width="45%" alt="Login screen"/>
<img src="screenshots/main.png" width="45%" alt="Main screen"/>
</div>
73 changes: 0 additions & 73 deletions client-src/scripts/AppComponent.js

This file was deleted.

10 changes: 0 additions & 10 deletions client-src/scripts/app.js

This file was deleted.

69 changes: 69 additions & 0 deletions client/components/App.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import React from 'react';

import NavBar from './NavBar.js';
import LoginPanel from './LoginPanel.js';
import QueryForm from './QueryForm.js';
import QueryResults from './QueryResults.js';

export default class App extends React.Component {
state = {
user: null
};

componentDidMount() {
// Get logged in user
fetch('/auth/whoami', {
method: 'get',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
}
}).then((response) => {
if (response.ok) {
response.json().then((json) => {
this.setState({ user: json });
});
} else if (response.status !== 401) {
// Ignore 'unauthorized' responses before logging in
console.error('Failed to retrieve logged user.', JSON.stringify(response));
}
});
}

handleQueryExecution = (data) => {
// Send SOQL query to server
const queryUrl = '/query?q=' + encodeURI(data.query);
fetch(queryUrl, {
headers: {
Accept: 'application/json'
},
cache: 'no-store'
}).then((response) => {
response.json().then((json) => {
if (response.ok) {
this.setState({ result: JSON.stringify(json, null, 2) });
} else {
this.setState({
result: 'Failed to retrieve query result.'
});
}
});
});
};

render() {
return (
<div>
<NavBar user={this.state.user} />
{this.state.user == null ? (
<LoginPanel />
) : (
<div className="slds-m-around--xx-large">
<QueryForm onExecuteQuery={this.handleQueryExecution} />
{this.state.result ? <QueryResults result={this.state.result} /> : null}
</div>
)}
</div>
);
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
var React = require('react');
import React from 'react';

var LoginPanel = module.exports = React.createClass({
login: function() {
export default class LoginPanel extends React.Component {
login() {
window.location = '/auth/login';
},
render: function() {
}

render() {
return (
<div className="slds-modal slds-fade-in-open">
<div className="slds-modal__container">
Expand All @@ -23,4 +24,4 @@ var LoginPanel = module.exports = React.createClass({
</div>
);
}
});
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
var React = require('react');
import React from 'react';

var NavBar = module.exports = React.createClass({
logout: function() {
export default class NavBar extends React.Component {
logout() {
window.location = '/auth/logout';
},
render: function() {
}

render() {
return (
<div className="slds-page-header" role="banner">
<div className="slds-grid">

{/* Banner */}
<div className="slds-col slds-has-flexi-truncate">
<div className="slds-media slds-media--center slds-no-space slds-grow">
Expand All @@ -18,35 +18,34 @@ var NavBar = module.exports = React.createClass({
</svg>
</div>
<div className="slds-media__body">
<p className="slds-page-header__title slds-truncate slds-align-middle" title="Salesforce React Integration">Salesforce React Integration</p>
<p className="slds-text-body--small page-header__info">A sample integration project between Force.com and a React application</p>
<p className="slds-page-header__title slds-truncate slds-align-middle" title="Salesforce React Integration">
Salesforce React Integration
</p>
<p className="slds-text-body--small page-header__info">A sample integration project between Salesforce Platform and a React application</p>
</div>
</div>
</div>

{
/* Logged user name */
this.props.user == null ? null :
<div className="slds-col--padded slds-no-flex slds-grid slds-align-middle">
Hi {this.props.user.display_name}
</div>
this.props.user == null ? null : <div className="slds-col--padded slds-no-flex slds-grid slds-align-middle">Hi {this.props.user.display_name}</div>
}

{
/* Logout button */
this.props.user == null ? null :
<div className="slds-col slds-no-flex slds-grid">
<button onClick={this.logout} className="slds-button slds-button--neutral">
<svg aria-hidden="true" className="slds-button__icon--stateful slds-button__icon--left">
<use xlinkHref="/assets/icons/utility-sprite/svg/symbols.svg#logout"></use>
</svg>
Log out
</button>
</div>
this.props.user == null ? null : (
<div className="slds-col slds-no-flex slds-grid">
<button onClick={this.logout} className="slds-button slds-button--neutral">
<svg aria-hidden="true" className="slds-button__icon--stateful slds-button__icon--left">
<use xlinkHref="/assets/icons/utility-sprite/svg/symbols.svg#logout"></use>
</svg>
Log out
</button>
</div>
)
}

</div>
</div>
);
}
});
}
Loading

0 comments on commit 06ac60b

Please sign in to comment.