Skip to content

Commit

Permalink
fix(tickets): customized status enhancements and fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
polonel committed Jun 22, 2023
1 parent 073a308 commit ece5b34
Show file tree
Hide file tree
Showing 30 changed files with 491 additions and 230 deletions.
43 changes: 27 additions & 16 deletions public/js/5.js

Large diffs are not rendered by default.

Binary file modified public/js/5.js.gz
Binary file not shown.
7 changes: 4 additions & 3 deletions src/backup/backup.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,10 @@ const pkg = require('../../package.json')
global.env = process.env.NODE_ENV || 'production'

let CONNECTION_URI = null
let FILENAME = null

function createZip (callback) {
const filename = 'trudesk-v' + pkg.version + '-' + moment().format('MMDDYYYY_HHmm') + '.zip'
const filename = FILENAME
const output = fs.createWriteStream(path.join(__dirname, '../../backups/', filename))
const archive = archiver('zip', {
zlib: { level: 9 }
Expand Down Expand Up @@ -124,6 +125,7 @@ function runBackup (callback) {

;(function () {
CONNECTION_URI = process.env.MONGOURI
FILENAME = process.env.FILENAME || 'trudesk-v' + pkg.version + '-' + moment().format('MMDDYYYY_HHmm') + '.zip'

if (!CONNECTION_URI) return process.send({ error: { message: 'Invalid connection uri' } })
const options = {
Expand Down Expand Up @@ -151,9 +153,8 @@ function runBackup (callback) {

runBackup(function (err) {
if (err) return process.send({ success: false, error: err })
const filename = 'trudesk-' + moment().format('MMDDYYYY_HHmm') + '.zip'

winston.info('Backup completed successfully: ' + filename)
winston.info('Backup completed successfully: ' + FILENAME)
process.send({ success: true })
})
})
Expand Down
4 changes: 2 additions & 2 deletions src/client/actions/tickets.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,10 @@ export const updateStatus = createAction(UPDATE_STATUS.ACTION, ({ id, name, html
}))

export const deletePriority = createAction(DELETE_PRIORITY.ACTION, ({ id, newPriority }) => ({ id, newPriority }))
export const deleteStatus = createAction(DELETE_STATUS.ACTION, (id) => ({ id }))
export const deleteStatus = createAction(DELETE_STATUS.ACTION, ({ id, newStatusId }) => ({ id, newStatusId }))
export const getTagsWithPage = createAction(GET_TAGS_WITH_PAGE.ACTION, ({ limit, page }) => ({ limit, page }))
export const tagsUpdateCurrentPage = createAction(TAGS_UPDATE_CURRENT_PAGE.ACTION, currentPage => ({ currentPage }))
export const createTag = createAction(CREATE_TAG.ACTION, ({ name, currentPage }) => ({ name, currentPage }))
export const transferToThirdParty = createAction(TRANSFER_TO_THIRDPARTY.ACTION, ({ uid }) => ({ uid }))
export const fetchTicketTypes = createAction(FETCH_TICKET_TYPES.ACTION)
export const fetchTicketStatus = createAction(FETCH_STATUS.ACTION)
export const fetchTicketStatus = createAction(FETCH_STATUS.ACTION)
4 changes: 2 additions & 2 deletions src/client/api/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,8 +167,8 @@ api.tickets.getStatus = () => {
})
}

api.tickets.deleteStatus = ({ id }) => {
return axios.post(`/api/v1/tickets/status/${id}/delete`, {}).then(res => {
api.tickets.deleteStatus = ({ id, newStatusId }) => {
return axios.post(`/api/v1/tickets/status/${id}/delete`, { newStatusId }).then(res => {
return res.data
})
}
Expand Down
25 changes: 0 additions & 25 deletions src/client/components/Nav/Sidebar/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -128,31 +128,6 @@ class Sidebar extends React.Component {
href='/tickets/unassigned'
active={activeSubItem === 'tickets-unassigned'}
/>
<NavSeparator />
<SubmenuItem
text='New'
icon='&#xE24D;'
href='/tickets/new'
active={activeSubItem === 'tickets-new'}
/>
<SubmenuItem
text='Pending'
icon='&#xE629;'
href='/tickets/pending'
active={activeSubItem === 'tickets-pending'}
/>
<SubmenuItem
text='Open'
icon='&#xE2C8;'
href='/tickets/open'
active={activeSubItem === 'tickets-open'}
/>
<SubmenuItem
text='Closed'
icon='&#xE2C7;'
href='/tickets/closed'
active={activeSubItem === 'tickets-closed'}
/>
</Submenu>
</SidebarItem>
)}
Expand Down
38 changes: 25 additions & 13 deletions src/client/components/SearchResults/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,6 @@ import $ from 'jquery'
import helpers from 'lib/helpers'

class SearchResults extends React.Component {
componentDidMount () {
helpers.UI.setupDataTethers()
$(document).on('mousedown', SearchResults.documentMouseEvent)
}

componentDidUpdate () {}

componentWillUnmount () {
SearchResults.toggleAnimation(true, false)
$(document).off('mousedown', SearchResults.documentMouseEvent)
}

static documentMouseEvent (event) {
const $target = $(event.target)
const isInContainer = $target.parents('.search-results-container').length > 0
Expand Down Expand Up @@ -67,6 +55,18 @@ class SearchResults extends React.Component {
}
}

componentDidMount () {
helpers.UI.setupDataTethers()
$(document).on('mousedown', SearchResults.documentMouseEvent)
}

componentDidUpdate () {}

componentWillUnmount () {
SearchResults.toggleAnimation(true, false)
$(document).off('mousedown', SearchResults.documentMouseEvent)
}

onSearchItemClick (e) {
e.preventDefault()
SearchResults.toggleAnimation(true, false)
Expand All @@ -89,8 +89,20 @@ class SearchResults extends React.Component {
{searchResults &&
searchResults.map(item => {
const doc = item.get('_source')

return (
<li key={item.get('_id')} className={`search-results-item status-${doc.get('status')}`}>
<li key={item.get('_id')} className={`search-results-item`} style={{ position: 'relative' }}>
<span
style={{
display: 'block',
height: '100%',
width: 5,
background: doc.getIn(['status', 'htmlColor']),
position: 'absolute',
top: 0,
left: 0
}}
></span>
<a href={`/tickets/${doc.get('uid')}`} onClick={e => this.onSearchItemClick(e)}>
<span className='priority' style={{ background: `${doc.getIn(['priority', 'htmlColor'])}` }} />
<span className='uid'>{doc.get('uid')}</span>
Expand Down
34 changes: 28 additions & 6 deletions src/client/containers/Modals/CreateStatusModal.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,14 @@ import ColorSelector from 'components/ColorSelector'

import $ from 'jquery'
import helpers from 'lib/helpers'
import EnableSwitch from 'components/Settings/EnableSwitch'

@observer
class CreateStatusModal extends React.Component {
@observable name = ''
@observable htmlColor = '#29B995'
@observable slatimer = true
@observable isResolved = false
constructor (props) {
super(props)
Expand All @@ -48,13 +51,15 @@ class CreateStatusModal extends React.Component {
// Form is valid... Submit..
this.props.createStatus({
name: this.name,
htmlColor: this.htmlColor
htmlColor: this.htmlColor,
slatimer: this.slatimer,
isResolved: this.isResolved
})
}
render () {
return (
<BaseModal {...this.props} ref={i => (this.base = i)}>
<BaseModal {...this.props} large={true}>
<form className={'uk-form-stacked'} onSubmit={e => this.onCreateStatusSubmit(e)}>
<div className='uk-margin-medium-bottom uk-clearfix'>
<h2>Create Status</h2>
Expand All @@ -63,7 +68,7 @@ class CreateStatusModal extends React.Component {
<div>
<div className='uk-clearfix'>
<div className='z-box uk-grid uk-grid-collpase uk-clearfix'>
<div className='uk-width-1-3'>
<div className='uk-width-1-4'>
<label>Status Name</label>
<input
type='text'
Expand All @@ -75,15 +80,33 @@ class CreateStatusModal extends React.Component {
data-validation-error-msg='Invalid name (3+ characters)'
/>
</div>
<div className='uk-width-1-3'>
<div className='uk-width-1-4'>
<ColorSelector
hideRevert={true}
defaultColor={'#29B995'}
validationEnabled={true}
onChange={e => (this.htmlColor = e.target.value)}
/>
</div>
<div className={'uk-width-1-4'}>
<div className={'uk-float-left'}>
<EnableSwitch
stateName={'slatimer'}
label={'SLA'}
checked={this.slatimer}
onChange={e => (this.slatimer = e.target.checked)}
/>
</div>
<div className={'uk-float-left'}>
<EnableSwitch
stateName={'isResolved'}
label={'isResolved'}
checked={this.isResolved}
onChange={e => (this.isResolved = e.target.checked)}
/>
</div>
</div>
</div>
<div className='uk-modal-footer uk-text-right'>
<Button text={'Cancel'} type={'button'} extraClass={'uk-modal-close'} flat={true} waves={true} />
Expand All @@ -98,7 +121,6 @@ class CreateStatusModal extends React.Component {
}

CreateStatusModal.propTypes = {
onPriorityCreated: PropTypes.func,
createStatus: PropTypes.func.isRequired
}

Expand Down
114 changes: 114 additions & 0 deletions src/client/containers/Modals/DeleteTicketStatusModal.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/*
* . .o8 oooo
* .o8 "888 `888
* .o888oo oooo d8b oooo oooo .oooo888 .ooooo. .oooo.o 888 oooo
* 888 `888""8P `888 `888 d88' `888 d88' `88b d88( "8 888 .8P'
* 888 888 888 888 888 888 888ooo888 `"Y88b. 888888.
* 888 . 888 888 888 888 888 888 .o o. )88b 888 `88b.
* "888" d888b `V88V"V8P' `Y8bod88P" `Y8bod8P' 8""888P' o888o o888o
* ========================================================================
* Author: Chris Brame
* Updated: 6/21/23 11:59 AM
* Copyright (c) 2014-2023. All rights reserved.
*/

import React from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import { fetchTicketStatus, deleteStatus } from 'actions/tickets'
import BaseModal from './BaseModal'
import Button from 'components/Button'
import SingleSelect from 'components/SingleSelect'

import helpers from 'lib/helpers'

class DeleteTicketStatusModal extends React.Component {
constructor (props) {
super(props)
this.state = {
selectedStatus: ''
}
}

componentDidMount () {}

getTicketStatuses () {
return this.props.settings && this.props.settings.get('status') ? this.props.settings.get('status').toArray() : []
}

onSelectChanged (e) {
this.setState({
selectedStatus: e.target.value
})
}

onFormSubmit (e) {
e.preventDefault()
if (!this.state.selectedStatus) {
helpers.UI.showSnackbar('Unable to get new ticket status. Aborting...', true)
return true
}

this.props.deleteStatus({ id: this.props.status.get('_id'), newStatusId: this.state.selectedStatus })
}

render () {
const { status } = this.props
const mappedStatuses = this.getTicketStatuses()
.filter(obj => {
return status.get('name') !== obj.get('name')
})
.map(item => {
return { text: item.get('name'), value: item.get('_id') }
})
return (
<BaseModal {...this.props} options={{ bgclose: false }}>
<form className={'uk-form-stacked'} onSubmit={e => this.onFormSubmit(e)}>
<div className='uk-margin-medium-bottom uk-clearfix'>
<h2>Remove Ticket Status</h2>
<span>
Please select the ticket status you wish to reassign tickets to in order to delete this ticket status.
</span>
</div>
<div className='uk-margin-medium-bottom uk-clearfix'>
<div className='uk-float-left' style={{ width: '100%' }}>
<label className={'uk-form-label nopadding nomargin'}>Status</label>
<SingleSelect
showTextbox={false}
items={mappedStatuses}
onSelectChange={e => this.onSelectChanged(e)}
value={this.state.selectedStatus}
/>
</div>
</div>
<div className='uk-margin-medium-bottom uk-clearfix'>
<span className='uk-text-danger'>
WARNING: This will change all tickets with status <strong>{status.get('name')}</strong> to the selected
ticket status.
<br />
<strong>This is permanent!</strong>
</span>
</div>
<div className='uk-modal-footer uk-text-right'>
<Button text={'Cancel'} flat={true} waves={true} extraClass={'uk-modal-close'} />
<Button text={'Delete'} style={'danger'} flat={true} type={'submit'} />
</div>
</form>
</BaseModal>
)
}
}

DeleteTicketStatusModal.propTypes = {
status: PropTypes.object.isRequired,
settings: PropTypes.object.isRequired,
deleteStatus: PropTypes.func.isRequired,
fetchTicketStatus: PropTypes.func.isRequired
}

const mapStateToProps = state => ({
settings: state.settings.settings,
ticketStatuses: state.ticketsState.ticketStatuses
})

export default connect(mapStateToProps, { fetchTicketStatus, deleteStatus })(DeleteTicketStatusModal)
6 changes: 3 additions & 3 deletions src/client/containers/Modals/FilterTicketsModal.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,8 @@ class FilterTicketsModal extends React.Component {
}

render () {
const statuses = this.props.ticketStatuses.map(s => ({text: s.get('name'), value: s.get('uid')})).toArray()
const statuses = this.props.ticketStatuses.map(s => ({ text: s.get('name'), value: s.get('_id') })).toArray()

const tags = this.props.ticketTags
.map(t => {
return { text: t.get('name'), value: t.get('_id') }
Expand Down Expand Up @@ -229,7 +229,7 @@ const mapStateToProps = state => ({
accountsState: state.accountsState,
ticketTags: state.tagsSettings.tags,
ticketTypes: state.ticketsState.types,
ticketStatuses: state.ticketsState.ticketStatuses,
ticketStatuses: state.ticketsState.ticketStatuses
})

export default connect(mapStateToProps, {
Expand Down
4 changes: 3 additions & 1 deletion src/client/containers/Modals/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ import DeleteTicketTypeModal from './DeleteTicketTypeModal'
import FilterTicketModal from './FilterTicketsModal'
import AddPriorityToTypeModal from './AddPriorityToTypeModal'
import CreatePriorityModal from './CreatePriorityModal'
import CreateStatusModal from './CreateStatusModal'
import DeletePriorityModal from './DeletePriorityModal'
import CreateStatusModal from './CreateStatusModal'
import DeleteTicketStatusModal from './DeleteTicketStatusModal'
import CreateTagModal from './CreateTagModal'
import AddTagsModal from './AddTagsModal'
import CreateTicketModal from './CreateTicketModal'
Expand Down Expand Up @@ -55,6 +56,7 @@ const MODAL_COMPONENTS = {
CREATE_PRIORITY: CreatePriorityModal,
DELETE_PRIORITY: DeletePriorityModal,
CREATE_STATUS: CreateStatusModal,
DELETE_STATUS: DeleteTicketStatusModal,
CREATE_TAG: CreateTagModal,
ADD_TAGS_MODAL: AddTagsModal,
CREATE_ROLE: CreateRoleModal,
Expand Down
Loading

0 comments on commit ece5b34

Please sign in to comment.