Skip to content

Commit

Permalink
Merge branch 'main' into CallMetadataUpdate
Browse files Browse the repository at this point in the history
  • Loading branch information
DaKingKong committed Dec 20, 2024
2 parents 0470ebd + a51bc5c commit 8acaa3a
Show file tree
Hide file tree
Showing 26 changed files with 163 additions and 76 deletions.
6 changes: 5 additions & 1 deletion .env.test
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,8 @@ DATABASE_URL=sqlite://./db.sqlite
TEST_CRM_CLIENT_ID=
TEST_CRM_CLIENT_SECRET=
TEST_CRM_TOKEN_URI=
TEST_CRM_REDIRECT_URI=https://ringcentral.github.io/ringcentral-embeddable/redirect.html
TEST_CRM_REDIRECT_URI=https://ringcentral.github.io/ringcentral-embeddable/redirect.html


# Admin
ADMIN_EXTENSION_ID_DEV_PASS_LIST=1234567890
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Unified CRM extension for Google Chrome and Microsoft Edge
# RingCentral App Connect for Google Chrome and Microsoft Edge

[![Build Status](https://github.com/ringcentral/rc-unified-crm-extension/workflows/CI%20Pipeline/badge.svg?branch=main)](https://github.com/ringcentral/rc-unified-crm-extension/actions) [![Latest release](https://img.shields.io/github/v/release/ringcentral/rc-unified-crm-extension)](https://github.com/ringcentral/rc-unified-crm-extension/releases) [![Coverage Status](https://coveralls.io/repos/github/ringcentral/rc-unified-crm-extension/badge.svg?branch=main)](https://coveralls.io/github/ringcentral/rc-unified-crm-extension?branch=main)

Expand Down
2 changes: 1 addition & 1 deletion bin/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import inquirer from 'inquirer';

const program = new Command();

program.version(packageJson.version).description('RingCentral CRM Extension');
program.version(packageJson.version).description('RingCentral App Connect');

program
.command('release')
Expand Down
10 changes: 5 additions & 5 deletions docs/crm/netsuite.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ To begin using the NetSuite integration, users will first need to do the followi
* Login to NetSuite, then visit the [RingCentral Suite App](https://www.suiteapp.com/RingCentral-Unified-CRM-Extension) page, or:
* Click on the "SuiteApps" tab if your role gives you access to it
* Search for "RingCentral" in the directory
* Click "RingCentral Unified CRM Extension" in the search results
* Click "RingCentral App Connect" in the search results
* Click the "Install" button found in the upper right hand corner of the page

If you see, "Not compatible" in place of an "Install" button, then you must be running an older version of NetSuite. You will need to upgrade to 2024.2 or later.
Expand All @@ -25,13 +25,13 @@ Installing the app from the SuiteApp marketplace is a necessary step prior to in

## Setup roles and permissions in NetSuite

Upon installation of the SuiteApp, a role will be created automatically within your account called "RingCentral CRM Extension." This role has been specially tuned to contain the bare minimum number access level to fully operate the Chrome extension. You can see a detailed list of permissions below if you would like to incorporate these permissions into a custom role of your own.
Upon installation of the SuiteApp, a role will be created automatically within your account called "RingCentral App Connect." This role has been specially tuned to contain the bare minimum number access level to fully operate the Chrome extension. You can see a detailed list of permissions below if you would like to incorporate these permissions into a custom role of your own.

### NetSuite OneWorld instructions

Upon installing the SuiteApp from the Marketplace, a new custom role named **"RingCentral CRM Extension"** will be automatically created in your account. If you are a OneWorld license holder, you will need to take these additional steps.
Upon installing the SuiteApp from the Marketplace, a new custom role named **"RingCentral App Connect"** will be automatically created in your account. If you are a OneWorld license holder, you will need to take these additional steps.

1. Clone the "RingCentral CRM Extension" role by selecting the "Customize" option.
1. Clone the "RingCentral App Connect" role by selecting the "Customize" option.
2. While cloning, add the permission **"List -> Subsidiaries"** to the cloned role.

Use this cloned role when logging into and connecting App Connect to NetSuite.
Expand All @@ -48,7 +48,7 @@ REST Web Services is default to be invisible. We'll need to turn on the feature

### Create role with required permissions

We recommend using the "RingCentral CRM Extension" role created for you when you install the SuiteApp. However, if you would like to create a custom role that includes the permissions necessary to allow this extension to operate fully, consult the table below.
We recommend using the "RingCentral App Connect" role created for you when you install the SuiteApp. However, if you would like to create a custom role that includes the permissions necessary to allow this extension to operate fully, consult the table below.

| Category | Permission | Level |
| ------------ | ------------------------------------ | ----- |
Expand Down
Binary file added docs/img/admin-bullhorn.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/img/admin-logging.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/img/admin-tab.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/img/admin-user-view.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 7 additions & 1 deletion docs/release-notes.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
# Release notes

## 1.3.0
## 1.3.2

- New: User setting inside call pop to control behavior of multiple matched contacts (disabled, all open, prompt to select)
- Fix: SMS logging issue
- Fix: Auto open extension now only opens when main page is opened

## 1.3.1

- New: (Only for admin users) Admin tools. Admins have an extra tab in the extension to control end users' settings
- Fix: SMS logging date format
Expand Down
57 changes: 57 additions & 0 deletions docs/users/admin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Managing user settings across your account

Super Admins within your RingCentral account have access to an additional area of App Connect in which they can manage the end user's experience across their entire account. This feature primarily allows admins to set certain preferences, or mandate certain preferences across their entire account. This allows admins for example to mandate that all calls across an account be logged. Or that specific settings be employed for their CRM.

<figure markdown>
![Admin tab in App Connect](../img/admin-tab.png){ .mw-400 }
<figcaption>The admin tab in App Connect gives admins the ability to manage settings on behalf of others</figcaption>
</figure>

## Gaining access to the admin tab

When you first load App Connect, you may not see the Admin tab. To make the Admin tab appears please check the following:

1. Make sure you possess the "Super Admin" role in the RingCentral [Admin Console](https://service.ringcentral.com/).
2. Connect to your CRM

## Managing settings on behalf of others

Once you have access to the Admin tab, admins can manage the following:

* Call and SMS logging settings
* Contact and call-pop settings
* CRM-specific settings
* Advanced settings
* Set the custom CRM manifest URL

<figure markdown>
![Logging calls](../img/admin-logging.png){ .mw-400 }
<figcaption>Admins can set call logging policies</figcaption>
</figure>

For each setting that can be managed by an admin, one can do the following:

* Mandate the setting be a specific value. This is done by disabling the user's ability to customize the value, and select the value you prefer.
* Set the default value of a setting. This is done by setting the preferred value, and by enabling the user to customize the value.

### What users within your account will see

When a setting is mandated by an admin, a lock icon will appear next to the setting and it will be disabled, thereby allowing the user to see the value, but be unable to change it.

<figure markdown>
![Logging calls](../img/admin-user-view.png){ .mw-400 }
<figcaption>Admins can manage CRM-specific settings</figcaption>
</figure>

## Managing CRM-specific settings

Each CRM supported by App Connect may expose custom settings. These settings can be managed under the area labeled as "Custom options."

<figure markdown>
![Logging calls](../img/admin-bullhorn.png){ .mw-400 }
<figcaption>Admins can manage CRM-specific settings</figcaption>
</figure>

## Managing custom adapter settings

App Connect enables developers to build custom adapters to connect to proprietary CRMs, or CRMs not supported natively by App Connect. Users can load a custom adapter under "Developer Settings." Admins however can manage this setting across their entire account under the "Custom adapter" area of the Admin tab.
3 changes: 2 additions & 1 deletion mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,13 @@ nav:
- 'Redtail CRM': crm/redtail.md
- 'NetSuite': crm/netsuite.md
- 'User guide':
- 'Accessing the extension': users/access.md
- 'Basic usage': users/access.md
- 'Making and receiving calls': users/making-calls.md
- 'Logging calls': users/logging.md
- 'Sending SMS': users/sms.md
- 'Presence': users/presence.md
- 'Settings': users/settings.md
- 'Administration': users/admin.md
- 'Developer guide':
- 'Introduction': developers/index.md
- 'Getting started': developers/getting-started.md
Expand Down
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "rc-unified-crm-extension-server",
"version": "1.3.0",
"description": "RingCentral Unified CRM Extension",
"version": "1.3.2",
"description": "RingCentral App Connect",
"main": "index.js",
"bin": {
"rc-unified-crm-extension": "bin/index.js"
Expand Down Expand Up @@ -72,4 +72,4 @@
"url": "https://github.com/ringcentral/rc-unified-crm-extension/issues"
},
"homepage": "https://github.com/ringcentral/rc-unified-crm-extension#readme"
}
}
4 changes: 3 additions & 1 deletion serverless-deploy/sample.env.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@ TEST_CRM_CLIENT_SECRET:
TEST_CRM_ACCESS_TOKEN_URI:
TEST_CRM_REDIRECT_URI:

DATABASE_URL:
DATABASE_URL:

ADMIN_EXTENSION_ID_DEV_PASS_LIST:
8 changes: 4 additions & 4 deletions src/adapters/bullhorn/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ async function createContact({ user, authHeader, phoneNumber, newContactName, ne
`${user.platformAdditionalInfo.restUrl}entity/ClientCorporation`,
{
name: "RingCentral_CRM_Extension_Placeholder_Company",
companyDescription: "<strong><span style=\"color: rgb(231,76,60);\">This company was created automatically by the RingCentral Unified CRM Extension. Feel free to edit, or associate this company's contacts to more appropriate records. </span></strong>"
companyDescription: "<strong><span style=\"color: rgb(231,76,60);\">This company was created automatically by the RingCentral App Connect. Feel free to edit, or associate this company's contacts to more appropriate records. </span></strong>"
},
{
headers: {
Expand Down Expand Up @@ -509,15 +509,15 @@ async function createMessageLog({ user, contactInfo, authHeader, message, additi
'</ul>' +
'------------<br>' +
'END<br><br>' +
'--- Created via RingCentral CRM Extension';
'--- Created via RingCentral App Connect';
break;
case 'Voicemail':
subject = `Voicemail left by ${contactInfo.name} - ${moment(message.creationTime).utcOffset(Number(user.timezoneOffset)).format('YY/MM/DD')}`;
comments = `<br><b>${subject}</b><br>Voicemail recording link: ${recordingLink} <br><br>--- Created via RingCentral CRM Extension`;
comments = `<br><b>${subject}</b><br>Voicemail recording link: ${recordingLink} <br><br>--- Created via RingCentral App Connect`;
break;
case 'Fax':
subject = `Fax document sent from ${contactInfo.name} - ${moment(message.creationTime).utcOffset(Number(user.timezoneOffset)).format('YY/MM/DD')}`;
comments = `<br><b>${subject}</b><br>Fax document link: ${faxDocLink} <br><br>--- Created via RingCentral CRM Extension`;
comments = `<br><b>${subject}</b><br>Fax document link: ${faxDocLink} <br><br>--- Created via RingCentral App Connect`;
break;
}

Expand Down
23 changes: 11 additions & 12 deletions src/adapters/clio/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,8 @@ async function unAuthorize({ user }) {

async function findContact({ user, authHeader, phoneNumber, overridingFormat }) {
const numberToQueryArray = [];
if (overridingFormat === '') {
numberToQueryArray.push(phoneNumber.replace(' ', '+'));
}
else {
numberToQueryArray.push(phoneNumber.replace(' ', '+'));
if (overridingFormat !== '') {
const formats = overridingFormat.split(',');
for (var format of formats) {
const phoneNumberObj = parsePhoneNumber(phoneNumber.replace(' ', '+'));
Expand All @@ -94,6 +92,7 @@ async function findContact({ user, authHeader, phoneNumber, overridingFormat })
}
}
}

const matchedContactInfo = [];
for (var numberToQuery of numberToQueryArray) {
const personInfo = await axios.get(
Expand Down Expand Up @@ -194,7 +193,7 @@ async function createCallLog({ user, contactInfo, authHeader, callLog, note, add
const postBody = {
data: {
subject: callLog.customSubject ?? `[Call] ${callLog.direction} Call ${callLog.direction === 'Outbound' ? 'to' : 'from'} ${contactInfo.name} [${contactInfo.phone}]`,
body: `\nContact Number: ${contactInfo.phoneNumber}\nCall Result: ${callLog.result}\nNote: ${note}${callLog.recording ? `\n[Call recording link] ${callLog.recording.link}` : ''}\n\n--- Created via RingCentral CRM Extension`,
body: `\nContact Number: ${contactInfo.phoneNumber}\nCall Result: ${callLog.result}\nNote: ${note}${callLog.recording ? `\n[Call recording link] ${callLog.recording.link}` : ''}\n\n--- Created via RingCentral App Connect`,
type: 'PhoneCommunication',
received_at: moment(callLog.startTime).toISOString(),
senders: [sender],
Expand Down Expand Up @@ -255,8 +254,8 @@ async function updateCallLog({ user, existingCallLog, authHeader, recordingLink,
let patchBody = {};
if (!!recordingLink) {
const urlDecodedRecordingLink = decodeURIComponent(recordingLink);
if (logBody.includes('\n\n--- Created via RingCentral CRM Extension')) {
logBody = logBody.replace('\n\n--- Created via RingCentral CRM Extension', `\n[Call recording link]${urlDecodedRecordingLink}\n\n--- Created via RingCentral CRM Extension`);
if (logBody.includes('\n\n--- Created via RingCentral App Connect')) {
logBody = logBody.replace('\n\n--- Created via RingCentral App Connect', `\n[Call recording link]${urlDecodedRecordingLink}\n\n--- Created via RingCentral App Connect`);
}
else {
logBody += `\n[Call recording link]${urlDecodedRecordingLink}`;
Expand All @@ -274,7 +273,7 @@ async function updateCallLog({ user, existingCallLog, authHeader, recordingLink,
originalNote = logBody.split('\n[Call recording link]')[0].split('Note: ')[1];
}
else {
originalNote = logBody.split('\n\n--- Created via RingCentral CRM Extension')[0].split('Note: ')[1];
originalNote = logBody.split('\n\n--- Created via RingCentral App Connect')[0].split('Note: ')[1];
}

logBody = logBody.replace(`Note: ${originalNote}`, `Note: ${note ?? ''}`);
Expand Down Expand Up @@ -367,15 +366,15 @@ async function createMessageLog({ user, contactInfo, authHeader, message, additi
`${message.subject}\n` +
'------------\n' +
'END\n\n' +
'--- Created via RingCentral CRM Extension';
'--- Created via RingCentral App Connect';
break;
case 'Voicemail':
logSubject = `Voicemail left by ${contactInfo.name} - ${moment(message.creationTime).format('YY/MM/DD')}`;
logBody = `Voicemail recording link: ${recordingLink} \n\n--- Created via RingCentral CRM Extension`;
logBody = `Voicemail recording link: ${recordingLink} \n\n--- Created via RingCentral App Connect`;
break;
case 'Fax':
logSubject = `Fax document sent from ${contactInfo.name} - ${moment(message.creationTime).format('YY/MM/DD')}`;
logBody = `Fax document link: ${faxDocLink} \n\n--- Created via RingCentral CRM Extension`;
logBody = `Fax document link: ${faxDocLink} \n\n--- Created via RingCentral App Connect`;
break;
}
const postBody = {
Expand Down Expand Up @@ -459,7 +458,7 @@ async function getCallLog({ user, callLogId, authHeader }) {
});
const note = getLogRes.data.data.body.includes('[Call recording link]') ?
getLogRes.data.data.body.split('Note: ')[1].split('\n[Call recording link]')[0] :
getLogRes.data.data.body.split('Note: ')[1].split('\n\n--- Created via RingCentral CRM Extension')[0];
getLogRes.data.data.body.split('Note: ')[1].split('\n\n--- Created via RingCentral App Connect')[0];
const contactId = getLogRes.data.data.senders[0].type == 'Person' ?
getLogRes.data.data.senders[0].id :
getLogRes.data.data.receivers[0].id;
Expand Down
Loading

0 comments on commit 8acaa3a

Please sign in to comment.