Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions backend/api/v1/admin/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import express from 'express'

module.exports = cache => {
const router = express.Router()

router.use((req, res, next) => {
const isAdmin = req.isAuthenticated() && req.user.type === 'admin'
return next()

// prevent unauthorized access
if (isAdmin) {
return next()
}

res.status(401).send({
success: false,
error: `You have not access to execute this action`
})
})

router.use('/tags', require('./tags')(cache))

return router
}
93 changes: 93 additions & 0 deletions backend/api/v1/admin/tags.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import express from 'express'
import axios from 'axios'

const env = process.env.NODE_ENV === 'dev' ? 'dev' : 'prod'
const c = require('../../../../config/config.json')
const base_url = c[env]['base_api'] + env

const getTagsList = () =>
axios.get(`${base_url}/drip/tag/list`).then(res => res.data)

const addTag = tag =>
axios
.post(`${base_url}/drip/tag/add`, {
name: tag.tag_name,
description: ''
})
.then(res => res.data)

const getUserTags = email =>
axios
.get(`${base_url}/drip/user/tag/list?email=${email}`)
.then(res => res.data)

const addUserTag = (tag_id, email) =>
axios
.post(`${base_url}/drip/user/tag/add`, { tag_id, email })
.then(res => res.data)

const filterTags = (items, query) => {
if (query === '') {
return items
}

return items.filter(
item =>
item.tag_name.toLowerCase().indexOf(query) > -1 ||
item.descrip.toLowerCase().indexOf(query) > -1
)
}

module.exports = cache => {
const router = express.Router()

router.get('/', (req, res) => {
let { tag = '' } = req.query
tag = tag.toLowerCase()

getTagsList()
.then(data => filterTags(data, tag))
.then(data => res.send(data))
.catch(err =>
res.status(500).end({
error: true,
message: err.message
})
)
})

router.post('/', (req, res) => {
const tag = req.body
console.dir(tag)

addTag(tag)
.then(data => res.send(data))
.catch(err =>
res.status(500).end({
error: true,
message: err.message
})
)
})

router.get('/user', (req, res) => {
const { email } = req.query

getUserTags(email)
.then(data => res.send(data))
.catch(err =>
res.status(500).end({
error: true,
message: err.message
})
)
})

router.post('/user', (req, res) => {
res.send({
success: true
})
})

return router
}
2 changes: 1 addition & 1 deletion backend/api/v1/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ module.exports = cache => {
router.use('/files', require('./files')(cache))
router.use('/chat', require('./chat')(cache))

// lets map to the start of url request
router.use('/tse', require('./tse')(cache))
router.use('/jobs', require('./jobs')(cache))
router.use('/careers', require('./careers')(cache))
router.use('/admin', require('./admin')(cache))

return router
}
124 changes: 124 additions & 0 deletions shared/Forms/Common/ClearableInput.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import React, { Component } from 'react'
import styled from 'styled-components'

export default class ClearableInput extends Component {
static defaultProps = {
error: false,
placeholder: '',
immediate: true,
onBlur: () => {},
onChange: () => {}
}
state = {
value: ''
}
initRef = ref => (this.input = ref)

handleChange = e => {
const { immediate, onChange } = this.props
const value = e.target ? e.target.value : e
this.setState({ value })

if (immediate) {
onChange(value)
}
}

handleKeyDown = e => {
const { onChange } = this.props
if (e.keyCode === 13) {
onChange(this.state.value)
}
}
clear = () => {
const { onChange } = this.props
const value = ''
this.setState({ value })

onChange(value)
}
blur = () => {
this.props.onBlur(this.state.value)
}

onFocus() {
this.input.focus()
}

componentWillReceiveProps(nextProps) {
if (this.props.value !== nextProps.value) {
this.setState({ value: nextProps.value })
}
}

componentDidMount() {
if (this.props.autoFocus) {
this.props.autoFocus && this.onFocus()
}

this.state.value = this.props.value
}

isEmpty = () => this.state.value.trim() === ''

render() {
const { error, placeholder } = this.props
const { value } = this.state
return (
<Wrapper error={error}>
<Input
ref={this.initRef}
value={value}
placeholder={placeholder}
onBlur={this.blur}
onChange={this.handleChange}
onKeyDown={this.handleKeyDown}
/>
{!this.isEmpty() && <Close onClick={this.clear}>×</Close>}
</Wrapper>
)
}
}

export const Wrapper = styled.div`
width: 100%;
position: relative;
background: #fff;
border: 1px solid #d7d9d9;

border-radius: 4px;
overflow: hidden;
width: 100%;
display: flex;

${props =>
props.error &&
`
color: indianred;
`};
`

export const Input = styled.input`
flex: 1;
padding: 8px 26px 8px 16px;
border: none;
`

const Close = styled.button`
position: absolute;
right: 10px;
top: 7px;
width: 16px;
border: none;
color: #999;
text-align: center;
padding: 0px;
font-size: 18px;

text-align: center;
vertical-align: top;

&:hover {
color: #d0021b;
}
`
3 changes: 3 additions & 0 deletions shared/components/admin/AdminMenu.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ class AdminMenu extends Component {
<li>
<Link to="/admin/emails/send">Send</Link>
</li>
<li>
<Link to="/admin/emails/tag_users">Tag Users</Link>
</li>
</ul>
</div>
</div>
Expand Down
29 changes: 29 additions & 0 deletions shared/components/admin/AdminTagUsers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React, { Component, PropTypes } from 'react'
import { connect } from 'react-redux'
import AdminLayout from './AdminLayout'
import TagUsers from './TagUsers'
import { changePageTitle } from '../../Layout/Actions/LayoutActions'

class AdminTagUsers extends Component {
static getPageMeta = () => ({
title: 'Tag Users'
})

componentDidMount() {
const { title } = AdminTagUsers.getPageMeta()
this.props.dispatch(changePageTitle(title))
}

render() {
const { history } = this.props

return (
<AdminLayout history={history}>
<h3>Tag Users</h3>

<TagUsers />
</AdminLayout>
)
}
}
export default connect(state => ({}))(AdminTagUsers)
92 changes: 92 additions & 0 deletions shared/components/admin/TagUsers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import React, { Component } from 'react'
import { connect } from 'react-redux'
import styled from 'styled-components'
import UsersSearch from './tags/UsersSearch'
import TagsSelect from './tags/TagsSelect'
import {
loadUserTags,
selectTagsUser,
clearUserTags
} from '../../reducers/AdminReducer'

const Box = ({ title, children, ...rest }) => (
<BoxWrapper>
{title && <BoxTitle>{title}</BoxTitle>}
<BoxContent>{children}</BoxContent>
</BoxWrapper>
)

class TagUsers extends Component {
defaultProps = {
selectedUser: {}
}

selectUser = (user, valid) => {
this.props.dispatch(selectTagsUser(user))

if (valid) {
this.loadUserTags(user)
} else {
this.props.dispatch(clearUserTags())
}
}

loadUserTags = user => {
this.props.dispatch(loadUserTags(user))
}

update = () => alert('in dev..')

render() {
const { selectedUser, userTags } = this.props
return (
<Container>
<Heading>Manage Tags</Heading>
<Box title={'User search'}>
<UsersSearch onChange={this.selectUser} />
</Box>

<code>{JSON.stringify(userTags)}</code>
<Box title={selectedUser ? 'User tags:' : 'Please, select user'}>
{selectedUser && <TagsSelect email={selectedUser} value={userTags} />}
</Box>

<Buttons>
<UpdateButton onClick={this.update} disabled={!selectedUser}>
Update
</UpdateButton>
</Buttons>
</Container>
)
}
}

export default connect(state => ({
selectedUser: state.admin.getIn(['tags', 'user']),
userTags: state.admin.getIn(['tags', 'list'])
}))(TagUsers)

const Container = styled.section``

const Heading = styled.h4``

const BoxWrapper = styled.div`
margin-top: 2em;
`

const BoxTitle = styled.div``

const BoxContent = styled.div``

const Buttons = styled.div`
margin-top: 2em;
`

const UpdateButton = styled.button`
height: 40px;
background: #f0d943;
font-size: 16px;
color: #333333;
border: none;
border-radius: 5px;
`
Loading