@fleetbase/ember-ui
Version:
Fleetbase UI provides all the interface components, helpers, services and utilities for building a Fleetbase extension into the Console.
202 lines (170 loc) • 5.68 kB
JavaScript
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { inject as service } from '@ember/service';
import { task } from 'ember-concurrency';
import getWithDefault from '@fleetbase/ember-core/utils/get-with-default';
import getModelName from '@fleetbase/ember-core/utils/get-model-name';
/**
* Component to handle a thread of comments.
*/
export default class CommentThreadComponent extends Component {
/**
* Service to handle data store operations.
* @service
*/
store;
/**
* Service for handling notifications.
* @service
*/
notifications;
/**
* Service for internationalization.
* @service
*/
intl;
/**
* The subject related to the comments.
* @tracked
*/
subject;
/**
* Array of comments related to the subject.
* @tracked
*/
comments = [];
/**
* The text input for publishing a new comment.
* @tracked
*/
input = '';
/**
* Context object containing utility functions.
*/
context = {
isCommentInvalid: this.isCommentInvalid.bind(this),
reloadComments: () => {
return this.reloadComments.perform();
},
publishReply: (comment, input) => {
return this.publishReply.perform(comment, input);
},
updateComment: (comment) => {
return this.updateComment.perform(comment);
},
deleteComment: (comment) => {
return this.deleteComment.perform(comment);
},
};
/**
* Constructor for the comment thread component.
* @param owner - The owner of the component.
* @param subject - The subject of the comment thread.
* @param subjectType - The type of the subject.
*/
constructor(owner, { subject, subjectType }) {
super(...arguments);
this.subject = subject;
this.comments = getWithDefault(this.args, 'comments', getWithDefault(subject, 'comments', []));
this.subjectType = subjectType ? subjectType : getModelName(subject);
}
get visibleComments() {
return this.args.comments ?? this.comments;
}
get subjectUuid() {
return this.subject?.uuid;
}
get subjectPublicId() {
return this.subject?.public_id ?? this.subject?.id ?? this.subject?.uuid;
}
/**
* Asynchronous task to publish a new comment.
* @task
*/
*publishComment() {
if (this.isCommentInvalid(this.input)) {
return;
}
if (typeof this.args.onPublishComment === 'function') {
yield this.args.onPublishComment(this.input, this.subject);
} else {
let comment = this.store.createRecord('comment', {
content: this.input,
subject_id: this.subjectPublicId,
subject_type: this.subjectType,
});
yield comment.save();
}
yield this.reloadComments.perform();
this.input = '';
}
/**
* Asynchronous task to reload the comments related to the subject.
* @task
*/
*reloadComments() {
if (typeof this.args.onReloadComments === 'function') {
this.comments = yield this.args.onReloadComments(this.subject);
} else {
const query = {
withoutParent: 1,
sort: '-created_at',
};
if (this.subjectUuid) {
query.subject_uuid = this.subjectUuid;
} else {
query.subject = this.subjectPublicId;
}
if (this.subjectType) {
query.subject_type = this.subjectType;
}
this.comments = yield this.store.query('comment', query);
}
}
*publishReply(comment, input) {
if (typeof this.args.onPublishReply === 'function') {
yield this.args.onPublishReply(comment, input, this.subject);
yield this.reloadComments.perform();
return;
}
let reply = this.store.createRecord('comment', {
content: input,
parent_comment_uuid: comment.uuid ?? comment.public_id ?? comment.id,
});
yield reply.save();
yield this.reloadComments.perform();
}
*updateComment(comment) {
if (typeof this.args.onUpdateComment === 'function') {
yield this.args.onUpdateComment(comment, this.subject);
yield this.reloadComments.perform();
return;
}
yield comment.save();
}
*deleteComment(comment) {
if (typeof this.args.onDeleteComment === 'function') {
yield this.args.onDeleteComment(comment, this.subject);
yield this.reloadComments.perform();
return;
}
yield comment.destroyRecord();
}
/**
* Checks if a comment is invalid.
* @param {string} comment - The comment to validate.
* @returns {boolean} True if the comment is invalid, false otherwise.
*/
isCommentInvalid(comment) {
if (!comment) {
this.notifications.warning(this.intl.t('component.comment-thread.comment-input-empty-notification'));
return true;
}
// make sure comment is at least 2 characters
if (typeof comment === 'string' && comment.length <= 1) {
this.notifications.warning(this.intl.t('component.comment-thread.comment-min-length-notification'));
return true;
}
return false;
}
}