mirror of
https://github.com/opensupports/opensupports.git
synced 2025-09-26 19:38:54 +02:00
720 lines
25 KiB
JavaScript
720 lines
25 KiB
JavaScript
import React from 'react';
|
|
import _ from 'lodash';
|
|
import {connect} from 'react-redux';
|
|
|
|
import AdminDataActions from 'actions/admin-data-actions';
|
|
|
|
import i18n from 'lib-app/i18n';
|
|
import API from 'lib-app/api-call';
|
|
import SessionStore from 'lib-app/session-store';
|
|
import MentionsParser from 'lib-app/mentions-parser';
|
|
import history from 'lib-app/history';
|
|
|
|
import TicketEvent from 'app-components/ticket-event';
|
|
import AreYouSure from 'app-components/are-you-sure';
|
|
import Form from 'core-components/form';
|
|
import FormField from 'core-components/form-field';
|
|
import SubmitButton from 'core-components/submit-button';
|
|
import DropDown from 'core-components/drop-down';
|
|
import Button from 'core-components/button';
|
|
import Message from 'core-components/message';
|
|
import Icon from 'core-components/icon';
|
|
import TextEditor from 'core-components/text-editor';
|
|
import InfoTooltip from 'core-components/info-tooltip';
|
|
import DepartmentDropdown from 'app-components/department-dropdown';
|
|
import TagSelector from 'core-components/tag-selector';
|
|
import Tag from 'core-components/tag';
|
|
|
|
class TicketViewer extends React.Component {
|
|
static propTypes = {
|
|
ticket: React.PropTypes.object,
|
|
onChange: React.PropTypes.func,
|
|
editable: React.PropTypes.bool,
|
|
customResponses: React.PropTypes.array,
|
|
assignmentAllowed: React.PropTypes.bool,
|
|
staffMembers: React.PropTypes.array,
|
|
staffMembersLoaded: React.PropTypes.bool,
|
|
allowAttachments: React.PropTypes.bool,
|
|
userId: React.PropTypes.number,
|
|
userStaff: React.PropTypes.bool,
|
|
userDepartments: React.PropTypes.array,
|
|
userLevel: React.PropTypes.number,
|
|
tags: React.PropTypes.array
|
|
};
|
|
|
|
static defaultProps = {
|
|
tags: [],
|
|
editable: false,
|
|
ticket: {
|
|
author: {},
|
|
department: {},
|
|
comments: [],
|
|
edited: null
|
|
}
|
|
};
|
|
|
|
state = {
|
|
loading: false,
|
|
commentValue: TextEditor.createEmpty(),
|
|
commentEdited: false,
|
|
commentPrivate: false,
|
|
edit: false,
|
|
editId: 0,
|
|
tagSelectorLoading: false,
|
|
editTitle: false,
|
|
newTitle: this.props.ticket.title,
|
|
editTitleError: false,
|
|
};
|
|
|
|
componentDidMount() {
|
|
if(!this.props.staffMembersLoaded && this.props.userStaff) {
|
|
this.props.dispatch(AdminDataActions.retrieveStaffMembers());
|
|
}
|
|
}
|
|
|
|
render() {
|
|
const ticket = this.props.ticket;
|
|
return (
|
|
<div className="ticket-viewer">
|
|
{this.state.editTitle ? this.renderEditableTitle() : this.renderTitleHeader()}
|
|
{this.props.editable ? this.renderEditableHeaders() : this.renderHeaders()}
|
|
<div className="ticket-viewer__content">
|
|
<TicketEvent
|
|
loading={this.state.loading}
|
|
type="COMMENT"
|
|
author={ticket.author}
|
|
content={this.props.userStaff ? MentionsParser.parse(ticket.content) : ticket.content}
|
|
userStaff={this.props.userStaff}
|
|
userId={this.props.userId}
|
|
date={ticket.date}
|
|
onEdit={this.onEdit.bind(this,0)}
|
|
edited={ticket.edited}
|
|
file={ticket.file}
|
|
edit={this.state.edit && this.state.editId == 0}
|
|
onToggleEdit={this.onToggleEdit.bind(this, 0)}
|
|
allowAttachments={this.props.allowAttachments}
|
|
/>
|
|
</div>
|
|
<div className="ticket-viewer__comments">
|
|
{ticket.events && ticket.events.map(this.renderTicketEvent.bind(this))}
|
|
</div>
|
|
{(!this.props.ticket.closed && (this.props.editable || !this.props.assignmentAllowed)) ? this.renderResponseField() : (this.showDeleteButton())? <Button size="medium" onClick={this.onDeleteTicketClick.bind(this)}>{i18n('DELETE_TICKET')}</Button> : null}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
renderTitleHeader() {
|
|
const {ticket, userStaff, userId} = this.props;
|
|
const {ticketNumber, title, author, editedTitle, language} = ticket;
|
|
|
|
return(
|
|
<div className="ticket-viewer__header row">
|
|
<span className="ticket-viewer__number">#{ticketNumber}</span>
|
|
<span className="ticket-viewer__title">{title}</span>
|
|
<span className="ticket-viewer__flag">
|
|
<Icon name={(language === 'en') ? 'us' : language}/>
|
|
</span>
|
|
{((author.id == userId && author.staff == userStaff) || userStaff) ? this.renderEditTitleOption() : null}
|
|
{editedTitle ? this.renderEditedTitleText() : null }
|
|
</div>
|
|
)
|
|
}
|
|
|
|
renderEditedTitleText(){
|
|
return(
|
|
<div className="ticket-viewer__edited-title-text"> {i18n('TITLE_EDITED')} </div>
|
|
)
|
|
}
|
|
|
|
renderEditTitleOption() {
|
|
return(
|
|
<span className="ticket-viewer__edit-title-icon">
|
|
<Icon name="pencil" onClick={() => this.setState({editTitle: true})} />
|
|
</span>
|
|
)
|
|
}
|
|
|
|
renderEditableTitle(){
|
|
return(
|
|
<div className="ticket-viewer__header row">
|
|
<div className="ticket-viewer__edit-title-box">
|
|
<FormField className="ticket-viewer___input-edit-title" error={this.state.editTitleError} value={this.state.newTitle} field='input' onChange={(e) => this.setState({newTitle: e.target.value })} />
|
|
</div>
|
|
<Button type='secondary' size="extra-small" onClick={this.changeTitle.bind(this)}>
|
|
{i18n('EDIT_TITLE')}
|
|
</Button>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
renderEditableHeaders() {
|
|
const ticket = this.props.ticket;
|
|
const departments = this.getDepartmentsForTransfer();
|
|
|
|
const priorities = {
|
|
'low': 0,
|
|
'medium': 1,
|
|
'high': 2
|
|
};
|
|
const priorityList = [
|
|
{content: i18n('LOW')},
|
|
{content: i18n('MEDIUM')},
|
|
{content: i18n('HIGH')}
|
|
];
|
|
|
|
return (
|
|
<div className="ticket-viewer__headers">
|
|
<div className="ticket-viewer__info-row-header row">
|
|
<div className="col-md-4">{i18n('DEPARTMENT')}</div>
|
|
<div className="col-md-4">{i18n('AUTHOR')}</div>
|
|
<div className="col-md-4">{i18n('TAGS')}</div>
|
|
</div>
|
|
<div className="ticket-viewer__info-row-values row">
|
|
<div className="col-md-4">
|
|
<DepartmentDropdown className="ticket-viewer__editable-dropdown"
|
|
departments={departments}
|
|
selectedIndex={_.findIndex(departments, {id: this.props.ticket.department.id})}
|
|
onChange={this.onDepartmentDropdownChanged.bind(this)} />
|
|
</div>
|
|
<div className="col-md-4">{ticket.author.name}</div>
|
|
<div className="col-md-4">
|
|
<TagSelector
|
|
items={this.props.tags}
|
|
values={this.props.ticket.tags}
|
|
onRemoveClick={this.removeTag.bind(this)}
|
|
onTagSelected={this.addTag.bind(this)}
|
|
loading={this.state.tagSelectorLoading}/>
|
|
</div>
|
|
</div>
|
|
<div className="ticket-viewer__info-row-header row">
|
|
<div className="col-md-4">{i18n('PRIORITY')}</div>
|
|
<div className="col-md-4">{i18n('OWNER')}</div>
|
|
<div className="col-md-4">{i18n('STATUS')}</div>
|
|
</div>
|
|
<div className="ticket-viewer__info-row-values row">
|
|
<div className="col-md-4">
|
|
<DropDown
|
|
className="ticket-viewer__editable-dropdown"
|
|
items={priorityList}
|
|
selectedIndex={priorities[ticket.priority]}
|
|
onChange={this.onPriorityDropdownChanged.bind(this)} />
|
|
</div>
|
|
<div className="col-md-4">
|
|
{this.renderAssignStaffList()}
|
|
</div>
|
|
<div className="col-md-4">
|
|
{ticket.closed ?
|
|
<Button type='secondary' size="extra-small" onClick={this.onReopenClick.bind(this)}>
|
|
{i18n('RE_OPEN')}
|
|
</Button> : i18n('OPENED')}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
renderHeaders() {
|
|
const ticket = this.props.ticket;
|
|
const priorities = {
|
|
'low': 'LOW',
|
|
'medium': 'MEDIUM',
|
|
'high': 'HIGH'
|
|
};
|
|
|
|
return (
|
|
<div className="ticket-viewer__headers">
|
|
<div className="ticket-viewer__info-row-header row">
|
|
<div className="ticket-viewer__department col-md-4">{i18n('DEPARTMENT')}</div>
|
|
<div className="ticket-viewer__author col-md-4">{i18n('AUTHOR')}</div>
|
|
<div className="ticket-viewer__date col-md-4">{i18n('TAGS')}</div>
|
|
</div>
|
|
<div className="ticket-viewer__info-row-values row">
|
|
<div className="ticket-viewer__department col-md-4">{ticket.department.name}</div>
|
|
<div className="ticket-viewer__author col-md-4">{ticket.author.name}</div>
|
|
<div className="col-md-4">{ticket.tags.length ? ticket.tags.map((tagName,index) => {
|
|
let tag = _.find(this.props.tags, {name:tagName});
|
|
return <Tag name={tag && tag.name} color={tag && tag.color} key={index} />
|
|
}) : i18n('NONE')}</div>
|
|
</div>
|
|
<div className="ticket-viewer__info-row-header row">
|
|
<div className="ticket-viewer__department col-md-4">{i18n('PRIORITY')}</div>
|
|
<div className="ticket-viewer__author col-md-4">{i18n('OWNER')}</div>
|
|
<div className="ticket-viewer__date col-md-4">{i18n('STATUS')}</div>
|
|
</div>
|
|
<div className="ticket-viewer__info-row-values row">
|
|
<div className="col-md-4">
|
|
{i18n(priorities[this.props.ticket.priority || 'low'])}
|
|
</div>
|
|
<div className="col-md-4">
|
|
{this.renderOwnerNode()}
|
|
</div>
|
|
<div className="col-md-4">
|
|
{i18n((this.props.ticket.closed) ? 'CLOSED' : 'OPENED')}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
renderOwnerNode() {
|
|
let ownerNode = null;
|
|
|
|
if (this.props.assignmentAllowed) {
|
|
ownerNode = this.renderAssignStaffList();
|
|
} else {
|
|
ownerNode = (this.props.ticket.owner) ? this.props.ticket.owner.name : i18n('NONE')
|
|
}
|
|
|
|
return ownerNode;
|
|
}
|
|
|
|
renderAssignStaffList() {
|
|
const items = this.getStaffAssignmentItems();
|
|
const ownerId = this.props.ticket.owner && this.props.ticket.owner.id;
|
|
|
|
let selectedIndex = _.findIndex(items, {id: ownerId});
|
|
selectedIndex = (selectedIndex !== -1) ? selectedIndex : 0;
|
|
|
|
return (
|
|
<DropDown
|
|
className="ticket-viewer__editable-dropdown" items={items}
|
|
selectedIndex={selectedIndex}
|
|
onChange={this.onAssignmentChange.bind(this)}
|
|
/>
|
|
);
|
|
}
|
|
|
|
renderTicketEvent(options, index) {
|
|
if (this.props.userStaff && typeof options.content === 'string') {
|
|
options.content = MentionsParser.parse(options.content);
|
|
}
|
|
return (
|
|
<TicketEvent
|
|
{...options}
|
|
author={(!_.isEmpty(options.author)) ? options.author : this.props.ticket.author}
|
|
userStaff={this.props.userStaff}
|
|
userId={this.props.userId}
|
|
onEdit={this.onEdit.bind(this, options.id)}
|
|
edit={this.state.edit && this.state.editId == options.id}
|
|
onToggleEdit={this.onToggleEdit.bind(this, options.id)}
|
|
key={index}
|
|
allowAttachments={this.props.allowAttachments}
|
|
/>
|
|
);
|
|
}
|
|
|
|
renderResponseField() {
|
|
return (
|
|
<div className="ticket-viewer__response">
|
|
<Form {...this.getCommentFormProps()}>
|
|
<div className="ticket-viewer__response-title row">{i18n('RESPOND')}</div>
|
|
<div className="row">
|
|
<div className="ticket-viewer__response-actions">
|
|
{this.renderCustomResponses()}
|
|
{this.renderPrivate()}
|
|
</div>
|
|
</div>
|
|
<div className="ticket-viewer__response-field row">
|
|
<FormField name="content" validation="TEXT_AREA" required field="textarea" fieldProps={{allowImages: this.props.allowAttachments}}/>
|
|
{(this.props.allowAttachments) ? <FormField name="file" field="file"/> : null}
|
|
<div className="ticket-viewer__response-buttons">
|
|
<SubmitButton type="secondary">{i18n('RESPOND_TICKET')}</SubmitButton>
|
|
<div>
|
|
<Button size="medium" onClick={this.onCloseTicketClick.bind(this)}>{i18n('CLOSE_TICKET')}</Button>
|
|
{(this.showDeleteButton())? <Button className="ticket-viewer__delete-button" size="medium" onClick={this.onDeleteTicketClick.bind(this)}>{i18n('DELETE_TICKET')}</Button> : null}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{(this.state.commentError) ? this.renderCommentError() : null}
|
|
</Form>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
renderCustomResponses() {
|
|
let customResponsesNode = null;
|
|
|
|
if (this.props.customResponses && this.props.editable) {
|
|
let customResponses = this.props.customResponses.map((customResponse) => {
|
|
return {
|
|
content: customResponse.name
|
|
};
|
|
});
|
|
|
|
customResponses.unshift({
|
|
content: i18n('SELECT_CUSTOM_RESPONSE')
|
|
});
|
|
|
|
customResponsesNode = (
|
|
<div className="ticket-viewer__response-custom">
|
|
<DropDown items={customResponses} size="medium" onChange={this.onCustomResponsesChanged.bind(this)}/>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return customResponsesNode;
|
|
}
|
|
|
|
renderPrivate() {
|
|
if (this.props.userStaff) {
|
|
return (
|
|
<div className="ticket-viewer__response-private">
|
|
<FormField label={i18n('PRIVATE')} name="private" field="checkbox"/>
|
|
<InfoTooltip className="ticket-viewer__response-private-info" text={i18n('PRIVATE_RESPONSE_DESCRIPTION')} />
|
|
</div>
|
|
);
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
renderCommentError() {
|
|
return (
|
|
<Message className="ticket-viewer__message" type="error">{i18n('TICKET_COMMENT_ERROR')}</Message>
|
|
);
|
|
}
|
|
|
|
getCommentFormProps() {
|
|
return {
|
|
onSubmit: this.onSubmit.bind(this),
|
|
loading: this.state.loading,
|
|
onChange: (formState) => {this.setState({
|
|
commentValue: formState.content,
|
|
commentFile: formState.file,
|
|
commentEdited: true,
|
|
commentPrivate: formState.private
|
|
})},
|
|
values: {
|
|
'content': this.state.commentValue,
|
|
'file': this.state.commentFile,
|
|
'private': this.state.commentPrivate
|
|
}
|
|
};
|
|
}
|
|
|
|
getPublicDepartments() {
|
|
return _.filter(SessionStore.getDepartments(),d => !(d.private*1));
|
|
}
|
|
|
|
onDepartmentDropdownChanged(event) {
|
|
AreYouSure.openModal(null, this.changeDepartment.bind(this, event.index));
|
|
}
|
|
|
|
onPriorityDropdownChanged(event) {
|
|
AreYouSure.openModal(null, this.changePriority.bind(this, event.index));
|
|
}
|
|
|
|
onAssignmentChange(event) {
|
|
AreYouSure.openModal(null, this.assingTo.bind(this, event.index));
|
|
}
|
|
|
|
assingTo(index) {
|
|
const id = this.getStaffAssignmentItems()[index].id;
|
|
const {ticketNumber, owner} = this.props.ticket;
|
|
|
|
let APICallPromise = new Promise(resolve => resolve());
|
|
|
|
if(owner) {
|
|
APICallPromise.then(() => API.call({
|
|
path: '/staff/un-assign-ticket',
|
|
data: { ticketNumber }
|
|
}));
|
|
}
|
|
|
|
if(id !== 0) {
|
|
APICallPromise.then(() => API.call({
|
|
path: '/staff/assign-ticket',
|
|
data: { ticketNumber, staffId: id }
|
|
}));
|
|
}
|
|
|
|
APICallPromise.then(this.onTicketModification.bind(this));
|
|
}
|
|
|
|
onReopenClick() {
|
|
AreYouSure.openModal(null, this.reopenTicket.bind(this));
|
|
}
|
|
|
|
onCloseTicketClick(event) {
|
|
event.preventDefault();
|
|
AreYouSure.openModal(null, this.closeTicket.bind(this));
|
|
}
|
|
|
|
onDeleteTicketClick(event) {
|
|
event.preventDefault();
|
|
AreYouSure.openModal(null, this.deleteTicket.bind(this));
|
|
}
|
|
|
|
changeTitle(){
|
|
API.call({
|
|
path: '/ticket/edit-title',
|
|
data: {
|
|
ticketNumber: this.props.ticket.ticketNumber,
|
|
title: this.state.newTitle
|
|
}
|
|
}).then(() => {
|
|
this.setState({
|
|
editTitle: false,
|
|
editTitleError: false
|
|
});
|
|
this.onTicketModification();
|
|
}).catch((result) => {
|
|
this.setState({
|
|
editTitleError: i18n(result.message)
|
|
})
|
|
});
|
|
}
|
|
|
|
reopenTicket() {
|
|
API.call({
|
|
path: '/ticket/re-open',
|
|
data: {
|
|
ticketNumber: this.props.ticket.ticketNumber
|
|
}
|
|
}).then(this.onTicketModification.bind(this));
|
|
}
|
|
|
|
closeTicket() {
|
|
API.call({
|
|
path: '/ticket/close',
|
|
data: {
|
|
ticketNumber: this.props.ticket.ticketNumber
|
|
}
|
|
}).then(this.onTicketModification.bind(this));
|
|
}
|
|
|
|
deleteTicket() {
|
|
API.call({
|
|
path: '/ticket/delete',
|
|
data: {
|
|
ticketNumber: this.props.ticket.ticketNumber
|
|
}
|
|
}).then((result) => {
|
|
this.onTicketModification(result);
|
|
history.push('/admin/panel/tickets/my-tickets/');
|
|
});
|
|
}
|
|
|
|
changeDepartment(index) {
|
|
API.call({
|
|
path: '/ticket/change-department',
|
|
data: {
|
|
ticketNumber: this.props.ticket.ticketNumber,
|
|
departmentId: this.getDepartmentsForTransfer()[index].id
|
|
}
|
|
}).then(this.onTicketModification.bind(this));
|
|
}
|
|
|
|
changePriority(index) {
|
|
const priorities = [
|
|
'low',
|
|
'medium',
|
|
'high'
|
|
];
|
|
|
|
API.call({
|
|
path: '/ticket/change-priority',
|
|
data: {
|
|
ticketNumber: this.props.ticket.ticketNumber,
|
|
priority: priorities[index]
|
|
}
|
|
}).then(this.onTicketModification.bind(this));
|
|
}
|
|
|
|
addTag(tag) {
|
|
this.setState({
|
|
tagSelectorLoading: true,
|
|
})
|
|
API.call({
|
|
path: '/ticket/add-tag',
|
|
data: {
|
|
ticketNumber: this.props.ticket.ticketNumber,
|
|
tagId: tag
|
|
}
|
|
})
|
|
.then(() => {
|
|
this.setState({
|
|
tagSelectorLoading: false,
|
|
});
|
|
this.onTicketModification();
|
|
})
|
|
.catch(() => this.setState({
|
|
tagSelectorLoading: false,
|
|
}))
|
|
}
|
|
|
|
removeTag(tag) {
|
|
this.setState({
|
|
tagSelectorLoading: true,
|
|
});
|
|
|
|
API.call({
|
|
path: '/ticket/remove-tag',
|
|
data: {
|
|
ticketNumber: this.props.ticket.ticketNumber,
|
|
tagId: tag
|
|
}
|
|
}).then(() => {
|
|
this.setState({
|
|
tagSelectorLoading: false,
|
|
});
|
|
|
|
this.onTicketModification();
|
|
}).catch(() => this.setState({
|
|
tagSelectorLoading: false,
|
|
}))
|
|
}
|
|
|
|
onCustomResponsesChanged({index}) {
|
|
let replaceContentWithCustomResponse = () => {
|
|
this.setState({
|
|
commentValue: TextEditor.getEditorStateFromHTML(this.props.customResponses[index-1].content || ''),
|
|
commentEdited: false
|
|
});
|
|
};
|
|
|
|
if (this.state.commentEdited && index) {
|
|
AreYouSure.openModal(null, replaceContentWithCustomResponse);
|
|
} else {
|
|
replaceContentWithCustomResponse();
|
|
}
|
|
}
|
|
|
|
onToggleEdit(ticketEventId){
|
|
this.setState({
|
|
edit: !this.state.edit,
|
|
editId: ticketEventId
|
|
})
|
|
}
|
|
|
|
onEdit(ticketeventid,{content}) {
|
|
this.setState({
|
|
loading: true
|
|
});
|
|
const data = {};
|
|
|
|
if(ticketeventid){
|
|
data.ticketEventId = ticketeventid
|
|
}else{
|
|
data.ticketNumber = this.props.ticket.ticketNumber
|
|
}
|
|
|
|
API.call({
|
|
path: '/ticket/edit-comment',
|
|
data: _.extend(
|
|
data,
|
|
TextEditor.getContentFormData(content)
|
|
)
|
|
}).then(this.onEditCommentSuccess.bind(this), this.onFailCommentFail.bind(this));
|
|
}
|
|
|
|
onEditCommentSuccess() {
|
|
this.setState({
|
|
loading: false,
|
|
commentError: false,
|
|
commentEdited: false,
|
|
edit:false
|
|
});
|
|
|
|
this.onTicketModification();
|
|
}
|
|
|
|
onFailCommentFail() {
|
|
this.setState({
|
|
loading: false,
|
|
commentError: true
|
|
});
|
|
}
|
|
|
|
onSubmit(formState) {
|
|
this.setState({
|
|
loading: true
|
|
});
|
|
|
|
API.call({
|
|
path: '/ticket/comment',
|
|
dataAsForm: true,
|
|
data: _.extend({
|
|
ticketNumber: this.props.ticket.ticketNumber
|
|
}, formState, {private: formState.private ? 1 : 0}, TextEditor.getContentFormData(formState.content))
|
|
}).then(this.onCommentSuccess.bind(this), this.onCommentFail.bind(this));
|
|
}
|
|
|
|
onCommentSuccess() {
|
|
this.setState({
|
|
loading: false,
|
|
commentValue: TextEditor.createEmpty(),
|
|
commentError: false,
|
|
commentEdited: false
|
|
});
|
|
|
|
this.onTicketModification();
|
|
}
|
|
|
|
onCommentFail() {
|
|
this.setState({
|
|
loading: false,
|
|
commentError: true
|
|
});
|
|
}
|
|
|
|
onTicketModification() {
|
|
if (this.props.onChange) {
|
|
this.props.onChange();
|
|
}
|
|
}
|
|
|
|
getStaffAssignmentItems() {
|
|
const {staffMembers, userDepartments, userId, ticket} = this.props;
|
|
const ticketDepartmentId = ticket.department.id;
|
|
let staffAssignmentItems = [
|
|
{content: 'None', id: 0}
|
|
];
|
|
|
|
if(_.any(userDepartments, {id: ticketDepartmentId})) {
|
|
staffAssignmentItems.push({content: i18n('ASSIGN_TO_ME'), id: userId});
|
|
}
|
|
|
|
staffAssignmentItems = staffAssignmentItems.concat(
|
|
_.map(
|
|
_.filter(staffMembers, ({id, departments}) => {
|
|
return (id != userId) && _.any(departments, {id: ticketDepartmentId});
|
|
}),
|
|
({id, name}) => ({content: name, id})
|
|
)
|
|
);
|
|
|
|
return staffAssignmentItems;
|
|
}
|
|
|
|
getDepartmentsForTransfer() {
|
|
return this.props.ticket.author.staff ? SessionStore.getDepartments() : this.getPublicDepartments();
|
|
}
|
|
|
|
showDeleteButton() {
|
|
if(!this.props.ticket.owner) {
|
|
if(this.props.userLevel == 3) return true;
|
|
if(this.props.userId == this.props.ticket.author.id) {
|
|
if((this.props.userStaff && this.props.ticket.author.staff) || (!this.props.userStaff && !this.props.ticket.author.staff)){
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
export default connect((store) => {
|
|
return {
|
|
userId: store.session.userId,
|
|
userStaff: store.session.staff,
|
|
userDepartments: store.session.userDepartments,
|
|
staffMembers: store.adminData.staffMembers,
|
|
staffMembersLoaded: store.adminData.staffMembersLoaded,
|
|
allowAttachments: store.config['allow-attachments'],
|
|
userSystemEnabled: store.config['user-system-enabled'],
|
|
userLevel: store.session.userLevel,
|
|
tags: store.config['tags']
|
|
};
|
|
})(TicketViewer);
|