diff --git a/client/src/app-components/language-selector.js b/client/src/app-components/language-selector.js index 6f28c686..a5e7c1ae 100644 --- a/client/src/app-components/language-selector.js +++ b/client/src/app-components/language-selector.js @@ -12,7 +12,7 @@ const codeLanguages = { 'Indian': 'in' }; const languages = Object.keys(codeLanguages); -const languageCodes = Object.values(codeLanguages).concat(['en']); +const languageCodes = languages.map((key) => { return codeLanguages[key]; }).concat(['en']); class LanguageSelector extends React.Component { static propTypes = { diff --git a/client/src/app-components/ticket-action.js b/client/src/app-components/ticket-action.js new file mode 100644 index 00000000..fb3657db --- /dev/null +++ b/client/src/app-components/ticket-action.js @@ -0,0 +1,228 @@ +import React from 'react'; +import classNames from 'classnames'; + +import i18n from 'lib-app/i18n'; +import Icon from 'core-components/icon'; + +class TicketAction extends React.Component { + static propTypes = { + type: React.PropTypes.oneOf([ + 'COMMENT', + 'ASSIGN', + 'UN_ASSIGN', + 'CLOSE', + 'RE_OPEN', + 'DEPARTMENT_CHANGED', + 'PRIORITY_CHANGED' + ]), + author: React.PropTypes.object, + content: React.PropTypes.string, + date: React.PropTypes.number + }; + + render() { + let iconNode = null; + + if (this.props.type === 'COMMENT' && this.props.author && this.props.author.staff) { + iconNode = this.renderStaffPic(); + } else { + iconNode = this.renderIcon(); + } + + return ( +
+ +
+ {iconNode} +
+
+ {this.renderActionDescription()} +
+
+ ); + } + + renderStaffPic() { + return ( +
+ +
+ ); + } + + renderIcon() { + return ( +
+ +
+ ); + } + + renderActionDescription() { + const renders = { + 'COMMENT': this.renderComment.bind(this), + 'ASSIGN': this.renderAssignment.bind(this), + 'UN_ASSIGN': this.renderUnAssignment.bind(this), + 'CLOSE': this.renderClosed.bind(this), + 'RE_OPEN': this.renderReOpened.bind(this), + 'DEPARTMENT_CHANGED': this.renderDepartmentChange.bind(this), + 'PRIORITY_CHANGED': this.renderPriorityChange.bind(this) + }; + + return renders[this.props.type](); + } + + renderComment() { + return ( +
+ +
+ {this.props.author.name} + ({i18n((this.props.author.staff) ? 'STAFF' : 'CUSTOMER')}) +
+
{this.props.date}
+
+ {this.renderFileRow(this.props.file)} +
+ ); + } + + renderAssignment() { + return ( +
+ {this.props.author.name} + assigned this ticket + on {this.props.date} +
+ ) + } + + renderUnAssignment() { + return ( +
+ {this.props.author.name} + unassigned this ticket + on {this.props.date} +
+ ) + } + + renderClosed() { + return ( +
+ {this.props.author.name} + closed this ticket + on {this.props.date} +
+ ) + } + + renderReOpened() { + return ( +
+ {this.props.author.name} + reopen this ticket + on {this.props.date} +
+ ); + } + + renderDepartmentChange() { + return ( +
+ {this.props.author.name} + change department to + {this.props.content} + on {this.props.date} +
+ ); + } + + renderPriorityChange() { + return ( +
+ {this.props.author.name} + change priority to + {this.props.content} + on {this.props.date} +
+ ); + } + + renderFileRow(file) { + let node = null; + + if (file) { + node = {this.getFileLink(file)} ; + } else { + node = i18n('NO_ATTACHMENT'); + } + + return ( +
+ {node} +
+ ) + } + + getClass() { + const circledTypes = { + 'COMMENT': false, + 'ASSIGN': true, + 'UN_ASSIGN': true, + 'CLOSE': true, + 'RE_OPEN': true, + 'DEPARTMENT_CHANGED': true, + 'PRIORITY_CHANGED': true + }; + const classes = { + 'row': true, + 'ticket-action': true, + 'ticket-action_staff': this.props.author && this.props.author.staff, + 'ticket-action_circled': circledTypes[this.props.type], + 'ticket-action_unassignment': this.props.type === 'UN_ASSIGN', + 'ticket-action_close': this.props.type === 'CLOSE', + 'ticket-action_reopen': this.props.type === 'RE_OPEN', + 'ticket-action_department': this.props.type === 'DEPARTMENT_CHANGED', + 'ticket-action_priority': this.props.type === 'PRIORITY_CHANGED' + }; + + return classNames(classes); + } + + getIconProps() { + const iconName = { + 'COMMENT': 'comment-o', + 'ASSIGN': 'user', + 'UN_ASSIGN': 'user-times', + 'CLOSE': 'lock', + 'RE_OPEN': 'unlock-alt', + 'DEPARTMENT_CHANGED': 'exchange', + 'PRIORITY_CHANGED': 'exclamation' + }; + const iconSize = { + 'COMMENT': '2x', + 'ASSIGN': 'lg', + 'UN_ASSIGN': 'lg', + 'CLOSE': 'lg', + 'RE_OPEN': 'lg', + 'DEPARTMENT_CHANGED': 'lg', + 'PRIORITY_CHANGED': 'lg' + }; + + return { + name: iconName[this.props.type], + size: iconSize[this.props.type] + } + } + + getFileLink(filePath = '') { + const fileName = filePath.replace(/^.*[\\\/]/, ''); + + return ( + {fileName} + ) + } +} + +export default TicketAction; \ No newline at end of file diff --git a/client/src/app-components/ticket-action.scss b/client/src/app-components/ticket-action.scss new file mode 100644 index 00000000..0e9eb818 --- /dev/null +++ b/client/src/app-components/ticket-action.scss @@ -0,0 +1,170 @@ +@import "../scss/vars"; + +.ticket-action { + margin-top: 20px; + text-align: left; + position: relative; + + &__connector { + position: absolute; + background-color: $light-grey; + width: 3px; + height: 100%; + top: 38px; + left: 33px; + z-index: 0; + } + + &__staff-pic { + vertical-align: top; + background-color: $secondary-blue; + color: white; + border-radius: 5px; + width: 42px; + height: 42px; + overflow: hidden; + position: relative; + border: 2px solid $light-grey; + + &-img { + position: absolute; + height: 100%; + left: 50%; + transform: translate(-50%, 0) + } + } + + &__icon { + vertical-align: top; + background-color: $secondary-blue; + color: white; + border-radius: 5px; + width: 42px; + height: 42px; + padding-left: 8px; + padding-top: 4px; + } + + &__comment { + position: relative; + + &-pointer { + right: 100%; + border: solid transparent; + position: absolute; + border-right-color: $light-grey; + border-width: 13px; + margin-top: 8px; + } + + &-author { + text-align: left; + float: left; + position: relative; + padding: 12px; + color: $primary-black; + + &-type { + font-size: 10px; + padding-left: 10px; + color: $secondary-blue; + font-variant: small-caps; + } + } + + &-date { + text-align: right; + border: 2px solid $light-grey; + border-bottom: none; + padding: 12px; + background-color: $light-grey; + + } + + &-content { + background-color: white; + border: 2px solid $very-light-grey; + border-top: none; + padding: 20px 10px; + text-align: left; + } + } + + &_staff { + .ticket-action__icon { + background-color: $primary-blue; + } + + .ticket-action__comment-author-type { + color: $primary-blue; + } + } + + &_circled { + margin-top: 35px; + margin-bottom: 30px; + + .ticket-action__connector { + top: 28px; + } + + .ticket-action__icon { + background-color: white; + color: $primary-black; + border: 3px solid $light-grey; + border-radius: 50%; + width: 36px; + height: 36px; + padding-left: 8px; + padding-top: 4px; + margin-left: 2px; + margin-top: -8px; + } + + .ticket-action__circled { + color: $primary-black; + font-size: $font-size--sm; + margin-top: 1px; + } + + .ticket-action__circled-author { + color: $secondary-blue; + } + + .ticket-action__circled-indication { + color: $primary-green; + } + } + + &_unassignment { + .ticket-action__icon { + padding-left: 6px; + } + } + + &_close { + .ticket-action__icon { + padding-left: 9px; + } + } + + &_reopen { + .ticket-action__icon { + padding-left: 9px; + padding-top: 5px; + } + } + + &_department { + .ticket-action__icon { + padding-left: 6px; + } + } + + &_priority { + .ticket-action__icon { + padding-left: 11px; + padding-top: 5px; + } + } +} \ No newline at end of file diff --git a/client/src/app/main/dashboard/dashboard-ticket/ticket-viewer.js b/client/src/app-components/ticket-viewer.js similarity index 81% rename from client/src/app/main/dashboard/dashboard-ticket/ticket-viewer.js rename to client/src/app-components/ticket-viewer.js index f594aa89..f561a0b8 100644 --- a/client/src/app/main/dashboard/dashboard-ticket/ticket-viewer.js +++ b/client/src/app-components/ticket-viewer.js @@ -6,7 +6,7 @@ import API from 'lib-app/api-call'; import store from 'app/store'; import SessionActions from 'actions/session-actions'; -import TicketAction from 'app/main/dashboard/dashboard-ticket/ticket-action'; +import TicketAction from 'app-components/ticket-action'; import Form from 'core-components/form'; import FormField from 'core-components/form-field'; import SubmitButton from 'core-components/submit-button'; @@ -34,11 +34,13 @@ class TicketViewer extends React.Component { render() { + const ticket = this.props.ticket; + return (
- #{this.props.ticket.ticketNumber} - {this.props.ticket.title} + #{ticket.ticketNumber} + {ticket.title}
{i18n('DEPARTMENT')}
@@ -46,15 +48,15 @@ class TicketViewer extends React.Component {
{i18n('DATE')}
-
{this.props.ticket.department.name}
-
{this.props.ticket.author.name}
-
{this.props.ticket.date}
+
{ticket.department.name}
+
{ticket.author.name}
+
{ticket.date}
- +
- {this.props.ticket.comments.map(this.renderComment.bind(this))} + {ticket.actions && ticket.actions.map(this.renderAction.bind(this))}
{i18n('RESPOND')}
@@ -69,9 +71,9 @@ class TicketViewer extends React.Component { ); } - renderComment(comment, index) { + renderAction(action, index) { return ( - + ); } diff --git a/client/src/app/main/dashboard/dashboard-ticket/ticket-viewer.scss b/client/src/app-components/ticket-viewer.scss similarity index 97% rename from client/src/app/main/dashboard/dashboard-ticket/ticket-viewer.scss rename to client/src/app-components/ticket-viewer.scss index f133235c..b382aa34 100644 --- a/client/src/app/main/dashboard/dashboard-ticket/ticket-viewer.scss +++ b/client/src/app-components/ticket-viewer.scss @@ -1,4 +1,4 @@ -@import "../../../../scss/vars"; +@import "../scss/vars"; .ticket-viewer { &__header { diff --git a/client/src/app/main/dashboard/dashboard-ticket/dashboard-ticket-page.js b/client/src/app/main/dashboard/dashboard-ticket/dashboard-ticket-page.js index fb322cc1..602b4e05 100644 --- a/client/src/app/main/dashboard/dashboard-ticket/dashboard-ticket-page.js +++ b/client/src/app/main/dashboard/dashboard-ticket/dashboard-ticket-page.js @@ -2,7 +2,7 @@ import React from 'react'; import _ from 'lodash'; import {connect} from 'react-redux'; -import TicketViewer from 'app/main/dashboard/dashboard-ticket/ticket-viewer'; +import TicketViewer from 'app-components/ticket-viewer'; class DashboardTicketPage extends React.Component { diff --git a/client/src/app/main/dashboard/dashboard-ticket/ticket-action.js b/client/src/app/main/dashboard/dashboard-ticket/ticket-action.js deleted file mode 100644 index 8a9925d5..00000000 --- a/client/src/app/main/dashboard/dashboard-ticket/ticket-action.js +++ /dev/null @@ -1,105 +0,0 @@ -import React from 'react'; -import classNames from 'classnames'; - -import i18n from 'lib-app/i18n'; -import Icon from 'core-components/icon'; - -class TicketAction extends React.Component { - static propTypes = { - type: React.PropTypes.oneOf(['comment', 'assign']), - config: React.PropTypes.object - }; - - static defaultProps = { - type: 'comment' - }; - - render() { - return ( -
- -
-
- -
-
-
- {this.renderActionDescription()} -
-
- ); - } - - renderActionDescription() { - const renders = { - 'comment': this.renderComment.bind(this), - 'assign': this.renderAssignment.bind(this) - }; - - return renders[this.props.type](); - } - - renderComment() { - const {config} = this.props; - - return ( -
- -
- {config.author.name} - ({i18n((config.author.staff) ? 'STAFF' : 'CUSTOMER')}) -
-
{config.date}
-
- {this.renderFileRow(config.file)} -
- ); - } - - renderAssignment() { - // TODO: Add actions architecture instead of just comments - - return ( -
-
- ) - } - - renderFileRow(file) { - let node = null; - - if (file) { - node = {this.getFileLink(file)} ; - } else { - node = i18n('NO_ATTACHMENT'); - } - - return ( -
- {node} -
- ) - } - - getClass() { - const {config} = this.props; - - let classes = { - 'row': true, - 'ticket-action': true, - 'ticket-action_staff': config.author && config.author.staff - }; - - return classNames(classes); - } - - getFileLink(filePath = '') { - const fileName = filePath.replace(/^.*[\\\/]/, ''); - - return ( - {fileName} - ) - } -} - -export default TicketAction; \ No newline at end of file diff --git a/client/src/app/main/dashboard/dashboard-ticket/ticket-action.scss b/client/src/app/main/dashboard/dashboard-ticket/ticket-action.scss deleted file mode 100644 index 4b39970b..00000000 --- a/client/src/app/main/dashboard/dashboard-ticket/ticket-action.scss +++ /dev/null @@ -1,83 +0,0 @@ -@import "../../../../scss/vars"; - -.ticket-action { - margin-top: 20px; - text-align: left; - position: relative; - - &__connector { - position: absolute; - background-color: $light-grey; - width: 3px; - height: 100%; - top: 38px; - left: 33px; - z-index: 0; - } - - &__icon { - vertical-align: top; - background-color: $secondary-blue; - color: white; - border-radius: 5px; - width: 42px; - height: 42px; - padding-left: 8px; - padding-top: 4px; - } - - &__comment { - position: relative; - - &-pointer { - right: 100%; - border: solid transparent; - position: absolute; - border-right-color: $light-grey; - border-width: 13px; - margin-top: 8px; - } - - &-author { - text-align: left; - float: left; - position: relative; - padding: 12px; - color: $primary-black; - - &-type { - font-size: 10px; - padding-left: 10px; - color: $secondary-blue; - font-variant: small-caps; - } - } - - &-date { - text-align: right; - border: 2px solid $light-grey; - border-bottom: none; - padding: 12px; - background-color: $light-grey; - - } - - &-content { - background-color: white; - border: 2px solid $very-light-grey; - border-top: none; - padding: 20px 10px; - text-align: left; - } - } - - &_staff { - .ticket-action__icon { - background-color: $primary-blue; - } - - .ticket-action__comment-author-type { - color: $primary-blue; - } - } -} \ No newline at end of file diff --git a/client/src/data/fixtures/user-fixtures.js b/client/src/data/fixtures/user-fixtures.js index 529789bc..bbd87aa0 100644 --- a/client/src/data/fixtures/user-fixtures.js +++ b/client/src/data/fixtures/user-fixtures.js @@ -159,28 +159,98 @@ module.exports = [ name: 'Steve Jobs', email: 'steve@jobs.com' }, - comments: [ + actions: [ { - content: 'Do you have apache installed? It generally happens if you dont have apache.', + type: 'ASSIGN', + date: 20150409, author: { - id: 15, - name: 'Steve Jobs', + name: 'Emilia Clarke', email: 'jobs@steve.com', + profilePic: 'http://i65.tinypic.com/9bep95.jpg', staff: true - }, - date: '12 Dec 2016', - file: '' + } }, { + type: 'COMMENT', + date: 20150409, + content: 'Do you have apache installed? It generally happens if you dont have apache.', + author: { + name: 'Emilia Clarke', + email: 'jobs@steve.com', + profilePic: 'http://i65.tinypic.com/9bep95.jpg', + staff: true + } + }, + { + type: 'UN_ASSIGN', + date: 20150410, + author: { + name: 'Emilia Clarke', + email: 'jobs@steve.com', + profilePic: 'http://i65.tinypic.com/9bep95.jpg', + staff: true + } + }, + { + type: 'DEPARTMENT_CHANGED', + date: 20150411, + content: 'System support', + author: { + name: 'Emilia Clarke', + email: 'jobs@steve.com', + profilePic: 'http://i65.tinypic.com/9bep95.jpg', + staff: true + } + }, + { + type: 'COMMENT', + date: 20150412, content: 'I have already installed apache, but the problem persists', author: { - id: 12, name: 'Haskell Curry', steve: 'haskell@lambda.com', staff: false - }, - date: '12 Dec 2016', - file: '' + } + }, + { + type: 'PRIORITY_CHANGED', + date: 20150413, + content: 'MEDIUM', + author: { + name: 'Emilia Clarke', + email: 'jobs@steve.com', + profilePic: 'http://i65.tinypic.com/9bep95.jpg', + staff: true + } + }, + { + type: 'COMMENT', + date: 20150511, + content: 'Thanks!, I soved it by myself', + author: { + name: 'Haskell Curry', + steve: 'haskell@lambda.com', + staff: false + } + }, + { + type: 'CLOSE', + date: 20150513, + author: { + name: 'Emilia Clarke', + email: 'jobs@steve.com', + profilePic: 'http://i65.tinypic.com/9bep95.jpg', + staff: true + } + }, + { + type: 'RE_OPEN', + date: 20151018, + author: { + name: 'Haskell Curry', + email: 'haskell@lambda.com', + staff: false + } } ] }, @@ -205,34 +275,110 @@ module.exports = [ owner: { name: 'Steve Jobs' }, - comments: [ + actions: [ { - content: 'Do you have apache installed? It generally happens if you dont have apache.', + type: 'ASSIGN', + date: 20150409, author: { - name: 'Steve Jobs', + name: 'Emilia Clarke', email: 'jobs@steve.com', + profilePic: 'http://i65.tinypic.com/9bep95.jpg', staff: true } }, { + type: 'COMMENT', + date: 20150409, + content: 'Do you have apache installed? It generally happens if you dont have apache.', + author: { + name: 'Emilia Clarke', + email: 'jobs@steve.com', + profilePic: 'http://i65.tinypic.com/9bep95.jpg', + staff: true + } + }, + { + type: 'UN_ASSIGN', + date: 20150410, + author: { + name: 'Emilia Clarke', + email: 'jobs@steve.com', + profilePic: 'http://i65.tinypic.com/9bep95.jpg', + staff: true + } + }, + { + type: 'DEPARTMENT_CHANGED', + date: 20150411, + content: 'System support', + author: { + name: 'Emilia Clarke', + email: 'jobs@steve.com', + profilePic: 'http://i65.tinypic.com/9bep95.jpg', + staff: true + } + }, + { + type: 'COMMENT', + date: 20150412, content: 'I have already installed apache, but the problem persists', author: { name: 'Haskell Curry', steve: 'haskell@lambda.com', staff: false } + }, + { + type: 'PRIORITY_CHANGED', + date: 20150413, + content: 'MEDIUM', + author: { + name: 'Emilia Clarke', + email: 'jobs@steve.com', + profilePic: 'http://i65.tinypic.com/9bep95.jpg', + staff: true + } + }, + { + type: 'COMMENT', + date: 20150511, + content: 'Thanks!, I soved it by myself', + author: { + name: 'Haskell Curry', + steve: 'haskell@lambda.com', + staff: false + } + }, + { + type: 'CLOSE', + date: 20150513, + author: { + name: 'Emilia Clarke', + email: 'jobs@steve.com', + profilePic: 'http://i65.tinypic.com/9bep95.jpg', + staff: true + } + }, + { + type: 'RE_OPEN', + date: 20151018, + author: { + name: 'Haskell Curry', + email: 'haskell@lambda.com', + staff: false + } } ] }, { - ticketNumber: '878552', + ticketNumber: '118551', title: 'Lorem ipsum door', content: 'I had a problem with the installation of the php server', department: { id: 2, name: 'Environment Setup' }, - date: '15 Apr 2016', + date: 20150409, file: 'http://www.opensupports.com/some_file.zip', language: 'en', unread: false, @@ -245,22 +391,98 @@ module.exports = [ owner: { name: 'Steve Jobs' }, - comments: [ + actions: [ { - content: 'Do you have apache installed? It generally happens if you dont have apache.', + type: 'ASSIGN', + date: 20150409, author: { - name: 'Steve Jobs', + name: 'Emilia Clarke', email: 'jobs@steve.com', + profilePic: 'http://i65.tinypic.com/9bep95.jpg', staff: true } }, { + type: 'COMMENT', + date: 20150409, + content: 'Do you have apache installed? It generally happens if you dont have apache.', + author: { + name: 'Emilia Clarke', + email: 'jobs@steve.com', + profilePic: 'http://i65.tinypic.com/9bep95.jpg', + staff: true + } + }, + { + type: 'UN_ASSIGN', + date: 20150410, + author: { + name: 'Emilia Clarke', + email: 'jobs@steve.com', + profilePic: 'http://i65.tinypic.com/9bep95.jpg', + staff: true + } + }, + { + type: 'DEPARTMENT_CHANGED', + date: 20150411, + content: 'System support', + author: { + name: 'Emilia Clarke', + email: 'jobs@steve.com', + profilePic: 'http://i65.tinypic.com/9bep95.jpg', + staff: true + } + }, + { + type: 'COMMENT', + date: 20150412, content: 'I have already installed apache, but the problem persists', author: { name: 'Haskell Curry', steve: 'haskell@lambda.com', staff: false } + }, + { + type: 'PRIORITY_CHANGED', + date: 20150413, + content: 'MEDIUM', + author: { + name: 'Emilia Clarke', + email: 'jobs@steve.com', + profilePic: 'http://i65.tinypic.com/9bep95.jpg', + staff: true + } + }, + { + type: 'COMMENT', + date: 20150511, + content: 'Thanks!, I soved it by myself', + author: { + name: 'Haskell Curry', + steve: 'haskell@lambda.com', + staff: false + } + }, + { + type: 'CLOSE', + date: 20150513, + author: { + name: 'Emilia Clarke', + email: 'jobs@steve.com', + profilePic: 'http://i65.tinypic.com/9bep95.jpg', + staff: true + } + }, + { + type: 'RE_OPEN', + date: 20151018, + author: { + name: 'Haskell Curry', + email: 'haskell@lambda.com', + staff: false + } } ] }