diff --git a/.eslintrc.js b/.eslintrc.js index 051624ad..dbbbfc0a 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -736,8 +736,8 @@ module.exports = { 'no-underscore-dangle': [2, { 'allow': [ '_id', '__get__', '__set__', '__RewireAPI__', '__Rewire__', '__ResetDependency__', '__GetDependency__', ] }], - // Max assertions is 20 and warning rather than error. - 'jest/max-expects': [1, { 'max': 20 }], + // Max assertions is 10 and warning rather than error. + 'jest/max-expects': [1, { 'max': 10 }], // We are not using TypeScript 'jest/no-untyped-mock-factory': 0, }, diff --git a/controllers/__tests__/comment.test.js b/controllers/__tests__/comment.test.js deleted file mode 100644 index 23c25a7f..00000000 --- a/controllers/__tests__/comment.test.js +++ /dev/null @@ -1,121 +0,0 @@ -/** - * Copyright: The PastVu contributors. - * GNU Affero General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/agpl.txt) - */ - -import { CommentN } from '../../models/Comment'; -import admin from '../admin'; -import comment from '../comment'; -import testHelpers from '../../tests/testHelpers'; - -describe('comment', () => { - beforeEach(async () => { - // Mock non-registerd user handshake. - admin.handshake = { 'usObj': { 'isAdmin': true } }; - }); - - afterEach(() => { - // Delete handshake. - delete admin.handshake; - }); - - describe('create for news', () => { - let news; - - beforeEach(async () => { - const data = { pdate: new Date(), 'title': 'Test news', 'txt': 'Test news content' }; - - ({ news } = await admin.saveOrCreateNews(data)); - - const user = await testHelpers.createUser({ login: 'user1', pass: 'pass1' }); - - // Mock non-registered user handshake. - comment.handshake = { 'usObj': { 'isAdmin': true, 'registered': true, user } }; - }); - - afterEach(() => { - // Delete handshake. - delete comment.handshake; - }); - - it('create', async () => { - expect.assertions(3); - - const data = { txt: 'news comment', type: 'news', obj: news.cid }; - - // Create two comments. - const result = await comment.create(data); - - expect(result.comment.txt).toMatch(data.txt); - expect(result.comment.user).toMatch('user1'); - - await expect(CommentN.count({ obj: news })).resolves.toBe(1); - }); - }); - - describe('retrive', () => { - let news; - - beforeEach(async () => { - const data = { pdate: new Date(), 'title': 'Test news', 'txt': 'Test news content' }; - - ({ news } = await admin.saveOrCreateNews(data)); - - const user = await testHelpers.createUser({ login: 'user1', pass: 'pass1' }); - - // Mock non-registered user handshake. - comment.handshake = { 'usObj': { 'isAdmin': true, 'registered': true, user } }; - }); - - afterEach(() => { - // Delete handshake. - delete comment.handshake; - }); - - it('give news comments for user', async () => { - expect.assertions(17); - - const data = { txt: 'news comment', type: 'news', obj: news.cid }; - - // Create 4 comments. - const comment0 = await comment.create(data); - const comment1 = await comment.create(data); - - data.parent = comment1.comment.cid; - data.level = comment1.comment.level + 1; - - const comment2 = await comment.create(data); - - data.parent = comment2.comment.cid; - data.level = comment2.comment.level + 1; - - const comment3 = await comment.create(data); - - // Sanity check. - await expect(CommentN.count({ obj: news })).resolves.toBe(4); - - const comments = await comment.giveForUser({ login: 'user1', type: 'news' }); - - expect(comments.type).toMatch('news'); - expect(comments.countActive).toBe(4); - expect(comments.objs[news.cid].cid).toStrictEqual(news.cid); - expect(comments.objs[news.cid].ccount).toBe(4); - // Comment 0 - no child, waits answer. - expect(comments.comments[3].cid).toStrictEqual(comment0.comment.cid); - expect(comments.comments[3].hasChild).toBeFalsy(); - expect(comments.comments[3].waitsAnswer).toBeTruthy(); - // Comment 1 - has child, does not wait answer. - expect(comments.comments[2].cid).toStrictEqual(comment1.comment.cid); - expect(comments.comments[2].hasChild).toBeTruthy(); - expect(comments.comments[2].waitsAnswer).toBeFalsy(); - // Comment 2 - has child, does not wait answer. - expect(comments.comments[1].cid).toStrictEqual(comment2.comment.cid); - expect(comments.comments[1].hasChild).toBeTruthy(); - expect(comments.comments[1].waitsAnswer).toBeFalsy(); - // Comment 3 - no child, waits answer. - expect(comments.comments[0].cid).toStrictEqual(comment3.comment.cid); - expect(comments.comments[0].hasChild).toBeFalsy(); - expect(comments.comments[0].waitsAnswer).toBeTruthy(); - }); - }); -}); diff --git a/controllers/comment.js b/controllers/comment.js index cd0e01ec..7bc151bb 100644 --- a/controllers/comment.js +++ b/controllers/comment.js @@ -722,36 +722,9 @@ async function giveForUser({ login, page = 1, type = 'photo', active = true, del } const fields = { _id: 0, lastChanged: 1, cid: 1, obj: 1, stamp: 1, txt: 1, 'del.origin': 1 }; - const options = { sort: { stamp: -1 }, skip: page * commentsUserPerPage, limit: commentsUserPerPage }; + const options = { lean: true, sort: { stamp: -1 }, skip: page * commentsUserPerPage, limit: commentsUserPerPage }; - if (!iAm.registered) { - comments = await commentModel.find(query, fields, options).lean().exec(); - } else { - fields.hasChild = 1; - comments = await commentModel.aggregate([ - { - '$match': query, - }, - { - '$lookup': { - 'from': commentModel.collection.collectionName, - 'localField': 'cid', - 'foreignField': 'parent', - 'as': 'children', - }, - }, - { - '$addFields': { - 'hasChild': { - $gt: [{ $size: '$children' }, 0], - }, - }, - }, - { - '$project': fields, - }, - ]).sort(options.sort).skip(options.skip).limit(options.limit).exec(); - } + comments = await commentModel.find(query, fields, options).exec(); } if (_.isEmpty(comments)) { @@ -784,6 +757,18 @@ async function giveForUser({ login, page = 1, type = 'photo', active = true, del if (type === 'photo' && iAm.registered) { await this.call('photo.fillPhotosProtection', { photos: objs, setMyFlag: true }); + + for (const obj of objs) { + objFormattedHashCid[obj.cid] = objFormattedHashId[obj._id] = obj; + obj._id = undefined; + obj.user = undefined; + obj.mime = undefined; + } + } else { + for (const obj of objs) { + objFormattedHashCid[obj.cid] = objFormattedHashId[obj._id] = obj; + obj._id = undefined; + } } for (const obj of objs) { @@ -795,9 +780,6 @@ async function giveForUser({ login, page = 1, type = 'photo', active = true, del // For each comment check object exists and assign to comment its cid for (const comment of comments) { - // Mark those awaiting response. - comment.waitsAnswer = comment.hasChild !== undefined && !comment.hasChild; - const obj = objFormattedHashId[comment.obj]; if (obj !== undefined) { @@ -944,7 +926,7 @@ async function create(data) { throw obj.nocomments ? new NoticeError(constantsError.COMMENT_NOT_ALLOWED) : new AuthorizationError(); } - if (data.parent && (!parent || parent.del || parent.level >= 9 || data.level !== parent.level + 1)) { + if (data.parent && (!parent || parent.del || parent.level >= 9 || data.level !== (parent.level || 0) + 1)) { throw new NoticeError(constantsError.COMMENT_WRONG_PARENT); } @@ -970,11 +952,9 @@ async function create(data) { } } - comment.level = data.level ?? 0; - if (data.parent) { comment.parent = data.parent; - comment.level = data.level ?? parent.level + 1; + comment.level = data.level; } if (fragAdded) { @@ -1018,6 +998,10 @@ async function create(data) { comment.obj = objCid; comment.can = {}; + if (comment.level === undefined) { + comment.level = 0; + } + session.emitUser({ usObj: iAm, excludeSocket: socket }); subscrController.commentAdded(obj._id, iAm.user, stamp); diff --git a/public/style/common.less b/public/style/common.less index 9a065cae..933d91bd 100755 --- a/public/style/common.less +++ b/public/style/common.less @@ -1,7 +1,6 @@ @import '_vars.less'; @import 'fonts/fontU.less'; @import 'bs/bootstrap.less'; -@import 'bs/badges.less'; @-webkit-keyframes fadeIn { 0% { opacity: 0; } @@ -481,14 +480,6 @@ body { } } -// Badges -.badge-latest { - font-size: 11px; - font-weight: normal; - color: #f2f2f2; - background-color: rgba(85, 85, 85, 80%); -} - // Tooltip .tltp { position: absolute; diff --git a/views/module/user/comments.pug b/views/module/user/comments.pug index b8e347a3..9090f58b 100644 --- a/views/module/user/comments.pug +++ b/views/module/user/comments.pug @@ -45,10 +45,6 @@ .dotDelimeter · .commentChanged(title="Показать историю изменений", data-bind="text: ($data.del ? 'Удален ' : 'Изменен ') + moment($data.lastChanged).calendar().toLowerCase(), click: function () {$parent.showHistory($data.obj.cid, $data.cid)}") // /ko - //ko if: $data.waitsAnswer - .dotDelimeter · - .badge.badge-latest Ждёт ответа - // /ko a.commentText(data-bind="attr: {href: $data.link}, html: $data.txt") | @@ -62,10 +58,6 @@ .dotDelimeter · .commentChanged(title="Показать историю изменений", data-bind="text: ($data.del ? 'Удален ' : 'Изменен ') + moment($data.lastChanged).calendar().toLowerCase(), click: function () {$parent.showHistory($data.obj.cid, $data.cid)}") // /ko - //ko if: $data.waitsAnswer - .dotDelimeter · - .badge.badge-latest Ждёт ответа - // /ko a.commentText(style="margin-left:29px", data-bind="attr: {href: $data.link}, html: $data.txt") | @@ -78,4 +70,4 @@ // /ko li.edge(data-bind="css: {disabled: !pageHasNext()}"): a(data-bind="attr: {href: pageUrl() + '/' + (page() + 1) + pageQuery()}", title="Следующая страница") » li.edge(data-bind="css: {disabled: page() === pageLast()}"): a(data-bind="attr: {href: pageUrl() + '/' + pageLast() + pageQuery()}", title="Последняя страница") »» - | + | \ No newline at end of file