denshobato_chat_panel 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +10 -0
- data/.rspec +2 -0
- data/.travis.yml +4 -0
- data/Gemfile +4 -0
- data/README.md +93 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/denshobato_chat_panel.gemspec +29 -0
- data/lib/api/conversation_api.rb +32 -0
- data/lib/api/denshobato_api.rb +6 -0
- data/lib/api/message_api.rb +96 -0
- data/lib/denshobato_chat_panel/engine.rb +5 -0
- data/lib/denshobato_chat_panel/react_helper.rb +7 -0
- data/lib/denshobato_chat_panel/version.rb +3 -0
- data/lib/denshobato_chat_panel.rb +9 -0
- data/lib/generators/denshobato_chat_panel/assets/javascripts/denshobato.js +26077 -0
- data/lib/generators/denshobato_chat_panel/assets/stylesheets/denshobato.scss +441 -0
- data/lib/generators/denshobato_chat_panel/install_generator.rb +50 -0
- data/lib/react/actions/Conversation.jsx +9 -0
- data/lib/react/actions/Index.jsx +7 -0
- data/lib/react/actions/Messages.jsx +30 -0
- data/lib/react/api/Api.jsx +19 -0
- data/lib/react/components/Message.jsx +47 -0
- data/lib/react/components/MessageForm.jsx +37 -0
- data/lib/react/components/Messages.jsx +110 -0
- data/lib/react/containers/MessagesContainer.jsx +47 -0
- data/lib/react/denshobato.js +18 -0
- data/lib/react/reducers/Conversation.jsx +20 -0
- data/lib/react/reducers/Index.jsx +8 -0
- data/lib/react/reducers/Messages.jsx +21 -0
- data/lib/react/store/Store.jsx +8 -0
- data/lib/react/utils/ChatUtils.js +12 -0
- data/package.json +35 -0
- data/webpack.config.js +21 -0
- metadata +163 -0
@@ -0,0 +1,110 @@
|
|
1
|
+
import React, { Component } from 'react';
|
2
|
+
import store from '../store/Store';
|
3
|
+
import { actions } from '../actions/Index';
|
4
|
+
import Message from './Message';
|
5
|
+
import { reset } from 'redux-form';
|
6
|
+
import MessageForm from './MessageForm';
|
7
|
+
import ChatUtils from '../utils/ChatUtils';
|
8
|
+
|
9
|
+
const room = document.getElementById('denshobato-message-panel');
|
10
|
+
|
11
|
+
export default class Messages extends Component {
|
12
|
+
static propTypes = {
|
13
|
+
conversation: React.PropTypes.shape({
|
14
|
+
senderId: React.PropTypes.number,
|
15
|
+
conversationId: React.PropTypes.number,
|
16
|
+
senderClass: React.PropTypes.string,
|
17
|
+
}),
|
18
|
+
showAll: React.PropTypes.bool.isRequired,
|
19
|
+
messages: React.PropTypes.arrayOf(React.PropTypes.object),
|
20
|
+
};
|
21
|
+
|
22
|
+
constructor(props) {
|
23
|
+
super(props);
|
24
|
+
};
|
25
|
+
|
26
|
+
componentDidMount() {
|
27
|
+
store.dispatch(actions.conversation.conversation(room.dataset.room, room.dataset.currentUserId, room.dataset.currentUserClass));
|
28
|
+
}
|
29
|
+
|
30
|
+
componentWillReceiveProps(nextProps) {
|
31
|
+
if (nextProps.messages.length != this.props.messages.length) {
|
32
|
+
this.refreshChat();
|
33
|
+
}
|
34
|
+
}
|
35
|
+
|
36
|
+
handleSubmit = (e) => {
|
37
|
+
const { conversation } = this.props;
|
38
|
+
this.refreshChat();
|
39
|
+
store.dispatch(actions.messages.create(e.body, conversation.senderId, conversation.conversationId, conversation.senderClass));
|
40
|
+
store.dispatch(reset('message-form'));
|
41
|
+
};
|
42
|
+
|
43
|
+
refreshChat = () => {
|
44
|
+
store.dispatch(actions.messages.fetch(room.dataset.room));
|
45
|
+
};
|
46
|
+
|
47
|
+
showAll = () => {
|
48
|
+
store.dispatch(actions.messages.showAll());
|
49
|
+
};
|
50
|
+
|
51
|
+
render() {
|
52
|
+
const { messages, conversation, showAll } = this.props;
|
53
|
+
|
54
|
+
return (
|
55
|
+
<div>
|
56
|
+
<div className="top_menu">
|
57
|
+
<div className="buttons">
|
58
|
+
<div className="button close-button" onClick={ChatUtils.closeChat}></div>
|
59
|
+
<div className="button minimize"></div>
|
60
|
+
<div className="button maximize"></div>
|
61
|
+
</div>
|
62
|
+
<div className="title">
|
63
|
+
<div className="chat-header">
|
64
|
+
<div className="header-description">
|
65
|
+
<p>
|
66
|
+
{`Chat with ${conversation.recipient}`}
|
67
|
+
</p>
|
68
|
+
</div>
|
69
|
+
</div>
|
70
|
+
</div>
|
71
|
+
<button className="refresh-button btn" onClick={this.refreshChat}>Refresh</button>
|
72
|
+
</div>
|
73
|
+
<div className='chat-wrapper'>
|
74
|
+
<div className='chat-message padding'>
|
75
|
+
{ do {
|
76
|
+
if (messages.length >= 50 && !showAll) {
|
77
|
+
<div className='text-center'>
|
78
|
+
<button className='load-messages' onClick={this.showAll}>Load previous messages</button>
|
79
|
+
</div>;
|
80
|
+
}
|
81
|
+
} }
|
82
|
+
|
83
|
+
{/* TODO: Refactoring this condition. */}
|
84
|
+
{ do {
|
85
|
+
if (messages.length >= 50 && !showAll) {
|
86
|
+
messages.slice(Math.max(messages.length - 50, 1)).map((message, index) => {
|
87
|
+
return (
|
88
|
+
<div key={index}>
|
89
|
+
<Message message={message} sender={conversation}/>
|
90
|
+
</div>
|
91
|
+
);
|
92
|
+
});
|
93
|
+
} else {
|
94
|
+
messages.map((message, index) => {
|
95
|
+
return (
|
96
|
+
<div key={index}>
|
97
|
+
<Message message={message} sender={conversation}/>
|
98
|
+
</div>
|
99
|
+
);
|
100
|
+
});
|
101
|
+
}
|
102
|
+
}
|
103
|
+
}
|
104
|
+
<MessageForm onSubmit={this.handleSubmit}/>
|
105
|
+
</div>
|
106
|
+
</div>
|
107
|
+
</div>
|
108
|
+
);
|
109
|
+
}
|
110
|
+
}
|
@@ -0,0 +1,47 @@
|
|
1
|
+
import React, { Component } from 'react';
|
2
|
+
import store from '../store/Store';
|
3
|
+
import { connect } from 'react-redux';
|
4
|
+
import { actions } from '../actions/Index';
|
5
|
+
import Messages from '../components/Messages';
|
6
|
+
import ChatUtils from '../utils/ChatUtils';
|
7
|
+
|
8
|
+
@connect((state) => {
|
9
|
+
return {
|
10
|
+
messages: state.messages,
|
11
|
+
conversation: state.conversation,
|
12
|
+
}
|
13
|
+
})
|
14
|
+
|
15
|
+
export default class MessagesContainer extends Component {
|
16
|
+
constructor(props) {
|
17
|
+
super(props);
|
18
|
+
}
|
19
|
+
|
20
|
+
componentDidMount() {
|
21
|
+
let room = document.getElementById('denshobato-message-panel');
|
22
|
+
store.dispatch(actions.messages.fetch(room.dataset.room));
|
23
|
+
};
|
24
|
+
|
25
|
+
componentWillReceiveProps(nextProps) {
|
26
|
+
if (nextProps.messages.length != this.props.messages.messages.length) {
|
27
|
+
ChatUtils.scrollChat();
|
28
|
+
}
|
29
|
+
}
|
30
|
+
|
31
|
+
render() {
|
32
|
+
const { messages, conversation } = this.props;
|
33
|
+
return (
|
34
|
+
<div>
|
35
|
+
{do {
|
36
|
+
if (!messages.loaded) {
|
37
|
+
<div className="loading">
|
38
|
+
<p>LOADING MESSAGES...</p>
|
39
|
+
</div>;
|
40
|
+
} else {
|
41
|
+
<Messages messages={messages.messages} conversation={conversation} showAll={messages.showAll}/>;
|
42
|
+
}
|
43
|
+
}}
|
44
|
+
</div>
|
45
|
+
);
|
46
|
+
}
|
47
|
+
}
|
@@ -0,0 +1,18 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { render } from 'react-dom';
|
3
|
+
import { Provider, connect } from 'react-redux';
|
4
|
+
import MessagesContainer from './containers/MessagesContainer';
|
5
|
+
import store from './store/Store';
|
6
|
+
|
7
|
+
window.onload = (() => {
|
8
|
+
const domNode = document.getElementById('denshobato-message-panel');
|
9
|
+
|
10
|
+
if (domNode != null) {
|
11
|
+
render(
|
12
|
+
<Provider store={store}>
|
13
|
+
<MessagesContainer/>
|
14
|
+
</Provider>,
|
15
|
+
domNode
|
16
|
+
);
|
17
|
+
}
|
18
|
+
});
|
@@ -0,0 +1,20 @@
|
|
1
|
+
import { CONVERSATION } from '../actions/Conversation';
|
2
|
+
|
3
|
+
const conversationState = {
|
4
|
+
author: null,
|
5
|
+
conversationId: null,
|
6
|
+
senderId: null,
|
7
|
+
senderClass: null,
|
8
|
+
recipient: null,
|
9
|
+
recipientClass: null,
|
10
|
+
};
|
11
|
+
|
12
|
+
export function conversation(state = conversationState, action) {
|
13
|
+
switch (action.type) {
|
14
|
+
case CONVERSATION:
|
15
|
+
let data = action.response;
|
16
|
+
return { ...state, conversationId: data.conversation_id, author: data.author, senderId: data.sender_id, senderClass: data.sender_class, recipient: data.recipient, recipientClass: data.recipient_class };
|
17
|
+
default:
|
18
|
+
return state;
|
19
|
+
}
|
20
|
+
}
|
@@ -0,0 +1,8 @@
|
|
1
|
+
import { messages } from './Messages';
|
2
|
+
import { conversation } from './Conversation';
|
3
|
+
import { combineReducers } from 'redux';
|
4
|
+
import { reducer as formReducer } from 'redux-form';
|
5
|
+
|
6
|
+
const Reducer = combineReducers({ messages: messages, conversation: conversation, form: formReducer });
|
7
|
+
|
8
|
+
export default Reducer;
|
@@ -0,0 +1,21 @@
|
|
1
|
+
import { FETCH, CREATE, DELETE, SHOW_ALL } from '../actions/Messages';
|
2
|
+
|
3
|
+
const messagesState = { messages: [], loaded: false, showAll: false };
|
4
|
+
|
5
|
+
export function messages(state = messagesState, action) {
|
6
|
+
switch (action.type) {
|
7
|
+
case FETCH:
|
8
|
+
return { ...state, messages: action.data, loaded: true };
|
9
|
+
case CREATE:
|
10
|
+
let newState = state.messages.concat([action.message]);
|
11
|
+
return { ...state, messages: newState };
|
12
|
+
case DELETE:
|
13
|
+
let index = state.messages.map((x) => x.id).indexOf(action.id);
|
14
|
+
state.messages.splice(index, 1);
|
15
|
+
return { ...state, messages: state.messages };
|
16
|
+
case SHOW_ALL:
|
17
|
+
return { ...state, showAll: action.data };
|
18
|
+
default:
|
19
|
+
return state;
|
20
|
+
}
|
21
|
+
}
|
@@ -0,0 +1,8 @@
|
|
1
|
+
import { createStore, applyMiddleware } from 'redux';
|
2
|
+
import thunk from 'redux-thunk';
|
3
|
+
import Reducer from '../reducers/Index';
|
4
|
+
|
5
|
+
const createStoreWithMiddleware = applyMiddleware(thunk)(createStore);
|
6
|
+
const store = createStoreWithMiddleware(Reducer);
|
7
|
+
|
8
|
+
export default store;
|
@@ -0,0 +1,12 @@
|
|
1
|
+
export default class ChatUtils {
|
2
|
+
static scrollChat() {
|
3
|
+
let messages = document.getElementsByClassName('chat-wrapper')[0];
|
4
|
+
if (messages != null) {
|
5
|
+
$(messages).animate({ scrollTop: messages.scrollWidth * 999 });
|
6
|
+
};
|
7
|
+
};
|
8
|
+
|
9
|
+
static closeChat () {
|
10
|
+
$('.chat-message').slideToggle();
|
11
|
+
};
|
12
|
+
};
|
data/package.json
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
{
|
2
|
+
"name": "Denshobato",
|
3
|
+
"version": "0.1.0",
|
4
|
+
"description": "Denshobato messaging panel",
|
5
|
+
"main": "denshobato.js",
|
6
|
+
"scripts": {
|
7
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
8
|
+
},
|
9
|
+
"author": "Eugene Domosedov (ID25)",
|
10
|
+
"license": "MIT",
|
11
|
+
"dependencies": {
|
12
|
+
"axios": "^0.8.1",
|
13
|
+
"react": "^0.14.3",
|
14
|
+
"react-dom": "0.14.0",
|
15
|
+
"react-redux": "^4.0.6",
|
16
|
+
"redux": "^3.0.4",
|
17
|
+
"redux-form": "^4.1.1",
|
18
|
+
"redux-thunk": "^0.1.0"
|
19
|
+
},
|
20
|
+
"devDependencies": {
|
21
|
+
"babel-core": "latest",
|
22
|
+
"babel-loader": "latest",
|
23
|
+
"babel-plugin-transform-decorators-legacy": "^1.3.4",
|
24
|
+
"babel-preset-es2015": "latest",
|
25
|
+
"babel-preset-react": "latest",
|
26
|
+
"babel-preset-stage-0": "latest",
|
27
|
+
"babel-preset-stage-1": "latest",
|
28
|
+
"babel-preset-stage-2": "latest",
|
29
|
+
"babel-preset-stage-3": "latest",
|
30
|
+
"redux-devtools": "^3.0.1",
|
31
|
+
"redux-devtools-dock-monitor": "^1.0.1",
|
32
|
+
"redux-devtools-log-monitor": "^1.0.1",
|
33
|
+
"webpack": "^1.12.9"
|
34
|
+
}
|
35
|
+
}
|
data/webpack.config.js
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
var path = require('path');
|
2
|
+
var webpack = require('webpack');
|
3
|
+
|
4
|
+
module.exports = {
|
5
|
+
entry: './lib/react/denshobato.js',
|
6
|
+
output: { path: __dirname + '/app/assets/javascripts/', filename: 'denshobato.js' },
|
7
|
+
resolve: { extensions: ['', '.js', '.jsx'] },
|
8
|
+
module: {
|
9
|
+
loaders: [
|
10
|
+
{
|
11
|
+
test: /.jsx?$/,
|
12
|
+
loader: 'babel-loader',
|
13
|
+
exclude: /node_modules/,
|
14
|
+
query: {
|
15
|
+
plugins: ['transform-decorators-legacy'],
|
16
|
+
presets: ['es2015', 'react', 'stage-0', 'stage-1', 'stage-2', 'stage-3'],
|
17
|
+
},
|
18
|
+
},
|
19
|
+
],
|
20
|
+
},
|
21
|
+
};
|
metadata
ADDED
@@ -0,0 +1,163 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: denshobato_chat_panel
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- ID25
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-03-11 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: grape
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.11'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.11'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '10.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '10.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: activerecord
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: sqlite3
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
description: Chat Panel for Denshobato messaging.
|
98
|
+
email:
|
99
|
+
- xid25x@gmail.com
|
100
|
+
executables: []
|
101
|
+
extensions: []
|
102
|
+
extra_rdoc_files: []
|
103
|
+
files:
|
104
|
+
- ".gitignore"
|
105
|
+
- ".rspec"
|
106
|
+
- ".travis.yml"
|
107
|
+
- Gemfile
|
108
|
+
- README.md
|
109
|
+
- Rakefile
|
110
|
+
- bin/console
|
111
|
+
- bin/setup
|
112
|
+
- denshobato_chat_panel.gemspec
|
113
|
+
- lib/api/conversation_api.rb
|
114
|
+
- lib/api/denshobato_api.rb
|
115
|
+
- lib/api/message_api.rb
|
116
|
+
- lib/denshobato_chat_panel.rb
|
117
|
+
- lib/denshobato_chat_panel/engine.rb
|
118
|
+
- lib/denshobato_chat_panel/react_helper.rb
|
119
|
+
- lib/denshobato_chat_panel/version.rb
|
120
|
+
- lib/generators/denshobato_chat_panel/assets/javascripts/denshobato.js
|
121
|
+
- lib/generators/denshobato_chat_panel/assets/stylesheets/denshobato.scss
|
122
|
+
- lib/generators/denshobato_chat_panel/install_generator.rb
|
123
|
+
- lib/react/actions/Conversation.jsx
|
124
|
+
- lib/react/actions/Index.jsx
|
125
|
+
- lib/react/actions/Messages.jsx
|
126
|
+
- lib/react/api/Api.jsx
|
127
|
+
- lib/react/components/Message.jsx
|
128
|
+
- lib/react/components/MessageForm.jsx
|
129
|
+
- lib/react/components/Messages.jsx
|
130
|
+
- lib/react/containers/MessagesContainer.jsx
|
131
|
+
- lib/react/denshobato.js
|
132
|
+
- lib/react/reducers/Conversation.jsx
|
133
|
+
- lib/react/reducers/Index.jsx
|
134
|
+
- lib/react/reducers/Messages.jsx
|
135
|
+
- lib/react/store/Store.jsx
|
136
|
+
- lib/react/utils/ChatUtils.js
|
137
|
+
- package.json
|
138
|
+
- webpack.config.js
|
139
|
+
homepage: https://github.com/ID25/denshobato_chat_panel
|
140
|
+
licenses:
|
141
|
+
- MIT
|
142
|
+
metadata: {}
|
143
|
+
post_install_message:
|
144
|
+
rdoc_options: []
|
145
|
+
require_paths:
|
146
|
+
- lib
|
147
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
148
|
+
requirements:
|
149
|
+
- - ">="
|
150
|
+
- !ruby/object:Gem::Version
|
151
|
+
version: '0'
|
152
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
153
|
+
requirements:
|
154
|
+
- - ">="
|
155
|
+
- !ruby/object:Gem::Version
|
156
|
+
version: '0'
|
157
|
+
requirements: []
|
158
|
+
rubyforge_project:
|
159
|
+
rubygems_version: 2.5.0
|
160
|
+
signing_key:
|
161
|
+
specification_version: 4
|
162
|
+
summary: Chat Panel for Denshobato messaging.
|
163
|
+
test_files: []
|