Skip to content

Commit a2f3b7a

Browse files
committed
first commit
0 parents  commit a2f3b7a

39 files changed

+3094
-0
lines changed

.editorconfig

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[*.{js,jsx,ts,tsx,vue}]
2+
indent_style = space
3+
indent_size = 2
4+
trim_trailing_whitespace = true
5+
insert_final_newline = true

.eslintrc.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
module.exports = {
2+
root: true,
3+
env: {
4+
node: true
5+
},
6+
extends: ['plugin:vue/essential', 'eslint:recommended'],
7+
rules: {
8+
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
9+
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
10+
'no-empty-pattern': 'off',
11+
'no-unused-vars': 'warn'
12+
},
13+
parserOptions: {
14+
parser: 'babel-eslint'
15+
}
16+
}

.gitignore

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
.DS_Store
2+
node_modules
3+
/dist
4+
package-lock.json
5+
6+
# local env files
7+
.env.local
8+
.env.*.local
9+
10+
# Log files
11+
npm-debug.log*
12+
yarn-debug.log*
13+
yarn-error.log*
14+
15+
# Editor directories and files
16+
.idea
17+
.vscode
18+
*.suo
19+
*.ntvs*
20+
*.njsproj
21+
*.sln
22+
*.sw?

.npmignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
demo
2+
*.map

.prettierrc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"singleQuote": true,
3+
"semi": false,
4+
"useTabs": true
5+
}

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2019 Antoine Dupont
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 264 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,264 @@
1+
<p align="center">
2+
<a href="https://travis-ci.org/antoine92190/vue-advanced-chat"><img src="https://img.shields.io/travis/antoine92190/vue-advanced-chat/master.svg"></a>
3+
<a href="https://www.npmjs.com/package/vue-advanced-chat"><img src="https://img.shields.io/npm/dm/vue-advanced-chat.svg"></a>
4+
<a href="https://www.npmjs.com/package/vue-advanced-chat"><img src="https://img.shields.io/npm/v/vue-advanced-chat.svg"></a>
5+
<a href="https://www.npmjs.com/package/vue-advanced-chat"><img src="https://img.shields.io/npm/l/vue-advanced-chat.svg"></a>
6+
</p>
7+
8+
# vue-advanced-chat
9+
10+
## Features
11+
12+
- Realtime chat messaging
13+
- Customizeable
14+
- Backend agnostic
15+
- Images, files & emojis
16+
- Firestore example
17+
18+
## [Demo](https://antoine92190.github.io/vue-advanced-chat)
19+
20+
Enjoy :smile:
21+
22+
## Table of Contents
23+
24+
- [Installation](#installation)
25+
- [Usage](#example)
26+
- [Props API](#props-api)
27+
- [Props data structure](#props-data-structure)
28+
- [Events API](#events-api)
29+
- [Using with Firestore](#using-with-firestore)
30+
31+
## Installation
32+
33+
```bash
34+
# Using npm
35+
npm install --save vue-advanced-chat
36+
37+
# Using yarn
38+
yarn add --save vue-advanced-chat
39+
```
40+
41+
## Usage
42+
43+
You can import it as a custom component:
44+
45+
```html
46+
<template>
47+
<chat-window :rooms="rooms" :messages="messages" />
48+
</template>
49+
50+
<script>
51+
import ChatWindow from 'vue-advanced-chat'
52+
import 'vue-advanced-chat/dist/vue-advanced-chat.css'
53+
54+
export default {
55+
components: {
56+
ChatWindow
57+
},
58+
data() {
59+
return {
60+
userId: '1234'
61+
rooms: [],
62+
messages: []
63+
}
64+
}
65+
}
66+
</script>
67+
```
68+
69+
## Props API
70+
71+
| Prop | Type | Required | Default |
72+
| ------------------ | ------- | -------- | ------- |
73+
| height | String | - | 600px |
74+
| rooms | Array | - | [ ] |
75+
| loadingRooms (1) | Boolean | - | false |
76+
| messages | Array | - | [ ] |
77+
| messagesLoaded (2) | Boolean | - | false |
78+
| menuActions (3) | Array | - | [ ] |
79+
| showFiles | Boolean | - | true |
80+
| showEmojis | Boolean | - | true |
81+
| textMessages (4) | Object | - | null |
82+
83+
(1) `loadingRooms` is must be used to show/hide a spinner icon while rooms are loading
84+
85+
(2) `messagesLoaded` must be manually set to `true` when all messages of a conversation have been loaded. Meaning the user cannot scroll on top anymore
86+
87+
(3) `menuActions` can be used to display your own buttons when clicking the vertical dots icon inside a room.<br>
88+
You can then use the [menuActionHandler](#events-api) event to call your own action after clicking a button. Ex:
89+
90+
```javascript
91+
menuActions="[
92+
{
93+
name: 'inviteUser',
94+
title: 'Invite User'
95+
},
96+
{
97+
name: 'removeUser',
98+
title: 'Remove User'
99+
},
100+
{
101+
name: 'deleteRoom',
102+
title: 'Delete Room'
103+
}
104+
]"
105+
```
106+
107+
(4) `textMessages` can be used to replace default texts. Ex:
108+
109+
```javascript
110+
textMessages="{
111+
MESSAGE_DELETED: 'Ce message a été supprimé',
112+
MESSAGES_EMPTY: 'Aucun message',
113+
CONVERSATION_STARTED: 'La conversation a commencée le :',
114+
TYPE_MESSAGE: 'Taper votre message',
115+
SEARCH: 'Rechercher'
116+
}"
117+
```
118+
119+
## Props data structure
120+
121+
Your props must follow a specific structure to display rooms and messages correctly:
122+
123+
### Rooms prop
124+
125+
```javascript
126+
rooms="[
127+
{
128+
roomId: 1,
129+
roomName: 'Room 1',
130+
users: [
131+
{
132+
_id: 1234,
133+
username: 'John Doe'
134+
},
135+
{
136+
_id: 4321,
137+
username: 'John Snow'
138+
}
139+
]
140+
}
141+
]"
142+
```
143+
144+
### Messages prop
145+
146+
Message objects are rendered differently depending on their type. Currently, only text, emoji and file types are supported.<br>
147+
Each message object has a `sender_id` field which can have the value 'me' or the id of the corresponding agent.
148+
149+
```javascript
150+
messages="[
151+
{
152+
content: 'message 1",
153+
sender_id: 1234,
154+
username: 'John Doe',
155+
date: '13 November',
156+
timestamp: '10:20',
157+
file: {
158+
name: 'My File',
159+
size: 67351,
160+
type: 'png',
161+
url: 'https://firebasestorage.googleapis.com/...'
162+
}
163+
}
164+
]"
165+
```
166+
167+
## Events API
168+
169+
| Event | Params | Fires when |
170+
| --------------------- | --------------------------------------------- | ----------------------------------------------------- |
171+
| fetchMessages (1) | `{ room, options }` | A user has scrolled on top to load more messages |
172+
| sendMessage | `{ roomId, content, file (3) }` | A user has sent a message |
173+
| editMessage | `{ roomId, messageId, newContent, file (3) }` | A user has edited a message |
174+
| deleteMessage | `{ roomId, messageId }` | A user has deleted a message |
175+
| uploadFile | `{ roomId, messageId, file (3) }` | A user has uploaded a file |
176+
| addRoom | - | A user clicks on the plus icon next to searchbar |
177+
| menuActionHandler (2) | `{ roomId, action }` | A user clicks on the vertical dots icon inside a room |
178+
179+
(1) `fetchMessages` should be a method implementing a pagination system. Its purpose is to load older messages of a conversation when the user scroll on top
180+
181+
(2) `menuActionHandler` is the result of the `menuActions` prop.<br>
182+
When clicking a button from your `menuActions` array, `menuActionHandler` will give you the name of the button that was click.
183+
Then you can do whatever you want with it. Ex:
184+
185+
```javascript
186+
menuActionHandler({ roomId, action }) {
187+
switch (action.name) {
188+
case 'inviteUser':
189+
// call a method to invite a user to the room
190+
case 'removeUser':
191+
// call a method to remove a user from the room
192+
case 'deleteRoom':
193+
// call a method to delete the room
194+
}
195+
},
196+
```
197+
198+
(3) All file params contain: `{ blob, localURL, name, size, type }`
199+
200+
## Using with Firestore
201+
202+
### Source code
203+
204+
You can find the source code to implement a full featured chat app using Firebase/Firestore inside the `demo` folder.
205+
<br>
206+
To test it using your own Firebase project:
207+
208+
- Clone this repository: `git clone https://github.com/antoine92190/vue-advanced-chat.git`
209+
- Inside `demo/src/firestore/index.js` file, replace the line `const config = { ... }` by your own Firebase config
210+
- Go inside `demo` folder and run `npm run serve`
211+
212+
### Data structure
213+
214+
If you decide to use the same code as in the `demo` folder to create your chat app, you need to have a specific Firestore data structure.<br>
215+
To help you get started, I added in `demo/src/App.vue` a method `addData` to initialize some data on your Firestore database.
216+
217+
#### Users collection
218+
219+
```javascript
220+
users: {
221+
USER_ID_1: {
222+
_id: 1,
223+
username: 'User 1'
224+
},
225+
USER_ID_2: {
226+
_id: 2,
227+
username: 'User 2'
228+
},
229+
USER_ID_3: {
230+
_id: 3,
231+
username: 'User 2'
232+
}
233+
}
234+
```
235+
236+
#### Rooms collection
237+
238+
```javascript
239+
chatRooms: {
240+
ROOM_ID_1: {
241+
users: [1, 3]
242+
},
243+
ROOM_ID_2: {
244+
users: [1, 2, 3]
245+
}
246+
}
247+
```
248+
249+
#### Messages collection inside a room document
250+
251+
```javascript
252+
messages: {
253+
MESSAGE_ID_1: {
254+
content: 'My first message',
255+
sender_id: 2,
256+
timestamp: 'December 11, 2019 at 4:00:00 PM UTC+2,
257+
seen: true
258+
}
259+
}
260+
```
261+
262+
## License
263+
264+
This project is licensed under [MIT License](http://en.wikipedia.org/wiki/MIT_License)

babel.config.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module.exports = {
2+
presets: ['@vue/cli-plugin-babel/preset']
3+
}

demo/.editorconfig

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[*.{js,jsx,ts,tsx,vue}]
2+
indent_style = space
3+
indent_size = 2
4+
trim_trailing_whitespace = true
5+
insert_final_newline = true

demo/.eslintrc.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
module.exports = {
2+
root: true,
3+
env: {
4+
node: true
5+
},
6+
extends: ['plugin:vue/essential', 'eslint:recommended'],
7+
rules: {
8+
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
9+
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
10+
'no-empty-pattern': 'off',
11+
'no-unused-vars': 'warn'
12+
},
13+
parserOptions: {
14+
parser: 'babel-eslint'
15+
}
16+
}

0 commit comments

Comments
 (0)