Skip to content

Commit 278a492

Browse files
committed
fix(notices): missing create notice option
1 parent e506cc4 commit 278a492

File tree

15 files changed

+242
-611
lines changed

15 files changed

+242
-611
lines changed

src/client/actions/notices.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@ import { createAction } from 'redux-actions'
22
import { FETCH_NOTICES, CREATE_NOTICE, UPDATE_NOTICE, DELETE_NOTICE, UNLOAD_NOTICES } from 'actions/types'
33

44
export const fetchNotices = createAction(FETCH_NOTICES.ACTION)
5-
export const createNotice = createAction(CREATE_NOTICE.ACTION)
5+
export const createNotice = createAction(
6+
CREATE_NOTICE.ACTION,
7+
payload => payload,
8+
() => ({ thunk: true })
9+
)
610
export const updateNotice = createAction(UPDATE_NOTICE.ACTION)
711
export const unloadNotices = createAction(
812
UNLOAD_NOTICES.ACTION,

src/client/api/index.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,12 @@ api.departments.delete = ({ _id }) => {
251251
}
252252

253253
api.notices = {}
254+
api.notices.create = payload => {
255+
return axios.post('/api/v2/notices', payload).then(res => {
256+
return res.data
257+
})
258+
}
259+
254260
api.notices.get = () => {
255261
return axios.get('/api/v2/notices').then(res => {
256262
return res.data
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
import React from 'react'
2+
import PropTypes from 'prop-types'
3+
import { connect } from 'react-redux'
4+
import { PopoverColorPicker } from 'components/PopoverColorPicker'
5+
import Button from 'components/Button'
6+
import BaseModal from 'containers/Modals/BaseModal'
7+
import { observer } from 'mobx-react'
8+
import { makeObservable, observable } from 'mobx'
9+
10+
import { createNotice } from 'actions/notices'
11+
12+
import helpers from 'lib/helpers'
13+
import $ from 'jquery'
14+
15+
@observer
16+
class CreateNoticeModal extends React.Component {
17+
constructor (props) {
18+
super(props)
19+
20+
makeObservable(this)
21+
}
22+
23+
@observable name = ''
24+
@observable message = ''
25+
@observable color = ''
26+
@observable fontColor = ''
27+
28+
componentDidMount () {
29+
this.color = '#4CAF50'
30+
this.fontColor = '#ffffff'
31+
32+
helpers.UI.inputs()
33+
helpers.UI.reRenderInputs()
34+
helpers.formvalidator()
35+
}
36+
37+
componentDidUpdate (prevProps, prevState, snapshot) {
38+
helpers.UI.reRenderInputs()
39+
}
40+
41+
onInputChange (target, e) {
42+
this[target] = e.target.value
43+
}
44+
45+
onFormSubmit (e) {
46+
e.preventDefault()
47+
const $form = $(e.target)
48+
if (!$form.isValid(null, null, false)) return false
49+
50+
const payload = {
51+
name: this.name,
52+
message: this.message,
53+
color: this.color,
54+
fontColor: this.fontColor
55+
}
56+
57+
this.props.createNotice(payload).then(() => {
58+
helpers.resizeAll()
59+
})
60+
}
61+
62+
render () {
63+
return (
64+
<BaseModal {...this.props} options={{ bgclose: false }}>
65+
<div className={'mb-25'}>
66+
<h2>Create Notice</h2>
67+
</div>
68+
<form className={'uk-form-stacked'} onSubmit={e => this.onFormSubmit(e)}>
69+
<div className={'uk-margin-medium-bottom'}>
70+
<label>Name</label>
71+
<input
72+
type='text'
73+
className={'md-input'}
74+
value={this.name}
75+
onChange={e => this.onInputChange('name', e)}
76+
data-validation='length'
77+
data-validation-length={'min2'}
78+
data-validation-error-msg={'Please enter a notice name. (Must contain 2 characters)'}
79+
/>
80+
</div>
81+
<div className={'uk-margin-medium-bottom'}>
82+
<label>Message</label>
83+
<textarea
84+
className={'md-input'}
85+
value={this.message}
86+
onChange={e => this.onInputChange('message', e)}
87+
data-validation='length'
88+
data-validation-length={'min10'}
89+
data-validation-error-msg={'Please enter a notice message. (Must contain 10 characters)'}
90+
/>
91+
</div>
92+
<div>
93+
<span style={{ display: 'inline-block', float: 'left', paddingTop: 5 }}>Background Color</span>
94+
<PopoverColorPicker
95+
color={this.color}
96+
onChange={c => {
97+
this.color = c
98+
}}
99+
style={{ float: 'left', marginLeft: 5, marginRight: 15 }}
100+
/>
101+
<span style={{ display: 'inline-block', float: 'left', paddingTop: 5 }}>Font Color</span>
102+
<PopoverColorPicker
103+
color={this.fontColor}
104+
onChange={c => {
105+
this.fontColor = c
106+
}}
107+
style={{ float: 'left', marginLeft: 5 }}
108+
/>
109+
</div>
110+
111+
<div className='uk-modal-footer uk-text-right'>
112+
<Button text={'Close'} flat={true} waves={true} extraClass={'uk-modal-close'} />
113+
<Button text={'Create Notice'} flat={true} waves={true} style={'primary'} type={'submit'} />
114+
</div>
115+
</form>
116+
</BaseModal>
117+
)
118+
}
119+
}
120+
121+
CreateNoticeModal.propTypes = {
122+
createNotice: PropTypes.func.isRequired
123+
}
124+
125+
const mapStateToProps = state => ({})
126+
127+
export default connect(mapStateToProps, { createNotice })(CreateNoticeModal)

src/client/containers/Modals/index.jsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import CreateTeamModal from './CreateTeamModal'
3838
import EditTeamModal from './EditTeamModal'
3939
import CreateDepartmentModal from './CreateDepartmentModal'
4040
import EditDepartmentModal from './EditDepartmentModal'
41+
import CreateNoticeModal from 'containers/Modals/CreateNoticeModal'
4142
import EditNoticeModal from 'containers/Modals/EditNoticeModal'
4243
import LinkWarningModal from 'containers/Modals/LinkWarningModal'
4344

@@ -63,6 +64,7 @@ const MODAL_COMPONENTS = {
6364
EDIT_TEAM: EditTeamModal,
6465
CREATE_DEPARTMENT: CreateDepartmentModal,
6566
EDIT_DEPARTMENT: EditDepartmentModal,
67+
CREATE_NOTICE: CreateNoticeModal,
6668
EDIT_NOTICE: EditNoticeModal,
6769
LINK_WARNING: LinkWarningModal
6870
}

src/client/containers/Notice/NoticeContainer.jsx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ class NoticeContainer extends React.Component {
2929
this.props.fetchNotices()
3030
}
3131

32+
componentDidUpdate () {
33+
helpers.resizeAll()
34+
}
35+
3236
componentWillUnmount () {
3337
this.props.unloadNotices()
3438
}
@@ -145,6 +149,18 @@ class NoticeContainer extends React.Component {
145149
onClick={() => this.onDeactivateNotice()}
146150
/>
147151
)}
152+
{helpers.canUser('notices:create') && (
153+
<Button
154+
text={'Create'}
155+
flat={false}
156+
small={true}
157+
waves={false}
158+
extraClass={'hover-success'}
159+
onClick={() => {
160+
this.props.showModal('CREATE_NOTICE')
161+
}}
162+
/>
163+
)}
148164
</div>
149165
</div>
150166
}

src/client/reducers/noticesReducer.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { fromJS, List } from 'immutable'
22
import { handleActions } from 'redux-actions'
3-
import { FETCH_NOTICES, UPDATE_NOTICE, DELETE_NOTICE, UNLOAD_NOTICES } from 'actions/types'
3+
import { FETCH_NOTICES, UPDATE_NOTICE, DELETE_NOTICE, UNLOAD_NOTICES, CREATE_NOTICE } from 'actions/types'
44

55
const initialState = {
66
notices: List([]),
@@ -24,6 +24,15 @@ const reducer = handleActions(
2424
}
2525
},
2626

27+
[CREATE_NOTICE.SUCCESS]: (state, action) => {
28+
const notice = action.response.notice
29+
30+
return {
31+
...state,
32+
notices: state.notices.push(fromJS(notice))
33+
}
34+
},
35+
2736
[UPDATE_NOTICE.SUCCESS]: (state, action) => {
2837
const notice = action.response.notice
2938
const idx = state.notices.findIndex(n => {

src/client/sagas/notices/index.js

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
*/
1414

1515
import { call, put, takeLatest } from 'redux-saga/effects'
16-
import { FETCH_NOTICES, UPDATE_NOTICE, DELETE_NOTICE, UNLOAD_NOTICES, HIDE_MODAL } from 'actions/types'
16+
import { FETCH_NOTICES, UPDATE_NOTICE, DELETE_NOTICE, UNLOAD_NOTICES, HIDE_MODAL, CREATE_NOTICE } from 'actions/types'
1717

1818
import api from '../../api'
1919
import Log from '../../logger'
@@ -31,6 +31,23 @@ function * fetchNotices ({ payload }) {
3131
}
3232
}
3333

34+
function * createNotice ({ payload, meta }) {
35+
try {
36+
const response = yield call(api.notices.create, payload)
37+
yield put({ type: CREATE_NOTICE.SUCCESS, response, meta })
38+
yield put({ type: HIDE_MODAL.ACTION })
39+
helpers.UI.showSnackbar('Notice Created')
40+
} catch (error) {
41+
const errorText = error.response ? error.response.data.error : error
42+
if (error.response && error.response.status !== (401 || 403)) {
43+
Log.error(errorText, error)
44+
helpers.UI.showSnackbar(`Error: ${errorText}`, true)
45+
}
46+
47+
yield put({ type: CREATE_NOTICE.ERROR, error })
48+
}
49+
}
50+
3451
function * updateNotice ({ payload }) {
3552
try {
3653
const response = yield call(api.notices.update, payload)
@@ -71,6 +88,7 @@ function * unloadThunk ({ payload, meta }) {
7188
}
7289

7390
export default function * watch () {
91+
yield takeLatest(CREATE_NOTICE.ACTION, createNotice)
7492
yield takeLatest(FETCH_NOTICES.ACTION, fetchNotices)
7593
yield takeLatest(UPDATE_NOTICE.ACTION, updateNotice)
7694
yield takeLatest(DELETE_NOTICE.ACTION, deleteNotice)

src/controllers/api/v2/notices.js

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,29 @@
1212
* Copyright (c) 2014-2022. All rights reserved.
1313
*/
1414

15-
var apiUtils = require('../apiUtils')
16-
var Notice = require('../../../models/notice')
15+
const winston = require('../../../logger')
16+
const apiUtils = require('../apiUtils')
17+
const Notice = require('../../../models/notice')
1718

18-
var apiNotices = {}
19+
const apiNotices = {}
20+
21+
apiNotices.create = async (req, res) => {
22+
const payload = req.body
23+
24+
try {
25+
const notice = await Notice.create({
26+
name: payload.name,
27+
message: payload.message,
28+
color: payload.color,
29+
fontColor: payload.fontColor
30+
})
31+
32+
return apiUtils.sendApiSuccess(res, { notice })
33+
} catch (err) {
34+
winston.debug(err)
35+
return apiUtils.sendApiError(res, 500, err.message)
36+
}
37+
}
1938

2039
apiNotices.get = function (req, res) {
2140
Notice.find({}, function (err, notices) {

src/controllers/api/v2/routes.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ module.exports = function (middleware, router, controllers) {
6464

6565
// Notices
6666
router.get('/api/v2/notices', apiv2Auth, apiv2.notices.get)
67+
router.post('/api/v2/notices', apiv2Auth, canUser('notices:create'), apiv2.notices.create)
6768
// router.get('/api/v2/notices/active', apiv2Auth, apiv2.notices.getActive)
6869
router.put('/api/v2/notices/:id', apiv2Auth, canUser('notices:update'), apiv2.notices.update)
6970
router.put('/api/v2/notices/:id/activate', apiv2Auth, canUser('notices:activate'), apiv2.notices.activate)

0 commit comments

Comments
 (0)