Skip to content

Commit

Permalink
LDBR-3.18: Комментарии (#38)
Browse files Browse the repository at this point in the history
* LDBR-3.18: Добавить комментарии с плохой версткой.

* LDBR-3.18: Интегрировать с бэкендом.

* LDBR-3.18: Исправить комментарии.

* LDBR-3.18: Переписать стиль у комментов

* LDBR-3.18: Исправить undefined при добавлении комментария в новую карточку

* LDBR-3.18: Починить редактирование комментария

* LDBR-3.18: Предзапрос профиля для работы комментов

* LDBR-3.18: Исправить замечания линтера

* LDBR-3.18: Исправить авторство комментария при создании комментария.

Co-authored-by: Georgiy <[email protected]>
  • Loading branch information
DPeshkoff and GeorgiyX authored Nov 25, 2021
1 parent 64104d3 commit 90d0594
Show file tree
Hide file tree
Showing 9 changed files with 661 additions and 3 deletions.
67 changes: 67 additions & 0 deletions src/actions/comments.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
'use strict';

// Modules
import Dispatcher from '../modules/Dispatcher/Dispatcher.js';

/**
* Константа, содержащая в себе типы действий для списка досок.
*/
export const CommentsActionTypes = {
CARD_ADD_COMMENT: 'card/comment/add',
CARD_EDIT_COMMENT: 'card/comment/edit',
CARD_UPDATE_COMMENT: 'card/comment/update',
CARD_DELETE_COMMENT: 'card/comment/delete',
};

/**
* Класс, содержащий в себе действия в системе.
*/
export const commentsActions = {
/**
* Создает комментарий
* @param {String} text текст комментария
*/
createComment(text) {
Dispatcher.dispatch({
actionName: CommentsActionTypes.CARD_ADD_COMMENT,
data: {text},
});
},

/**
* Удалить комментарий (не спрашиваем, хотим ли)
* @param {Number} cmid id комментария
*/
deleteComment(cmid) {
Dispatcher.dispatch({
actionName: CommentsActionTypes.CARD_DELETE_COMMENT,
data: {cmid},
});
},

/**
* Переключает комментарий в режим редактирования
* @param {Number} cmid id комментария
*/
editComment(cmid) {
Dispatcher.dispatch({
actionName: CommentsActionTypes.CARD_EDIT_COMMENT,
data: {cmid},
});
},

/**
* Обновляет список карточек
* @param {String} text текст комментария
* @param {Number} cmid id комментария
*/
updateComment(text, cmid) {
Dispatcher.dispatch({
actionName: CommentsActionTypes.CARD_UPDATE_COMMENT,
data: {
text,
cmid,
},
});
},
};
11 changes: 11 additions & 0 deletions src/modules/Helpers/IsAuthorHelper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import UserStore from '../../stores/UserStore/UserStore.js';

/**
* Handelbars helper, проверяет авторство комментария
* @param {any} author - логин автора комментария
* @return {boolean} - результат сравнения
* @constructor
*/
export default function IsAuthorHelper(author) {
return author === UserStore.getContext('userName');
};
53 changes: 53 additions & 0 deletions src/modules/Network/Network.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class Network {
board: 'api/boards',
card: 'api/cards',
cardlist: 'api/cardLists',
comments: 'api/comments',
usersearch: {
card: 'api/usersearch/card',
board: 'api/usersearch/board',
Expand Down Expand Up @@ -538,6 +539,58 @@ class Network {
return this.httpRequest(`http://${this.BackendUrl}:${this.BackendPort}` +
`/${this._endpoints.checklistsItems}/${chliid}`, options);
}


/**
* Метод, реализующий запрос POST /api/comments.
* @param {object} data полезная нагрузка запроса
* @return {Promise<Response>} промис запроса
*/
async createComment(data) {
const options = {
method: 'post',
body: JSON.stringify(data),
};
return this.httpRequest(
`http://${this.BackendUrl}:${this.BackendPort}/${this._endpoints.comments}`,
options);
}

/**
* Метод, реализующий запрос PUT /api/comments.
* @param {Object} data полезная нагрузка запроса
* @param {Number} cmid id обновляемого комментария
* @return {Promise<Response>} промис запроса
*/
async updateComment(data) {
const options = {
method: 'put',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
};
return this.httpRequest(
`http://${this.BackendUrl}:${this.BackendPort}/${this._endpoints.comments}/${data.cmid}`,
options);
}

/**
* Метод, реализующий запрос DELETE /api/comments/:cmid.
* @param {Number} data данные запроса
* @return {Promise<Response>} промис запроса
*/
async deleteComment(data) {
const options = {
method: 'delete',
headers: {
'Content-Type': 'application/json',
},
};
return this.httpRequest(
`http://${this.BackendUrl}:${this.BackendPort}/${this._endpoints.comments}/${data.cmid}`,
options);
}
}

export default new Network();
46 changes: 44 additions & 2 deletions src/popups/Card/CardPopUp.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -88,14 +88,56 @@
{{#if errors}}
<div class="error">{{errors}}</div>
{{/if}}
{{# if edit }}
{{#if edit }}
<button class="button" id="cardPopUpAddAssigneeBtnId">Участники</button>
<button class="button" id="cardPopUpAddCheckListBtnId">Новый чек-лист</button>
<button class="button" id="cardPopUpSaveBtnId">Сохранить</button>
{{ else }}
{{else }}
<button class="button" id="cardPopUpCreateBtnId">Создать</button>
{{/if}}
{{#if edit}}
<div class="form-inline" role="form">
<div class="form-group">
<input class="simple-form-element" type="text" id="newCommentTextId"
name="comment" autocomplete="off"
placeholder="Добавить комментарий" required>
</div>
<div class="form-group">
<button class="button button_small" id="createCommentId">Добавить</button>
</div>
</div>
<div class="comments-wrapper">
{{#each comments}}
<div class="comment">
<img class="comment__avatar" src="{{this.user.avatar}}"/>
<div class="comment__content">
{{#if this.edit}}
<input class="simple-form-element commentInput" type="text"
pattern="^[a-zA-Z\d]{1,40}$" autocomplete="off" required
value="{{this.text}}">
{{else}}
<div class="comment__text">{{this.text}}</div>
<div class="date sub-text">{{this.date}}</div>
{{/if}}
</div>
<div class="comment__btns">
{{#if this.edit}}
<div class="material-icon-save saveComment"
data-id="{{this.cmid}}"></div>
{{/if}}
{{#if (IsAuthorHelper this.user.userName)}}
<div class="material-icon-edit material-icon-edit editComment"
data-id="{{this.cmid}}"></div>
<div class="material-icon-delete material-icon-delete deleteComment"
data-id="{{this.cmid}}"></div>
{{/if}}
</div>
</div>
{{/each}}
</div>
{{/if}}
</div>

</form>
<div class="close-button" id="cardPopUpCloseId"></div>
</div>
Expand Down
84 changes: 84 additions & 0 deletions src/popups/Card/CardPopUp.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import template from './CardPopUp.hbs';

// Actions
import {cardActions} from '../../actions/card.js';
import {commentsActions} from '../../actions/comments.js';
import {checkListAction} from '../../actions/checklist';

// Стили:
Expand Down Expand Up @@ -37,6 +38,13 @@ export default class CardPopUp extends BaseComponent {
positionSelect: document.getElementById('cardPopUpPositionId'),
card_name: document.getElementById('cardPopUpTitleId'),
description: document.getElementById('cardPopUpDescriptionId'),
comments: {
editBtns: document.querySelectorAll('.editComment'),
saveBtns: document.querySelectorAll('.saveComment'),
deleteBtns: document.querySelectorAll('.deleteComment'),
},
newCommentText: document.getElementById('newCommentTextId'),
addCommentBtn: document.getElementById('createCommentId'),
deadline: document.getElementById('cardPopUpDeadlineId'),
assigneeBtn: document.getElementById('cardPopUpAddAssigneeBtnId'),
checkList: {
Expand Down Expand Up @@ -66,6 +74,16 @@ export default class CardPopUp extends BaseComponent {
this._elements.closeBtn?.addEventListener('click', this._onPopUpClose);
this._elements.createBtn?.addEventListener('click', this._onCreate);
this._elements.saveBtn?.addEventListener('click', this._onSave);
this._elements.comments?.editBtns?.forEach((editCommentBtn)=>{
editCommentBtn.addEventListener('click', this._onEditComment);
});
this._elements.comments?.saveBtns?.forEach((saveCommentBtn)=>{
saveCommentBtn.addEventListener('click', this._onUpdateComment);
});
this._elements.comments?.deleteBtns?.forEach((deleteCommentBtn)=>{
deleteCommentBtn.addEventListener('click', this._onDeleteComment);
});
this._elements.addCommentBtn?.addEventListener('click', this._onCreateComment);
this._elements.deadline?.addEventListener('click', this._onDeadlineClick);
this._elements.assigneeBtn?.addEventListener('click', this._onAssigneeClick);

Expand Down Expand Up @@ -109,6 +127,16 @@ export default class CardPopUp extends BaseComponent {
this._elements.closeBtn?.removeEventListener('click', this._onPopUpClose);
this._elements.createBtn?.removeEventListener('click', this._onCreate);
this._elements.saveBtn?.removeEventListener('click', this._onSave);
this._elements.comments?.editBtns?.forEach((editCommentBtn)=>{
editCommentBtn.removeEventListener('click', this._onEditComment);
});
this._elements.comments?.saveBtns?.forEach((saveCommentBtn)=>{
saveCommentBtn.removeEventListener('click', this._onUpdateComment);
});
this._elements.comments?.deleteBtns?.forEach((deleteCommentBtn)=>{
deleteCommentBtn.removeEventListener('click', this._onDeleteComment);
});
this._elements.addCommentBtn?.removeEventListener('click', this._onCreateComment);
this._elements.deadline?.removeEventListener('click', this._onDeadlineClick);
this._elements.assigneeBtn?.removeEventListener('click', this._onAssigneeClick);

Expand Down Expand Up @@ -147,6 +175,12 @@ export default class CardPopUp extends BaseComponent {
this._onPopUpClose = this._onPopUpClose.bind(this);
this._onCreate = this._onCreate.bind(this);
this._onSave = this._onSave.bind(this);

/* Comments */
this._onDeleteComment = this._onDeleteComment.bind(this);
this._onEditComment = this._onEditComment.bind(this);
this._onUpdateComment = this._onUpdateComment.bind(this);
this._onCreateComment = this._onCreateComment.bind(this);
this._onDeadlineClick = this._onDeadlineClick.bind(this);
this._onAssigneeClick = this._onAssigneeClick.bind(this);

Expand Down Expand Up @@ -209,6 +243,56 @@ export default class CardPopUp extends BaseComponent {
);
}

/**
* Callback, вызываемый при нажатии "Создать комментарий"
* @param {Event} event объект события
* @private
*/
_onCreateComment(event) {
event.preventDefault();
commentsActions.createComment(
this._elements.newCommentText.value,
);
}

/**
* Callback, вызываемый при нажатии редактировании комментария
* @param {Event} event объект события
* @private
*/
_onEditComment(event) {
event.preventDefault();
commentsActions.editComment(
parseInt(event.target.dataset.id, 10),
);
}

/**
* Callback, вызываемый при нажатии "Обновить комментарий"
* @param {Event} event объект события
* @private
*/
_onUpdateComment(event) {
event.preventDefault();
const newComment = event.target.closest('.comment')
.querySelector('.commentInput').value;
commentsActions.updateComment(
newComment,
parseInt(event.target.dataset.id, 10),
);
}

/**
* Callback, вызываемый при удалении комментария
* @param {Event} event объект события
* @private
*/
_onDeleteComment(event) {
event.preventDefault();
commentsActions.deleteComment(
parseInt(event.target.dataset.id, 10),
);
}
/**
* Callback, вызываемый при редактировании дедлайна
* @param {Event} event объект события
Expand Down
31 changes: 31 additions & 0 deletions src/popups/Card/CardPopUp.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,35 @@
@import '../../styles/scss/Constants';
@import '../../styles/scss/Common';

.comments-wrapper {
display: flex;
flex-direction: column;
}

.comment {
display: flex;
flex-direction: row;

&__avatar {
@extend .avatar;
width: 25px;
height: 25px;
}

&__content {
margin-left: 10px;
flex-grow: 1;
}

&__text {
font-size: 16px;
}

&__btns {
display: flex;
flex-direction: row;
}
}

.check-list {
display: flex;
Expand Down
Loading

0 comments on commit 90d0594

Please sign in to comment.