Skip to content

Commit

Permalink
Merge pull request #2 from indexnetwork/init-web-sdk
Browse files Browse the repository at this point in the history
Init Web SDK
  • Loading branch information
serafettin authored Jan 10, 2024
2 parents a217b24 + 2d6c06a commit 845d8c1
Show file tree
Hide file tree
Showing 58 changed files with 13,294 additions and 0 deletions.
32 changes: 32 additions & 0 deletions .github/workflows/web-sdk-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Web-SDK CI

on:
pull_request:
types: [opened, synchronize]
branches: [main]
paths:
- "web-sdk/**"
jobs:
build-and-test:
runs-on: ubuntu-latest

strategy:
matrix:
node-version: [18.x]

steps:
- uses: actions/checkout@v2

- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}

- name: Install dependencies
run: npm install --prefix web-sdk

- name: Build
run: npm run build --prefix web-sdk

- name: Run tests
run: npm test --prefix web-sdk
38 changes: 38 additions & 0 deletions web-sdk/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Dependency directories
node_modules

# Build outputs
dist
build
out
coverage

# System files
.DS_Store
Thumbs.db

# Environment files
.env
.env.local
.env.development.local
.env.test.local
.env.production.local

# IDE/Editor folders
.vscode/
.idea/
*.swp
*.swo

# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Optional npm cache directory
.npm


# Temporary folders
tmp/
temp/
159 changes: 159 additions & 0 deletions web-sdk/README.MD
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
<h1 align="center">
<a href="https://index.network/#gh-light-mode-only">
<img style="width:400px" src="https://index.network/images/IndexNetworkLogo.png">
</a>
<a href="https://index.network/#gh-dark-mode-only">
<img style="width:400px" src="https://index.network/images/IndexNetworkLogo-white.png">
</a>
</h1>
<p align="center">
<i align="center">Create and monetize interoperable discovery engines. 🚀</i>
</p>

<div align="center">

![CI](https://github.com/indexnetwork/index/actions/workflows/web-sdk-ci.yml/badge.svg)
[![npm version](https://img.shields.io/npm/v/index-chat.svg)](https://www.npmjs.com/package/index-chat)

![React](https://img.shields.io/badge/react-18.2-blue.svg)
![TypeScript](https://img.shields.io/badge/typescript-5.3-blue.svg)
![Babel](https://img.shields.io/badge/babel-7.23-blue.svg)
![Webpack](https://img.shields.io/badge/webpack-5.89-blue.svg)
![TailwindCSS](https://img.shields.io/badge/tailwindcss-3.4-blue.svg)

</div>

# IndexChat

IndexChat is a chat UI component specifically designed for interaction within the Index Network.

Super easy to integrate and offers a seamless experience, making it an ideal tool for:

- creators,
- communities,
- DAOs,
- brands,
- researchers, and many more


👉🏻 [View Demo](https://index-demo-eight.vercel.app)


Let's start building! ⛓️


<div>
<img alt="Demo Screen" style="width:500px" src="demo/ui-light.png#gh-light-mode-only" />
<img alt="Demo Screen" style="width:500px" src="demo/ui-dark.png#gh-dark-mode-only" />
</div>


## Features

- Easy to integrate with any React application
- Real-time chat capabilities powered by modern practices
- Responsive design and built-in dark mode
- Fully customizable themes


## Installation

Get the latest package via npm.

```bash
npm install @index-network/web-sdk
```

## Usage

Place `IndexChat` tag into your app with your `index_id`.

This code creates a button that handles all the configuration. Now you can click it to start chatting. No extra work is required. 🎉


```typescript
import IndexChat from '@index-network/web-sdk';

const App = () => {
return (
<div>
{/* Your components */}
<IndexChat id='index_id' />
</div>
);
};

export default App;
```


## Styling

IndexChat allows you to customize the theme by overriding the defaults for any provided value. Here's an example of how you can set a custom theme:


```typescript
const customStyle = {
darkMode: true,
theme: {
light: {
primary: '#0F172A',
secondary: '#475569',
accent: '#BED0EC',
background: '#FFFFFF',
border: '#E2E8F0',
pale: '#F8FAFC',
},
dark: {
primary: '#DFEAF4',
secondary: '#E7EEFF',
accent: '#1256A2',
background: '#0F172A',
border: '#314969',
pale: '#212C45',
},
}
};

const App = () => {
return (
<div>
{/* Your components */}
<IndexChat id='index_id' style={customStyle} />
</div>
);
};
```

### Fonts

The package uses `Inter` as the primary and `Freizeit` as the secondary font default. If you want to enable them, add the following line to your app.

```typescript
import '@index-network/web-sdk/dist/assets/style/fonts.css';
```


## Warnings and Compatibility

Before integrating `web-sdk` into your project, please consider the following:


### Requirements

- <b>React Version:</b> `web-sdk` uses version 18.2.0. Ensure that your project has a compatible version.

- The jsx option is set to `react-jsx`, which requires React 17+.

- <b>TypeScript Version:</b> The package is built with TypeScript 5.3.3. Projects using an older version might encounter compatibility issues.

- `web-sdk` is compiled as a UMD (Universal Module Definition) module. Ensure that your module bundler and environment are compatible with UMD modules.


## Contributing

Contributions are always welcome! Please read the contributing guidelines to get started.

## License

This project is licensed under the MIT License.
53 changes: 53 additions & 0 deletions web-sdk/__test__/components/AskInput.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import '@testing-library/jest-dom';
import { screen, fireEvent } from '@testing-library/react';
import AskInput from '../../src/components/AskInput';
import { renderComponent } from '../mocks/mockProviders';
import { mockChatData, mockThemeData } from '../mocks/mockData';

describe('AskInput', () => {
let chatData: any;
let themeData: any;

beforeEach(() => {
chatData = { ...mockChatData };
themeData = { ... mockThemeData };
jest.clearAllMocks();
});

it('renders input field and send button', () => {
renderComponent(chatData, themeData, AskInput);

expect(screen.getByLabelText('ask-input')).toBeInTheDocument();
expect(screen.getByRole('button')).toBeInTheDocument();
});

it('updates input value on change', () => {
renderComponent(chatData, themeData, AskInput);

const input = screen.getByLabelText('ask-input') as HTMLInputElement;
fireEvent.change(input, { target: { value: 'Test Query' } });
expect(input.value).toBe('Test Query');
});

it('calls sendMessage on send button click with non-empty input', () => {
chatData.sendMessage = jest.fn();
renderComponent(chatData, themeData, AskInput);

const input = screen.getByLabelText('ask-input');
fireEvent.change(input, { target: { value: 'Test Query' } });
fireEvent.click(screen.getByRole('button'));

expect(chatData.sendMessage).toHaveBeenCalledWith('Test Query');
});

it('calls sendMessage on enter key press with non-empty input', () => {
renderComponent(chatData, themeData, AskInput);

const input = screen.getByLabelText('ask-input');
fireEvent.change(input, { target: { value: 'Test Query' } });
fireEvent.keyDown(input, { key: 'Enter', code: 'Enter' });

expect(chatData.sendMessage).toHaveBeenCalledWith('Test Query');
});

});
50 changes: 50 additions & 0 deletions web-sdk/__test__/components/ChatBody.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import '@testing-library/jest-dom';
import { screen } from '@testing-library/react';
import ChatBody from '../../src/components/ChatBody';
import { renderComponent } from '../mocks/mockProviders'
import { mockChatData, mockThemeData } from '../mocks/mockData';

describe('ChatBody', () => {
let chatData: any;
let themeData: any;

beforeEach(() => {
chatData = { ...mockChatData };
themeData = { ...mockThemeData };
jest.clearAllMocks();
});

it('renders messages correctly', () => {
renderComponent(chatData, themeData, ChatBody);

expect(screen.getByLabelText('chat-message')).toBeInTheDocument();
});

it('renders a placeholder when there are no messages', () => {
chatData.messages = [];
renderComponent(chatData, themeData, ChatBody);

expect(screen.getByLabelText('chat-body-placeholder')).toBeInTheDocument();
expect(screen.getByRole('img')).toBeInTheDocument();
});

it('renders user avatar in message - user', () => {
renderComponent(chatData, themeData, ChatBody);

expect(screen.getByAltText('Avatar')).toHaveAttribute('src', 'Test Avatar');
});

it('renders user avatar in message - user', () => {
chatData.userProfile = null;
renderComponent(chatData, themeData, ChatBody);

expect(screen.getByAltText('Avatar')).not.toHaveAttribute('src', 'Test Avatar');
});

it('renders assistant avatar in message - assistant', () => {
chatData.messages[0].role = 'assistant';
renderComponent(chatData, themeData, ChatBody);

expect(screen.getByAltText('Avatar')).toHaveAttribute('src', 'test-file-stub'); // check img file loader stub
});
});
Loading

0 comments on commit 845d8c1

Please sign in to comment.