display tags in frontend
This commit is contained in:
parent
fad0e8eafb
commit
5bf8ff94bc
|
@ -1,5 +1,6 @@
|
|||
import React from 'react';
|
||||
import _ from 'lodash';
|
||||
import {connect} from "react-redux";
|
||||
|
||||
import i18n from 'lib-app/i18n';
|
||||
import DateTransformer from 'lib-core/date-transformer';
|
||||
|
@ -11,6 +12,7 @@ import Button from 'core-components/button';
|
|||
import Tooltip from 'core-components/tooltip';
|
||||
import Icon from 'core-components/icon';
|
||||
import Checkbox from 'core-components/checkbox';
|
||||
import Tag from 'core-components/tag';
|
||||
|
||||
class TicketList extends React.Component {
|
||||
static propTypes = {
|
||||
|
@ -182,9 +184,16 @@ class TicketList extends React.Component {
|
|||
</Tooltip>
|
||||
),
|
||||
title: (
|
||||
<Button className="ticket-list__title-link" type="clean" route={{to: this.props.ticketPath + ticket.ticketNumber}}>
|
||||
{titleText}
|
||||
</Button>
|
||||
<div>
|
||||
<Button className="ticket-list__title-link" type="clean" route={{to: this.props.ticketPath + ticket.ticketNumber}}>
|
||||
{titleText}
|
||||
</Button>
|
||||
{ticket.tags.map((tagName,index) => {
|
||||
let tag = _.find(this.props.tags, {name:tagName});
|
||||
return <Tag size='small' name={tag && tag.name} color={tag && tag.color} key={index} />
|
||||
})}
|
||||
</div>
|
||||
|
||||
),
|
||||
priority: this.getTicketPriority(ticket.priority),
|
||||
department: ticket.department.name,
|
||||
|
@ -257,5 +266,8 @@ class TicketList extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
export default TicketList;
|
||||
export default connect((store) => {
|
||||
return {
|
||||
tags: store.config['tags']
|
||||
};
|
||||
})(TicketList);
|
|
@ -22,6 +22,8 @@ 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 = {
|
||||
|
@ -36,10 +38,12 @@ class TicketViewer extends React.Component {
|
|||
userId: React.PropTypes.number,
|
||||
userStaff: React.PropTypes.bool,
|
||||
userDepartments: React.PropTypes.array,
|
||||
userLevel: React.PropTypes.number
|
||||
userLevel: React.PropTypes.number,
|
||||
tags: React.PropTypes.array
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
tags: [],
|
||||
editable: false,
|
||||
ticket: {
|
||||
author: {},
|
||||
|
@ -63,6 +67,7 @@ class TicketViewer extends React.Component {
|
|||
|
||||
render() {
|
||||
const ticket = this.props.ticket;
|
||||
console.log('tickett',ticket)
|
||||
|
||||
return (
|
||||
<div className="ticket-viewer">
|
||||
|
@ -105,7 +110,7 @@ class TicketViewer extends React.Component {
|
|||
<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('DATE')}</div>
|
||||
<div className="col-md-4">{i18n('TAGS')}</div>
|
||||
</div>
|
||||
<div className="ticket-viewer__info-row-values row">
|
||||
<div className="col-md-4">
|
||||
|
@ -115,7 +120,7 @@ class TicketViewer extends React.Component {
|
|||
onChange={this.onDepartmentDropdownChanged.bind(this)} />
|
||||
</div>
|
||||
<div className="col-md-4">{ticket.author.name}</div>
|
||||
<div className="col-md-4">{DateTransformer.transformToString(ticket.date)}</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)}/></div>
|
||||
</div>
|
||||
<div className="ticket-viewer__info-row-header row">
|
||||
<div className="col-md-4">{i18n('PRIORITY')}</div>
|
||||
|
@ -153,12 +158,15 @@ class TicketViewer extends React.Component {
|
|||
<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('DATE')}</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="ticket-viewer__date col-md-4">{DateTransformer.transformToString(ticket.date, false)}</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>
|
||||
|
@ -412,7 +420,25 @@ class TicketViewer extends React.Component {
|
|||
}
|
||||
}).then(this.onTicketModification.bind(this));
|
||||
}
|
||||
addTag(tag) {
|
||||
API.call({
|
||||
path: '/ticket/add-tag',
|
||||
data: {
|
||||
ticketNumber: this.props.ticket.ticketNumber,
|
||||
tagId: tag
|
||||
}
|
||||
}).then(this.onTicketModification.bind(this))
|
||||
}
|
||||
|
||||
removeTag(tag) {
|
||||
API.call({
|
||||
path: '/ticket/remove-tag',
|
||||
data: {
|
||||
ticketNumber: this.props.ticket.ticketNumber,
|
||||
tagId: tag
|
||||
}
|
||||
}).then(this.onTicketModification.bind(this))
|
||||
}
|
||||
onCustomResponsesChanged({index}) {
|
||||
let replaceContentWithCustomResponse = () => {
|
||||
this.setState({
|
||||
|
@ -515,6 +541,7 @@ export default connect((store) => {
|
|||
staffMembersLoaded: store.adminData.staffMembersLoaded,
|
||||
allowAttachments: store.config['allow-attachments'],
|
||||
userSystemEnabled: store.config['user-system-enabled'],
|
||||
userLevel: store.session.userLevel
|
||||
userLevel: store.session.userLevel,
|
||||
tags: store.config['tags']
|
||||
};
|
||||
})(TicketViewer);
|
||||
|
|
|
@ -2,6 +2,7 @@ import React from 'react';
|
|||
import _ from 'lodash';
|
||||
import Icon from 'core-components/icon';
|
||||
import DropDown from 'core-components/drop-down';
|
||||
import Tag from 'core-components/tag';
|
||||
|
||||
class TagSelector extends React.Component {
|
||||
|
||||
|
@ -32,14 +33,8 @@ class TagSelector extends React.Component {
|
|||
|
||||
|
||||
renderSelectedTag(item,index) {
|
||||
return (
|
||||
<div className="tag-selector__selected-tag" style={{backgroundColor:item.color}} onClick={event => event.stopPropagation()} key={index}>
|
||||
<span className="tag-selector__selected-tag-name">{item.name}</span>
|
||||
<span onClick={this.onRemoveClick.bind(this,item.name)} className="tag-selector__selected-tag-remove" >
|
||||
<Icon name="times-circle" size="small"/>
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
return <Tag name={item.name} color={item.color} showDeleteButton onRemoveClick={this.onRemoveClick.bind(this,item.id)} key={index}/>;
|
||||
|
||||
}
|
||||
|
||||
renderTagOptions() {
|
||||
|
@ -50,24 +45,23 @@ class TagSelector extends React.Component {
|
|||
|
||||
renderTagOption(item,index) {
|
||||
return (
|
||||
<div onClick={this.onTagSelected.bind(this,item.name)} className="tag-selector__tag-option" key={index}>
|
||||
<div onClick={this.onTagSelected.bind(this,item.id)} className="tag-selector__tag-option" key={index}>
|
||||
<span className="tag-selector__tag-option-square" style={{backgroundColor:item.color}}/>
|
||||
<span className="tag-selector__tag-option-name" >{item.name}</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
onRemoveClick(tag) {
|
||||
|
||||
onRemoveClick(tagId) {
|
||||
if(this.props.onRemoveClick){
|
||||
this.props.onRemoveClick(tag);
|
||||
}
|
||||
}
|
||||
onTagSelected(tag) {
|
||||
if(this.props.onTagSelected){
|
||||
this.props.onTagSelected(tag);
|
||||
this.props.onRemoveClick(tagId);
|
||||
}
|
||||
}
|
||||
|
||||
onTagSelected(tagId) {
|
||||
if(this.props.onTagSelected){
|
||||
this.props.onTagSelected(tagId);
|
||||
}
|
||||
}
|
||||
}
|
||||
export default TagSelector;
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
cursor: text;
|
||||
background-color: white;
|
||||
border: 1px solid $grey;
|
||||
min-height: 38px;
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
|
@ -17,34 +18,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
&__selected-tags {
|
||||
border-radius: 3px;
|
||||
background-color: white;
|
||||
padding: 3px 1px;
|
||||
}
|
||||
|
||||
&__selected-tag {
|
||||
color: white;
|
||||
display: inline-block;
|
||||
border-radius: 3px;
|
||||
margin-left: 5px;
|
||||
padding: 3px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
&__selected-tag {
|
||||
cursor: default;
|
||||
|
||||
&-remove {
|
||||
cursor: pointer;
|
||||
margin-left: 10px;
|
||||
|
||||
&:hover {
|
||||
color: $light-grey;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__tag-options {
|
||||
font-size: 13px;
|
||||
color: $dark-grey;
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
import React from 'react';
|
||||
import Icon from 'core-components/icon';
|
||||
import classNames from 'classnames';
|
||||
|
||||
class Tag extends React.Component {
|
||||
|
||||
static propTypes = {
|
||||
name: React.PropTypes.string,
|
||||
color: React.PropTypes.string,
|
||||
showDeleteButton: React.PropTypes.bool,
|
||||
onRemoveClick: React.PropTypes.func,
|
||||
size: React.PropTypes.oneOf(['small','medium'])
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className={this.getClass()} style={{backgroundColor:this.props.color}} onClick={event => event.stopPropagation()} >
|
||||
<span className="tag__name">{this.props.name}</span>
|
||||
{this.props.showDeleteButton ? this.renderRemoveButton() : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
renderRemoveButton() {
|
||||
return (
|
||||
<span onClick={this.props.onRemoveClick} className="tag__remove" >
|
||||
<Icon name="times-circle" size="small"/>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
getClass() {
|
||||
let classes = {
|
||||
'tag': true,
|
||||
'tag_small': this.props.size === 'small',
|
||||
'tag_medium': this.props.size === 'medium'
|
||||
};
|
||||
|
||||
return classNames(classes);
|
||||
}
|
||||
}
|
||||
export default Tag;
|
|
@ -0,0 +1,24 @@
|
|||
@import '../scss/vars';
|
||||
|
||||
.tag{
|
||||
color: white;
|
||||
display: inline-block;
|
||||
border-radius: 3px;
|
||||
margin-left: 5px;
|
||||
padding: 3px;
|
||||
font-size: 13px;
|
||||
cursor: default;
|
||||
|
||||
&__remove {
|
||||
cursor: pointer;
|
||||
margin-left: 10px;
|
||||
|
||||
&:hover {
|
||||
color: $light-grey;
|
||||
}
|
||||
}
|
||||
|
||||
&_small {
|
||||
font-size: 11px;
|
||||
}
|
||||
}
|
|
@ -62,6 +62,8 @@ class SessionStore {
|
|||
this.setItem('allow-attachments', configs['allow-attachments']);
|
||||
this.setItem('maintenance-mode', configs['maintenance-mode']);
|
||||
this.setItem('max-size', configs['max-size']);
|
||||
this.setItem('tags', configs['tags']);
|
||||
|
||||
}
|
||||
|
||||
getConfigs() {
|
||||
|
@ -78,6 +80,7 @@ class SessionStore {
|
|||
'allow-attachments': (this.getItem('allow-attachments') * 1),
|
||||
'maintenance-mode': (this.getItem('maintenance-mode') * 1),
|
||||
'max-size': this.getItem('max-size'),
|
||||
'tags': this.getItem('tags')
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue