From b5c3d7ee238cd847077b9dd7cd7ef56d5b30283e Mon Sep 17 00:00:00 2001 From: Guillermo Date: Thu, 27 Sep 2018 21:19:34 -0300 Subject: [PATCH] feature #174 --- client/src/actions/session-actions.js | 2 +- client/src/app-components/activity-row.js | 2 +- client/src/app-components/ticket-event.js | 9 ++-- client/src/app-components/ticket-event.scss | 32 ++++++++++++-- client/src/app-components/ticket-viewer.js | 42 +++++++++++++------ client/src/app-components/ticket-viewer.scss | 15 ++++++- client/src/app/admin/admin-login-page.js | 10 ++--- .../src/app/admin/panel/admin-panel-menu.js | 2 +- .../panel/dashboard/admin-panel-stats.js | 4 +- client/src/data/languages/br.js | 1 + client/src/data/languages/cn.js | 1 + client/src/data/languages/de.js | 1 + client/src/data/languages/en.js | 1 + client/src/data/languages/es.js | 1 + client/src/data/languages/fr.js | 1 + client/src/data/languages/gr.js | 1 + client/src/data/languages/in.js | 1 + client/src/data/languages/it.js | 1 + client/src/data/languages/jp.js | 1 + client/src/data/languages/nl.js | 1 + client/src/data/languages/pt.js | 1 + client/src/data/languages/ru.js | 1 + client/src/data/languages/tr.js | 1 + client/src/scss/_vars.scss | 2 + server/controllers/ticket/comment.php | 4 +- server/models/Ticket.php | 7 +++- server/models/Ticketevent.php | 6 ++- tests/staff/get-new-tickets.rb | 2 +- tests/ticket/comment.rb | 42 +++++++++++++++++++ tests/ticket/seen.rb | 4 +- 30 files changed, 162 insertions(+), 37 deletions(-) diff --git a/client/src/actions/session-actions.js b/client/src/actions/session-actions.js index 8fb8045b..b99daf1e 100644 --- a/client/src/actions/session-actions.js +++ b/client/src/actions/session-actions.js @@ -125,4 +125,4 @@ export default { }) } } -}; \ No newline at end of file +}; diff --git a/client/src/app-components/activity-row.js b/client/src/app-components/activity-row.js index 14396977..aed852f0 100644 --- a/client/src/app-components/activity-row.js +++ b/client/src/app-components/activity-row.js @@ -126,4 +126,4 @@ class ActivityRow extends React.Component { } } -export default ActivityRow; \ No newline at end of file +export default ActivityRow; diff --git a/client/src/app-components/ticket-event.js b/client/src/app-components/ticket-event.js index ba19251f..3a925784 100644 --- a/client/src/app-components/ticket-event.js +++ b/client/src/app-components/ticket-event.js @@ -20,7 +20,8 @@ class TicketEvent extends React.Component { ]), author: React.PropTypes.object, content: React.PropTypes.string, - date: React.PropTypes.string + date: React.PropTypes.string, + private: React.PropTypes.string, }; render() { @@ -83,7 +84,8 @@ class TicketEvent extends React.Component {
{this.props.author.name} - ({i18n((this.props.author.staff) ? 'STAFF' : 'CUSTOMER')}) + {i18n((this.props.author.staff) ? 'STAFF' : 'CUSTOMER')} + {(this.props.private*1) ? {i18n('PRIVATE')} : null}
{DateTransformer.transformToString(this.props.date)}
@@ -205,7 +207,8 @@ class TicketEvent extends React.Component { 'ticket-event_close': this.props.type === 'CLOSE', 'ticket-event_reopen': this.props.type === 'RE_OPEN', 'ticket-event_department': this.props.type === 'DEPARTMENT_CHANGED', - 'ticket-event_priority': this.props.type === 'PRIORITY_CHANGED' + 'ticket-event_priority': this.props.type === 'PRIORITY_CHANGED', + 'ticket-event_private': this.props.private*1, }; return classNames(classes); diff --git a/client/src/app-components/ticket-event.scss b/client/src/app-components/ticket-event.scss index 328d16e1..ccd25dac 100644 --- a/client/src/app-components/ticket-event.scss +++ b/client/src/app-components/ticket-event.scss @@ -66,10 +66,14 @@ color: $primary-black; &-type { - font-size: 10px; + font-size: 10.6px; padding-left: 10px; color: $secondary-blue; - font-variant: small-caps; + background-color: very-light-grey; + border: 2px solid; + border-radius: 4px; + padding: 4px; + margin-left: 12px; } } @@ -78,6 +82,8 @@ border: 2px solid $light-grey; border-bottom: none; padding: 12px; + font-size: 10.6px; + font-family: helvetica; background-color: $light-grey; } @@ -176,4 +182,24 @@ padding-top: 5px; } } -} \ No newline at end of file + &_private { + .ticket-event__comment-pointer { + border-right-color: $light-yellow; + } + .ticket-event__comment-date { + background-color: $light-yellow; + border-color: $light-yellow; + } + .ticket-event__comment-content { + background-color: $very-light-yellow; + border-color: $very-light-yellow; + } + .ticket-event__staff-pic { + background-color: $light-yellow; + border-color: $light-yellow; + } + .ticket-event__file { + background-color: $light-yellow; + } + } +} diff --git a/client/src/app-components/ticket-viewer.js b/client/src/app-components/ticket-viewer.js index ca67dc68..c48523de 100644 --- a/client/src/app-components/ticket-viewer.js +++ b/client/src/app-components/ticket-viewer.js @@ -46,7 +46,8 @@ class TicketViewer extends React.Component { state = { loading: false, commentValue: TextEditor.createEmpty(), - commentEdited: false + commentEdited: false, + commentPrivate: false }; componentDidMount() { @@ -210,19 +211,22 @@ class TicketViewer extends React.Component { renderResponseField() { return (
-
{i18n('RESPOND')}
- {this.renderCustomResponses()} -
-
+ +
{i18n('RESPOND')}
+
+ {this.renderCustomResponses()} + {this.renderPrivate()} +
+
{(this.props.allowAttachments) ? : null}
{i18n('RESPOND_TICKET')}
- -
- {(this.state.commentError) ? this.renderCommentError() : null} +
+ {(this.state.commentError) ? this.renderCommentError() : null} +
); } @@ -242,7 +246,7 @@ class TicketViewer extends React.Component { }); customResponsesNode = ( -
+
); @@ -257,6 +261,18 @@ class TicketViewer extends React.Component { ); } + renderPrivate() { + if (this.props.userStaff) { + return ( +
+ +
+ ); + } else { + return null; + } + } + getCommentFormProps() { return { onSubmit: this.onSubmit.bind(this), @@ -264,11 +280,13 @@ class TicketViewer extends React.Component { onChange: (formState) => {this.setState({ commentValue: formState.content, commentFile: formState.file, - commentEdited: true + commentEdited: true, + commentPrivate: formState.private })}, values: { 'content': this.state.commentValue, - 'file': this.state.commentFile + 'file': this.state.commentFile, + 'private': this.state.commentPrivate } }; } @@ -386,7 +404,7 @@ class TicketViewer extends React.Component { dataAsForm: true, data: _.extend({ ticketNumber: this.props.ticket.ticketNumber - }, formState) + }, formState, {private: formState.private ? 1 : 0}) }).then(this.onCommentSuccess.bind(this), this.onCommentFail.bind(this)); } diff --git a/client/src/app-components/ticket-viewer.scss b/client/src/app-components/ticket-viewer.scss index 4ba5f7e9..1ae5f598 100644 --- a/client/src/app-components/ticket-viewer.scss +++ b/client/src/app-components/ticket-viewer.scss @@ -10,6 +10,9 @@ font-size: 16px; padding: 6px 0; } + &__private { + + } &__number { color: white; @@ -76,11 +79,19 @@ padding: 20px 0 0 20px; text-align: left; } + &-buttons { display: flex; - justify-content: space-between; - align-items: center; + justify-content: space-between; + align-items: center; } + + } + &__actions { + background-color: $very-light-grey; + + display:flex; + align-items:center;justify-content: space-between; } } diff --git a/client/src/app/admin/admin-login-page.js b/client/src/app/admin/admin-login-page.js index 72e5daba..3042b2ea 100644 --- a/client/src/app/admin/admin-login-page.js +++ b/client/src/app/admin/admin-login-page.js @@ -26,7 +26,7 @@ class AdminLoginPage extends React.Component { loadingLogin: false, loadingRecover: false }; - + componentDidUpdate(prevProps) { if (!prevProps.session.failed && this.props.session.failed) { this.refs.loginForm.refs.password.focus(); @@ -34,7 +34,7 @@ class AdminLoginPage extends React.Component { } render() { - return ( + return (
{this.renderLogin()} @@ -43,7 +43,7 @@ class AdminLoginPage extends React.Component {
); } - + renderLogin() { return (
@@ -65,7 +65,7 @@ class AdminLoginPage extends React.Component {
); } - + renderPasswordRecovery() { return (
@@ -161,7 +161,7 @@ class AdminLoginPage extends React.Component { loginFormErrors: errors }); } - + onRecoverFormErrorsValidation(errors) { this.setState({ recoverFormErrors: errors diff --git a/client/src/app/admin/panel/admin-panel-menu.js b/client/src/app/admin/panel/admin-panel-menu.js index 4c7ae546..b1a67843 100644 --- a/client/src/app/admin/panel/admin-panel-menu.js +++ b/client/src/app/admin/panel/admin-panel-menu.js @@ -224,4 +224,4 @@ export default connect((store) => { return { level: store.session.userLevel }; -})(AdminPanelMenu); \ No newline at end of file +})(AdminPanelMenu); diff --git a/client/src/app/admin/panel/dashboard/admin-panel-stats.js b/client/src/app/admin/panel/dashboard/admin-panel-stats.js index e3be6ac3..5da731fd 100644 --- a/client/src/app/admin/panel/dashboard/admin-panel-stats.js +++ b/client/src/app/admin/panel/dashboard/admin-panel-stats.js @@ -14,7 +14,7 @@ class AdminPanelStats extends React.Component {
); } - + } -export default AdminPanelStats; \ No newline at end of file +export default AdminPanelStats; diff --git a/client/src/data/languages/br.js b/client/src/data/languages/br.js index 26ba0fd7..99b4a26c 100644 --- a/client/src/data/languages/br.js +++ b/client/src/data/languages/br.js @@ -183,6 +183,7 @@ export default { 'HIMSELF': 'ele mesmo', 'ADD_USER': 'Adicionar usuário', 'UPLOAD_FILE': 'Subir arquivo', + 'PRIVATE': 'privado', 'CHART_CREATE_TICKET': 'Chamados criados', 'CHART_CLOSE': 'Chamados fechados', diff --git a/client/src/data/languages/cn.js b/client/src/data/languages/cn.js index e49f600a..7b07922b 100644 --- a/client/src/data/languages/cn.js +++ b/client/src/data/languages/cn.js @@ -184,6 +184,7 @@ export default { 'HIMSELF': '他自己', 'ADD_USER': '添加用户', 'UPLOAD_FILE': '上传文件', + 'PRIVATE': '私人的', 'CHART_CREATE_TICKET': '已創建門票', 'CHART_CLOSE': '門票已關閉', diff --git a/client/src/data/languages/de.js b/client/src/data/languages/de.js index fe739403..bb674974 100644 --- a/client/src/data/languages/de.js +++ b/client/src/data/languages/de.js @@ -184,6 +184,7 @@ export default { 'HIMSELF': 'selbst', 'ADD_USER': 'Benutzer hinzufügen', 'UPLOAD_FILE': 'Datei hochladen', + 'PRIVATE': 'Privatgelände', 'CHART_CREATE_TICKET': 'Tickets erstellt', 'CHART_CLOSE': 'Tickets geschlossen', diff --git a/client/src/data/languages/en.js b/client/src/data/languages/en.js index 3d180392..de65e008 100644 --- a/client/src/data/languages/en.js +++ b/client/src/data/languages/en.js @@ -184,6 +184,7 @@ export default { 'HIMSELF': 'himself', 'ADD_USER': 'Add user', 'UPLOAD_FILE': 'Upload file', + 'PRIVATE': 'private', 'CHART_CREATE_TICKET': 'Tickets created', 'CHART_CLOSE': 'Tickets closed', diff --git a/client/src/data/languages/es.js b/client/src/data/languages/es.js index b02971c3..320f7351 100644 --- a/client/src/data/languages/es.js +++ b/client/src/data/languages/es.js @@ -184,6 +184,7 @@ export default { 'HIMSELF': 'si mismo', 'ADD_USER': 'Añadir un usuario', 'UPLOAD_FILE': 'Subir archivo', + 'PRIVATE': 'privado', 'CHART_CREATE_TICKET': 'Tickets creados', 'CHART_CLOSE': 'Tickets cerrados', diff --git a/client/src/data/languages/fr.js b/client/src/data/languages/fr.js index 49c806f3..8aabc598 100644 --- a/client/src/data/languages/fr.js +++ b/client/src/data/languages/fr.js @@ -184,6 +184,7 @@ export default { 'HIMSELF': 'lui-même', 'ADD_USER': 'Ajouter un utilisateur', 'UPLOAD_FILE': 'Téléverser un fichier', + 'PRIVATE': 'privé', 'CHART_CREATE_TICKET': 'Tickets créés', 'CHART_CLOSE': 'Tickets fermés', diff --git a/client/src/data/languages/gr.js b/client/src/data/languages/gr.js index f5e9fa8e..8e55aa2e 100644 --- a/client/src/data/languages/gr.js +++ b/client/src/data/languages/gr.js @@ -184,6 +184,7 @@ 'HIMSELF': 'ο ίδιος', 'ADD_USER': 'Πρόσθεσε χρήστη', 'UPLOAD_FILE': 'Ανέβασμα αρχείου', + 'PRIVATE': 'ιδιωτικός', 'CHART_CREATE_TICKET': 'Τα εισιτήρια δημιουργήθηκαν', 'CHART_CLOSE': 'Τα εισιτήρια κλείσανε', diff --git a/client/src/data/languages/in.js b/client/src/data/languages/in.js index 2f02fd24..301ed531 100644 --- a/client/src/data/languages/in.js +++ b/client/src/data/languages/in.js @@ -184,6 +184,7 @@ export default { 'HIMSELF': 'स्वयं', 'ADD_USER': 'उपयोगकर्ता जोड़ें', 'UPLOAD_FILE': 'दस्तावेज अपलोड करें', + 'PRIVATE': 'निजी', 'CHART_CREATE_TICKET': 'टिकट बनाया', 'CHART_CLOSE': 'टिकट बंद कर दिया', diff --git a/client/src/data/languages/it.js b/client/src/data/languages/it.js index 16a7a4ba..bb203e0c 100644 --- a/client/src/data/languages/it.js +++ b/client/src/data/languages/it.js @@ -184,6 +184,7 @@ export default { 'HIMSELF': 'lui stesso', 'ADD_USER': 'Aggiungi utente', 'UPLOAD_FILE': 'Caricare un file', + 'PRIVATE': 'privato', 'CHART_CREATE_TICKET': 'Tickets creato', 'CHART_CLOSE': 'Tickets chiuso', diff --git a/client/src/data/languages/jp.js b/client/src/data/languages/jp.js index 9f5b3b37..beecedae 100644 --- a/client/src/data/languages/jp.js +++ b/client/src/data/languages/jp.js @@ -184,6 +184,7 @@ export default { 'HIMSELF': '彼自身', 'ADD_USER': 'ユーザーを追加する', 'UPLOAD_FILE': 'ファイルをアップロードする', + 'PRIVATE': 'プライベート', 'CHART_CREATE_TICKET': '作成されたチケット', 'CHART_CLOSE': 'チケットが閉じられました', diff --git a/client/src/data/languages/nl.js b/client/src/data/languages/nl.js index 21d702cd..8a95072f 100644 --- a/client/src/data/languages/nl.js +++ b/client/src/data/languages/nl.js @@ -184,6 +184,7 @@ export default { 'HIMSELF': 'zichzelf', 'ADD_USER': 'Voeg gebruiker toe', 'UPLOAD_FILE': 'Upload bestand', + 'PRIVATE': 'privaat', 'CHART_CREATE_TICKET': 'Aangemaakte incidenten', 'CHART_CLOSE': 'Gesloten incidenten', diff --git a/client/src/data/languages/pt.js b/client/src/data/languages/pt.js index 8e7c6fdf..7536a271 100644 --- a/client/src/data/languages/pt.js +++ b/client/src/data/languages/pt.js @@ -184,6 +184,7 @@ export default { 'HIMSELF': 'ele mesmo', 'ADD_USER': 'Adicionar usuário', 'UPLOAD_FILE': 'Subir arquivo', + 'PRIVATE': 'privado', 'CHART_CREATE_TICKET': 'Ingressos criados', 'CHART_CLOSE': 'Ingressos fechados', diff --git a/client/src/data/languages/ru.js b/client/src/data/languages/ru.js index fa573480..d24745ad 100644 --- a/client/src/data/languages/ru.js +++ b/client/src/data/languages/ru.js @@ -184,6 +184,7 @@ export default { 'HIMSELF': 'сам', 'ADD_USER': 'Добавить пользователя', 'UPLOAD_FILE': 'Загрузить файл', + 'PRIVATE': 'частный', 'CHART_CREATE_TICKET': 'Билеты создано', 'CHART_CLOSE': ' Билеты закрыты', diff --git a/client/src/data/languages/tr.js b/client/src/data/languages/tr.js index a3fe6920..14ff6b55 100644 --- a/client/src/data/languages/tr.js +++ b/client/src/data/languages/tr.js @@ -184,6 +184,7 @@ export default { 'HIMSELF': 'kendisi', 'ADD_USER': 'Kullanıcı Ekle', 'UPLOAD_FILE': 'Dosya yükleme', + 'PRIVATE': 'gizli', 'CHART_CREATE_TICKET': 'Biletler oluşturuldu', 'CHART_CLOSE': 'Biletler kapandı', diff --git a/client/src/scss/_vars.scss b/client/src/scss/_vars.scss index 8e9f97f3..352503ad 100644 --- a/client/src/scss/_vars.scss +++ b/client/src/scss/_vars.scss @@ -6,6 +6,8 @@ $primary-blue: #414A59; $secondary-blue: #20B8c5; $primary-yellow: #E5D151; +$light-yellow: rgba(229,209,81,0.6); +$very-light-yellow: #ffffe0; $primary-green: #82CA9C; diff --git a/server/controllers/ticket/comment.php b/server/controllers/ticket/comment.php index 8f09492b..d62ffe54 100755 --- a/server/controllers/ticket/comment.php +++ b/server/controllers/ticket/comment.php @@ -16,6 +16,7 @@ DataValidator::with('CustomValidations', true); * * @apiParam {String} content Content of the comment. * @apiParam {Number} ticketNumber The number of the ticket to comment. + * @apiParam {Boolean} private Indicates if the comment is not shown to users. * * @apiUse NO_PERMISSION * @apiUse INVALID_CONTENT @@ -111,7 +112,8 @@ class CommentController extends Controller { $comment->setProperties(array( 'content' => $this->content, 'file' => ($fileUploader instanceof FileUploader) ? $fileUploader->getFileName() : null, - 'date' => Date::getCurrentDate() + 'date' => Date::getCurrentDate(), + 'private' => (Controller::isStaffLogged() && Controller::request('private')) ? 1 : 0 )); if(Controller::isStaffLogged()) { diff --git a/server/models/Ticket.php b/server/models/Ticket.php index 119f56d5..4a844336 100755 --- a/server/models/Ticket.php +++ b/server/models/Ticket.php @@ -170,7 +170,8 @@ class Ticket extends DataStore { 'content'=> $ticketEvent->content, 'author' => [], 'date'=> $ticketEvent->date, - 'file'=> $ticketEvent->file + 'file'=> $ticketEvent->file, + 'private'=> $ticketEvent->private, ]; $author = $ticketEvent->getAuthor(); @@ -184,6 +185,10 @@ class Ticket extends DataStore { ]; } + if(!Controller::isStaffLogged() && $ticketEvent->private) { + continue; + } + $events[] = $event; } diff --git a/server/models/Ticketevent.php b/server/models/Ticketevent.php index 91f6c831..a8887e6a 100755 --- a/server/models/Ticketevent.php +++ b/server/models/Ticketevent.php @@ -13,6 +13,7 @@ * @apiParam {Boolean} author.staff Indicates if the author is a staff. * @apiParam {String} date The date of the ticket event. * @apiParam {String} file The file of the ticket event. + * @apiParam {Boolean} private Indicates if this event is not shown to users. */ class Ticketevent extends DataStore { @@ -58,7 +59,8 @@ class Ticketevent extends DataStore { 'file', 'authorUser', 'authorStaff', - 'date' + 'date', + 'private' ]; } @@ -87,4 +89,4 @@ class Ticketevent extends DataStore { ] ]; } -} \ No newline at end of file +} diff --git a/tests/staff/get-new-tickets.rb b/tests/staff/get-new-tickets.rb index 0def25ff..debe36f0 100644 --- a/tests/staff/get-new-tickets.rb +++ b/tests/staff/get-new-tickets.rb @@ -10,7 +10,7 @@ describe '/staff/get-new-tickets' do }) (result['status']).should.equal('success') - (result['data'].size).should.equal(9) + (result['data'].size).should.equal(8) end end diff --git a/tests/ticket/comment.rb b/tests/ticket/comment.rb index d522198f..cdf6dbe9 100644 --- a/tests/ticket/comment.rb +++ b/tests/ticket/comment.rb @@ -142,4 +142,46 @@ describe '/ticket/comment/' do (result['status']).should.equal('fail') (result['message']).should.equal('NO_PERMISSION') end + + it 'should keep private on 0 if an user creates a private comment' do + Scripts.login('commenter@os4.com', 'commenter') + + result = request('/ticket/comment', { + content: 'this is not a private comment', + ticketNumber: @ticketNumber, + csrf_userid: $csrf_userid, + csrf_token: $csrf_token, + private: 1 + }) + + (result['status']).should.equal('success') + comment = $database.getRow('ticketevent', 'this is not a private comment', 'content') + (comment['private']).should.equal("0") + request('/user/logout') + + end + + it 'should change private to 1 if a staff creates a private comment' do + request('/user/logout') + + Scripts.login('jorah@opensupports.com', 'testpassword', true) + + request('/staff/assign-ticket', { + ticketNumber: @ticketNumber, + csrf_userid: $csrf_userid, + csrf_token: $csrf_token, + }) + + result = request('/ticket/comment', { + content: 'this is a private comment', + ticketNumber: @ticketNumber, + csrf_userid: $csrf_userid, + csrf_token: $csrf_token, + private: 1 + }) + puts result['message'] + (result['status']).should.equal('success') + comment = $database.getRow('ticketevent', 'this is a private comment', 'content') + (comment['private']).should.equal("1") + end end diff --git a/tests/ticket/seen.rb b/tests/ticket/seen.rb index 9cff88bc..bdccd03a 100644 --- a/tests/ticket/seen.rb +++ b/tests/ticket/seen.rb @@ -18,7 +18,7 @@ describe '/ticket/seen' do end end - describe 'when a user is logged' do + describe 'when an user is logged' do request('/user/logout') Scripts.login() @@ -36,4 +36,4 @@ describe '/ticket/seen' do end end -end \ No newline at end of file +end