Skip to content

Instantly share code, notes, and snippets.

@evturn
Last active June 29, 2016 16:30
Show Gist options
  • Save evturn/fc6c8fe463b2304e11cbbd428fbaa3e1 to your computer and use it in GitHub Desktop.
Save evturn/fc6c8fe463b2304e11cbbd428fbaa3e1 to your computer and use it in GitHub Desktop.
Observables & Slack's slash commands
const React, { Component } from 'react'
const { render } from 'react-dom'
const { Observable } from 'rxjs'
const db = {}
class Backpack extends Component {
constructor(props) {
super(props)
this.state = {
last: false,
messages: props.messages,
db: {}
}
}
getIncomingMessage(text) {
return {
user: 'ev',
text,
color: 'red',
channel: this.props.channel
}
}
createMultipartReply(messages) {
return messages.map(text => {
return {
user: 'backpack',
color: 'blue',
channel: this.props.channel,
text,
}
})
}
saveInput(userMessage) {
const content = userMessage.text.substr(10, userMessage.text.length)
if (!db[userMessage.user]) {
db[userMessage.user] = []
}
db[userMessage.user].push({
item: content
})
this.setState({ db })
return [userMessage].concat(this.createMultipartReply([
`I got that stored`,
`Here it is:`,
content,
`Options available:`,
`[Add tags] [Copy to clipboard]`
]))
}
parseText(userMessage) {
return Observable.of(userMessage.text)
.map(x => {
return x.startsWith('/backpack')
? this.saveInput(userMessage)
: [userMessage]
})
}
inputChanged(e) {
Observable.of(e)
.filter(e => e.charCode === 13)
.filter(e => e !== '')
.map(e => e.target.value)
.map(x => this.getIncomingMessage(x))
.flatMap(userMessage => this.parseText(userMessage))
.map(x => {
this.setState({
messages: this.state.messages.concat(x),
last: x[0]
})
this.input.value = ''
return x[0]
})
.subscribe(
x => console.log(x),
e => console.log(e.message)
)
}
showSavedItems() {
this.setState({
messages: this.state.messages.concat(this.createMultipartReply(
['This is what I have stored:'].concat(this.state.db['ev'].map(x => x.item))
))
})
}
render() {
return (
<div>
<button onClick={_ => this.showSavedItems()}>Show saved</button>
<div style={channel}>
{this.props.channel}
</div>
<div style={promptCSS}>
{this.state.messages.map((x, i) => (
<div key={i}>
<span style={x}>{x.user}</span>: {x.text}
</div>
))}
</div>
<div style={{textAlign: 'center'}}>
<input
style={inputCSS}
type="text"
onKeyPress={e => this.inputChanged(e)}
ref={x => this.input = x}
/>
</div>
</div>
)
}
}
const promptCSS = {
fontSize: '22px',
fontFamily: 'Helvetica Neue',
fontWeight: 300,
height: '150px',
padding: '20px',
}
const inputCSS = {
position: 'absolute',
bottom: '70px',
left: 0,
right: 0,
height: '50px',
width: '100%',
fontSize: '20px',
fontFamily: 'Helvetica Neue',
fontWeight: 300
}
const channel = {
textAlign: 'center',
fontFamily: 'Helvetica Neue',
fontWeight: 300,
fontSize: '16px',
marginBottom: '15px',
}
render(
<Backpack
channel={'#coolguys'}
messages={[
{ user: 'ev', color: 'red', text: 'so yeah'},
{ user: 'kanye', color: 'hotpink', text: 'kinda scared for my life'},
{ user: 'kanye', color: 'hotpink', text: 'like is it really vegetarian?'},
{ user: 'ev', color: 'red', text: 'no one cares'}
]}
/>,
document.getElementById('app')
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment