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.
@@ -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: []