Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions .yarnrc.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
yarnPath: .yarn/releases/yarn-4.5.1.cjs
checksumBehavior: update

nodeLinker: node-modules
npmRegistryServer: "https://registry.npmjs.org"

npmScopes:
webex-engage:
npmRegistryServer: 'https://engci-maven-master.cisco.com/artifactory/api/npm/webex-release-npm/'
npmAuthIdent: 'cnNhcmlrYTpjbVZtZEd0dU9qQXhPakUzTlRnMk1UQXpNVFk2WmtnMVMyOVlSV2RsYkVkRlFXZDFValZ0YW1wd1FVUk5jbXMz'
npmAlwaysAuth: true
6 changes: 5 additions & 1 deletion packages/contact-center/cc-components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
"dependencies": {
"@momentum-ui/illustrations": "^1.24.0",
"@r2wc/react-to-web-component": "2.0.3",
"@react-stately/collections": "^3.12.5",
"@react-types/shared": "^3.30.0",
"@webex/cc-store": "workspace:*"
},
"devDependencies": {
Expand All @@ -38,6 +40,8 @@
"@testing-library/jest-dom": "6.6.2",
"@testing-library/react": "16.0.1",
"@types/jest": "29.5.14",
"@types/react": "18",
"@types/react-dom": "18",
"@types/react-test-renderer": "18",
"babel-loader": "9.2.1",
"eslint": "^9.20.1",
Expand Down Expand Up @@ -65,4 +69,4 @@
"react": ">=18.3.1",
"react-dom": ">=18.3.1"
}
}
}
4 changes: 3 additions & 1 deletion packages/contact-center/cc-components/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
"compilerOptions": {
"outDir": "./dist",
"declaration": true,
"declarationDir": "./dist/types"
"declarationDir": "./dist/types",
"jsx": "react-jsx",
"skipLibCheck": true
},
}
7 changes: 6 additions & 1 deletion packages/contact-center/cc-components/webpack.config.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const {mergeWithCustomize, customizeObject} = require('webpack-merge');
const path = require('path');

const baseConfig = require('../../../webpack.config');
const baseConfig = require('../../../tooling/webpack/base.config');

// Helper function to resolve paths relative to the monorepo root
const resolveMonorepoRoot = (...segments) => path.resolve(__dirname, '../../../', ...segments);
Expand Down Expand Up @@ -36,6 +36,11 @@ module.exports = mergeWithCustomize({
},
module: {
rules: [
{
test: /\.(ts|tsx)$/,
exclude: /node_modules/,
use: 'ts-loader',
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
Expand Down
6 changes: 6 additions & 0 deletions packages/contact-center/cc-digital-channels/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
const jestConfig = require('../../../jest.config.js');

jestConfig.rootDir = '../../../';
jestConfig.testMatch = ['**/cc-digital-channels/tests/**/*.ts', '**/cc-digital-channels/tests/**/*.tsx'];

module.exports = jestConfig;
45 changes: 45 additions & 0 deletions packages/contact-center/cc-digital-channels/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"name": "@webex/cc-digital-channels",
"version": "1.0.0",
"description": "Minimal implementation of Webex Engage Conversations",
"main": "dist/index.umd.js",
"module": "dist/index.esm.js",
"types": "dist/index.d.ts",
"files": [
"dist"
],
"scripts": {
"dev": "vite --port 3241",
"build:src": "vite build --mode lib",
"build:lib": "vite build --mode lib",
"preview": "vite preview",
"start": "vite --port 3241"
},
"dependencies": {
"@webex-engage/wxengage-conversations": "^1.0.2",
"@webex/cc-store": "workspace:*",
"react": "^18.3.1",
"react-dom": "^18.3.1"
},
"devDependencies": {
"@types/node": "^20.0.0",
"@types/react": "^18.3.23",
"@types/react-dom": "^18.3.7",
"@vitejs/plugin-react": "^4.3.1",
"typescript": "^5.5.3",
"vite": "^5.3.4",
"vite-plugin-dts": "^4.5.4"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import React from 'react';
import Engage from '@webex-engage/wxengage-conversations';

export interface WebexEngageConversationsProps {
conversationId: string;
jwtToken: string;
apiEndpoint: string;
signalREndpoint: string;
onError?: (error: unknown) => boolean;
className?: string;
style?: React.CSSProperties;
}

export const WebexEngageConversations: React.FC<WebexEngageConversationsProps> = ({
conversationId,
jwtToken,
apiEndpoint,
signalREndpoint,
onError,
className,
style
}) => {
const handleError = (error: unknown): boolean => {
if (onError) {
return onError(error);
}
// Default error handling
console.debug('Webex Engage component error:', error);
return false; // Prevent default error handling
};

return (
<div className={className} style={style}>
<md-theme>
<Engage
conversationId={conversationId}
jwtToken={jwtToken}
apiEndpoint={apiEndpoint}
signalREndpoint={signalREndpoint}
onError={handleError}
/>
</md-theme>
</div>
);
};

export default WebexEngageConversations;
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
.digital-channels-container {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
}

.digital-channels-error {
width: 100%;
padding: 16px;
background-color: #f8d7da;
border: 1px solid #f5c6cb;
border-radius: 4px;
color: #721c24;
}

.digital-channels-loading {
width: 100%;
padding: 16px;
background-color: #d1ecf1;
border: 1px solid #bee5eb;
border-radius: 4px;
color: #0c5460;
text-align: center;
}

.error-message,
.loading-message {
font-size: 14px;
font-weight: 500;
}

.digital-channels-container md-theme {
flex: 1;
height: 100%;
}

/* Override default engagement styles if needed */
.digital-channels-container engage-conversations {
height: 100%;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import {ITask} from '@webex/plugin-cc';

export interface UseDigitalChannelsProps {
currentTask: ITask;
jwtToken: string;
apiEndpoint: string;
signalREndpoint: string;
onError?: (error: unknown) => boolean;
logger?: {
log: (message: string, meta?: any) => void;
error: (message: string, error?: any, meta?: any) => void;
};
}

export interface DigitalChannelsProps {
conversationId: string;
jwtToken: string;
apiEndpoint: string;
signalREndpoint: string;
onError?: (error: unknown) => boolean;
className?: string;
style?: React.CSSProperties;
}

export interface ConversationData {
id: string;
status: string;
timestamp: string;
}

export interface Message {
id: string;
content: string;
conversationId: string;
timestamp: string;
type: 'sent' | 'received';
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import React from 'react';
import store from '@webex/cc-store';
import {observer} from 'mobx-react-lite';
import Engage from '@webex-engage/wxengage-conversations';

import {useDigitalChannels} from '../helper';
import {DigitalChannelsProps} from './digital-channels.types';
import './digital-channels.css';

const DigitalChannels: React.FunctionComponent<DigitalChannelsProps> = observer(
({jwtToken, apiEndpoint, signalREndpoint, onError, className, style}) => {
const {logger, currentTask} = store;

if (!currentTask) {
return null;
}

const result = useDigitalChannels({
currentTask,
jwtToken,
apiEndpoint,
signalREndpoint,
onError,
logger,
});

const {handleError, conversationId} = result;

return (
<div className={`digital-channels-container ${className || ''}`} style={style}>
<md-theme>
<Engage
conversationId={conversationId}
jwtToken={jwtToken}
apiEndpoint={apiEndpoint}
signalREndpoint={signalREndpoint}
onError={handleError}
/>
</md-theme>
</div>
);
}
);

export {DigitalChannels};
31 changes: 31 additions & 0 deletions packages/contact-center/cc-digital-channels/src/helper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import {UseDigitalChannelsProps} from './digital-channels/digital-channels.types';

export const useDigitalChannels = (props: UseDigitalChannelsProps) => {
const {jwtToken, apiEndpoint, signalREndpoint, onError, logger, currentTask} = props;

const handleError = (error: unknown): boolean => {
const errorMessage = error instanceof Error ? error.message : 'Unknown error';

logger?.error('Digital channels error', errorMessage, {
module: 'widget-cc-digital-channels#helper.ts',
method: 'handleError',
});

if (onError) {
return onError(error);
}

// Default error handling
console.debug('Webex Engage component error:', errorMessage);
return false; // Prevent default error handling
};

return {
name: 'DigitalChannels',
handleError,
conversationId: currentTask.data.interaction.callAssociatedDetails.mediaResourceId,
jwtToken,
apiEndpoint,
signalREndpoint,
};
};
5 changes: 5 additions & 0 deletions packages/contact-center/cc-digital-channels/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import {DigitalChannels} from './digital-channels';

export {DigitalChannels};
export {DigitalChannels as default};
export {WebexEngageConversations, type WebexEngageConversationsProps} from './components/WebexEngageConversations';
10 changes: 10 additions & 0 deletions packages/contact-center/cc-digital-channels/src/types/global.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Declare custom HTML elements used by the Webex Engage components
declare global {
namespace JSX {
interface IntrinsicElements {
'md-theme': React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>;
}
}
}

export {};
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
declare module '@webex-engage/wxengage-conversations' {
import { ComponentType } from 'react';

interface EngageProps {
conversationId: string;
jwtToken: string;
apiEndpoint: string;
signalREndpoint: string;
onError?: (error: unknown) => boolean;
}

const Engage: ComponentType<EngageProps>;
export default Engage;
}
Loading
Loading