diff --git a/client/src/App.jsx b/client/src/App.jsx
index ab2d1e1..fa2849a 100644
--- a/client/src/App.jsx
+++ b/client/src/App.jsx
@@ -18,6 +18,7 @@ import Contacts from './pages/Contacts/Contacts.jsx';
import ContactForm from './pages/ContactForm/ContactForm.jsx';
import DemoAccountInitializer from './services/demoAccountInitializer.js';
import createPrefixedLogger from './helpers/logger.js';
+import Navigator from './pages/Navigator/Navigator.jsx';
const logger = createPrefixedLogger('App');
@@ -61,6 +62,7 @@ function App() {
} />
} />
} />
+ } />
);
}
diff --git a/client/src/api/index.js b/client/src/api/index.js
index 767bce5..7d57380 100644
--- a/client/src/api/index.js
+++ b/client/src/api/index.js
@@ -4,7 +4,6 @@ import { clearAllState } from '../store/actions';
const isDev = process.env.NODE_ENV === 'development';
const apiUrl = isDev ? process.env.BACKEND_DEV_HOST : process.env.BACKEND_PROD_HOST;
-
const clearState = async () => {
store.dispatch(clearAllState());
await persistor.purge();
@@ -79,4 +78,7 @@ export const api = Object.freeze({
contacts: {
send: data => instance.post('/contacts/send', data),
},
+ navigator: {
+ getData: () => instance.get('/navigator/data'),
+ },
});
diff --git a/client/src/assets/text.json b/client/src/assets/text.json
index 8ca179a..b07ca2e 100644
--- a/client/src/assets/text.json
+++ b/client/src/assets/text.json
@@ -32,7 +32,8 @@
"tabs": {
"dashboard": "Dashboard",
"templates": "Templates",
- "contacts": "Contacts"
+ "contacts": "Contacts",
+ "navigator": "Navigator"
},
"envelopes": {
"emptyList": "Create some Embedded Sending transactions and they will start showing up here",
@@ -140,5 +141,12 @@
"github": "https://github.com/docusign/sample-app-embeddedsending-node",
"createsandbox": "https://go.docusign.com/o/sandbox/",
"learnmore": "https://developers.docusign.com/docs/esign-rest-api/esign101/concepts/embedding/embed-sender-correct-views/"
+ },
+ "navigator": {
+ "behindScenes": {
+ "scenarioOverview": "This scenario demonstrates a simple navigation widget that allows users to select different options.",
+ "codeFlow": "View the source code: [navigatorController.js](https://github.com/docusign/sample-app-embeddedsending-node/blob/main/server/controllers/navigatorController.js)",
+ "step1": "The application fetches navigation options from the backend API and displays them in an interactive widget."
+ }
}
}
diff --git a/client/src/components/SidebarLayoutFrame/SidebarLayoutFrame.jsx b/client/src/components/SidebarLayoutFrame/SidebarLayoutFrame.jsx
index 399b197..a46d227 100644
--- a/client/src/components/SidebarLayoutFrame/SidebarLayoutFrame.jsx
+++ b/client/src/components/SidebarLayoutFrame/SidebarLayoutFrame.jsx
@@ -22,6 +22,9 @@ const SidebarLayoutFrame = ({ children }) => {
{t.tabs.contacts}
+
+ {t.tabs.navigator}
+
{children}
diff --git a/client/src/constants.js b/client/src/constants.js
index 2fb6299..0016395 100644
--- a/client/src/constants.js
+++ b/client/src/constants.js
@@ -5,6 +5,7 @@ export const AppRoute = {
CONTACTS: '/contacts',
ADD_CONTACT: '/contacts/new',
EDIT_CONTACT_PREFIX: '/contacts/edit',
+ NAVIGATOR: '/navigator'
};
export const AppRouteFactory = {
diff --git a/client/src/pages/Navigator/Navigator.jsx b/client/src/pages/Navigator/Navigator.jsx
new file mode 100644
index 0000000..3ba021b
--- /dev/null
+++ b/client/src/pages/Navigator/Navigator.jsx
@@ -0,0 +1,20 @@
+import withAuth from '../../hocs/withAuth/withAuth.jsx';
+import AuthLayout from '../../components/AuthLayout/AuthLayout.jsx';
+import t from '../../helpers/t.js';
+import SidebarLayoutFrame from '../../components/SidebarLayoutFrame/SidebarLayoutFrame.jsx';
+import NavigatorContent from './components/NavigatorContent.jsx';
+import NavigatorBehindScenes from './components/NavigatorBehindScenes.jsx';
+
+const NavigatorNonAuth = () => {
+ return (
+ }>
+
+ {t.tabs.navigator}
+
+
+
+ );
+};
+
+const Navigator = withAuth(NavigatorNonAuth);
+export default Navigator;
\ No newline at end of file
diff --git a/client/src/pages/Navigator/components/NavigatorBehindScenes.jsx b/client/src/pages/Navigator/components/NavigatorBehindScenes.jsx
new file mode 100644
index 0000000..8b5ba9a
--- /dev/null
+++ b/client/src/pages/Navigator/components/NavigatorBehindScenes.jsx
@@ -0,0 +1,22 @@
+import BehindScenesContainer from '../../../components/BehindScenes/BehindScenesContainer';
+import BehindScenesSection from '../../../components/BehindScenes/BehindScenesSection';
+import TextWithAnchorsMarkup from '../../../components/BehindScenes/TextWithAnchorsMarkup';
+import t from '../../../helpers/t';
+
+const NavigatorBehindScenes = () => {
+ return (
+
+
+ {t.navigator.behindScenes.scenarioOverview}
+
+
+ {t.navigator.behindScenes.codeFlow}
+
+
+ {t.navigator.behindScenes.step1}
+
+
+ );
+};
+
+export default NavigatorBehindScenes;
\ No newline at end of file
diff --git a/client/src/pages/Navigator/components/NavigatorContent.jsx b/client/src/pages/Navigator/components/NavigatorContent.jsx
new file mode 100644
index 0000000..96bb63e
--- /dev/null
+++ b/client/src/pages/Navigator/components/NavigatorContent.jsx
@@ -0,0 +1,80 @@
+import { useState, useEffect, useRef } from 'react';
+import { useSelector } from 'react-redux';
+import { api } from '../../../api';
+import styles from './NavigatorContent.module.css';
+
+const NavigatorContent = () => {
+ const [error, setError] = useState(null);
+ const iframe = useRef(null);
+ const userEmail = useSelector(state => state.auth.userEmail);
+ const userName = useSelector(state => state.auth.userName);
+
+ useEffect(() => {
+ const initNavigator = async () => {
+ try {
+ const response = await api.navigator.getData();
+ const { token } = response.data;
+ console.log('Navigator token:', token);
+ if (!iframe.current) return;
+
+ // Configure the iframe
+ iframe.current.src = 'https://apps-d.docusign.com/navigator-for-partners';
+
+ const handleIframeLoad = () => {
+ const dataToSend = {
+ message: 'Embedded-Navigator-View',
+ authInfo: { access_token: token },
+ userInfo: {
+ sub: '13f69e9e-d3ec-4cfe-b551-5ff33b1751c8',
+ name: "prudhvi nag",
+ email: "prudhvinag@dsxtr.com",
+ accounts: [{
+ account_id: 'c9b55f81-6261-4a6e-b53f-59a2d341c10f',
+ name: userName,
+ is_default: true,
+ account_name: userName,
+ base_uri: 'https://demo.docusign.net',
+ }]
+ },
+ envelopeIds: [],
+ currentAccount: 'c9b55f81-6261-4a6e-b53f-59a2d341c10f',
+ timestamp: new Date().toISOString()
+ };
+
+ iframe.current.contentWindow.postMessage(
+ dataToSend,
+ iframe.current.src
+ );
+ };
+
+ iframe.current.onload = handleIframeLoad;
+
+ } catch (err) {
+ setError(err.message);
+ console.error('Navigator initialization error:', err);
+ }
+ };
+
+ initNavigator();
+ }, [userEmail, userName]);
+
+ if (error) return
Error: {error}
;
+
+ return (
+
+
+
DocuSign Navigator
+
+
+
+
+
+ );
+};
+
+export default NavigatorContent;
\ No newline at end of file
diff --git a/client/src/pages/Navigator/components/NavigatorContent.module.css b/client/src/pages/Navigator/components/NavigatorContent.module.css
new file mode 100644
index 0000000..72a3ef6
--- /dev/null
+++ b/client/src/pages/Navigator/components/NavigatorContent.module.css
@@ -0,0 +1,70 @@
+.container {
+ padding: 20px;
+}
+
+.widget {
+ background: white;
+ border-radius: 8px;
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+ padding: 24px;
+ height: calc(100vh - 120px);
+ display: flex;
+ flex-direction: column;
+}
+
+.widgetTitle {
+ color: #333;
+ font-size: 1.5rem;
+ margin-bottom: 20px;
+}
+
+.widgetContent {
+ display: flex;
+ flex-direction: column;
+ gap: 20px;
+}
+
+.content {
+ padding: 16px;
+ background: #f8f9fa;
+ border-radius: 4px;
+}
+
+.label {
+ color: #495057;
+ font-weight: 600;
+ margin-bottom: 8px;
+}
+
+.token {
+ font-family: monospace;
+ word-break: break-all;
+ padding: 12px;
+ background: #e9ecef;
+ border-radius: 4px;
+ border: 1px solid #dee2e6;
+}
+
+.loading {
+ text-align: center;
+ padding: 20px;
+}
+
+.error {
+ color: red;
+ padding: 20px;
+}
+
+.iframeContainer {
+ flex: 1;
+ min-height: 0;
+ position: relative;
+}
+
+.navigatorFrame {
+ width: 100%;
+ height: 100%;
+ border: none;
+ border-radius: 4px;
+ background: #f8f9fa;
+}
\ No newline at end of file
diff --git a/server/constants.js b/server/constants.js
index 93b1761..edd09dd 100644
--- a/server/constants.js
+++ b/server/constants.js
@@ -3,6 +3,7 @@ const BackendRoute = {
TEMPLATE: '/api/templates',
CONTACT: '/api/contacts',
ENVELOPE: '/api/envelopes',
+ NAVIGATOR: '/api/navigator'
};
const AuthMethod = {
@@ -23,7 +24,7 @@ const ViewType = {
// https://developers.docusign.com/platform/auth/reference/scopes/
// signature - Required to call most eSignature REST API endpoints
-const EMBEDDED_SENDING_SCOPES = ['signature', 'impersonation'];
+const EMBEDDED_SENDING_SCOPES = ['signature', 'impersonation', 'cds_read', 'adm_store_unified_repo_read'];
const ALLOWED_FOR_EDIT_ENVELOPE_STATUSES = ['sent', 'correct'];
diff --git a/server/controllers/navigatorController.js b/server/controllers/navigatorController.js
new file mode 100644
index 0000000..61c510e
--- /dev/null
+++ b/server/controllers/navigatorController.js
@@ -0,0 +1,23 @@
+const createPrefixedLogger = require('../utils/logger');
+const logger = createPrefixedLogger('[NavigatorController]');
+
+const getData = async (req, res, next) => {
+ try {
+ // Get token based on auth method
+ const token = req.user?.accessToken || req.session?.accessToken;
+ console.log('Access Token:', token);
+ const data = {
+ status: 'success',
+ message: 'Access token retrieved successfully',
+ token: token || 'No token available'
+ };
+ res.json(data);
+ } catch (error) {
+ logger.error('Error in getData:', error);
+ next(error);
+ }
+};
+
+module.exports = {
+ getData
+};
\ No newline at end of file
diff --git a/server/routes/navigatorRouter.js b/server/routes/navigatorRouter.js
new file mode 100644
index 0000000..bb8038a
--- /dev/null
+++ b/server/routes/navigatorRouter.js
@@ -0,0 +1,9 @@
+const { Router } = require('express');
+const navigatorController = require('../controllers/navigatorController');
+const authMiddleware = require('../middlewares/authMiddleware');
+
+const router = Router();
+
+router.get('/data', authMiddleware, navigatorController.getData);
+
+module.exports = router;
\ No newline at end of file
diff --git a/server/server.js b/server/server.js
index 2043ea8..0516332 100644
--- a/server/server.js
+++ b/server/server.js
@@ -16,6 +16,7 @@ const authRouter = require('./routes/authRouter');
const templatesRouter = require('./routes/templatesRouter');
const contactsRouter = require('./routes/contactsRouter');
const envelopesRouter = require('./routes/envelopesRouter');
+const navigatorRouter = require('./routes/navigatorRouter');
const createPrefixedLogger = require('./utils/logger');
const resolveAuthController = require('./utils/authControllerResolver');
@@ -55,6 +56,7 @@ app.use(BackendRoute.AUTH, authRouter);
app.use(BackendRoute.TEMPLATE, templatesRouter);
app.use(BackendRoute.CONTACT, contactsRouter);
app.use(BackendRoute.ENVELOPE, envelopesRouter);
+app.use(BackendRoute.NAVIGATOR, navigatorRouter);
async function start() {
try {