From 7c741fa0d673f3c808cf3f77127e44e823ea40f8 Mon Sep 17 00:00:00 2001 From: Roman Rizzi Date: Tue, 27 Aug 2019 09:09:00 -0300 Subject: [PATCH] FEATURE: Publish read state on group messages. (Originally introduced in #7989) (#8025) * Revert "Revert "FEATURE: Publish read state on group messages. (#7989) [Undo revert] (#8024)"" This reverts commit 36425eb9f04cfac7201632d648050cb43a035bc1. * Fix: Show who read only if the attribute is enabled * PERF: Precalculate the last post readed by a group member * Use book-reader icon instear of far-eye * FIX: update topic groups correctly * DEV: Tidy up read indicator update on write --- .../components/scrolling-post-stream.js.es6 | 9 +- .../components/topic-list-item.js.es6 | 41 +++++++++ .../discourse/controllers/topic.js.es6 | 11 +++ .../discourse/lib/transform-post.js.es6 | 3 +- .../javascripts/discourse/models/group.js.es6 | 3 +- .../groups-form-interaction-fields.hbs | 10 +++ .../templates/list/topic-list-item.raw.hbs | 5 ++ .../javascripts/discourse/templates/topic.hbs | 1 + .../discourse/widgets/post-menu.js.es6 | 86 +++++++++++++++++- .../discourse/widgets/post-stream.js.es6 | 1 + .../stylesheets/common/base/_topic-list.scss | 6 ++ .../stylesheets/common/base/topic-post.scss | 3 +- .../stylesheets/desktop/topic-post.scss | 4 +- app/assets/stylesheets/mobile/topic-post.scss | 1 + app/controllers/admin/groups_controller.rb | 3 +- app/controllers/groups_controller.rb | 3 +- app/controllers/post_readers_controller.rb | 26 ++++++ app/models/group.rb | 1 + app/models/post_timing.rb | 1 + app/models/topic_group.rb | 71 +++++++++++++++ app/models/topic_list.rb | 5 +- app/models/topic_tracking_state.rb | 56 +++++++++++- app/serializers/basic_group_serializer.rb | 3 +- app/serializers/listable_topic_serializer.rb | 15 +++- app/serializers/post_serializer.rb | 8 ++ app/serializers/topic_view_serializer.rb | 7 +- app/serializers/web_hook_post_serializer.rb | 3 + .../web_hook_topic_view_serializer.rb | 4 + config/locales/client.en.yml | 3 + config/routes.rb | 1 + config/site_settings.yml | 3 +- ...0190807194043_groups_publish_read_state.rb | 7 ++ ...20190820192341_create_topic_group_table.rb | 14 +++ lib/post_jobs_enqueuer.rb | 1 + lib/svg_sprite/svg_sprite.rb | 1 + lib/topic_query.rb | 20 ++++- lib/topic_view.rb | 8 ++ spec/components/topic_query_spec.rb | 18 ++++ spec/models/topic_group_spec.rb | 85 ++++++++++++++++++ spec/models/topic_tracking_state_spec.rb | 64 +++++++++++++ spec/requests/post_readers_controller_spec.rb | 90 +++++++++++++++++++ vendor/assets/svg-icons/fontawesome/solid.svg | 4 + 42 files changed, 688 insertions(+), 21 deletions(-) create mode 100644 app/controllers/post_readers_controller.rb create mode 100644 app/models/topic_group.rb create mode 100644 db/migrate/20190807194043_groups_publish_read_state.rb create mode 100644 db/migrate/20190820192341_create_topic_group_table.rb create mode 100644 spec/models/topic_group_spec.rb create mode 100644 spec/requests/post_readers_controller_spec.rb diff --git a/app/assets/javascripts/discourse/components/scrolling-post-stream.js.es6 b/app/assets/javascripts/discourse/components/scrolling-post-stream.js.es6 index 4121a8b0b33..89a48126f30 100644 --- a/app/assets/javascripts/discourse/components/scrolling-post-stream.js.es6 +++ b/app/assets/javascripts/discourse/components/scrolling-post-stream.js.es6 @@ -40,7 +40,8 @@ export default MountWidget.extend({ "gaps", "selectedQuery", "selectedPostsCount", - "searchService" + "searchService", + "showReadIndicator" ); }, @@ -291,6 +292,12 @@ export default MountWidget.extend({ onRefresh: "refreshLikes" }); } + + if (args.refreshReaders) { + this.dirtyKeys.keyDirty(`post-menu-${args.id}`, { + onRefresh: "refreshReaders" + }); + } } else if (args.force) { this.dirtyKeys.forceAll(); } diff --git a/app/assets/javascripts/discourse/components/topic-list-item.js.es6 b/app/assets/javascripts/discourse/components/topic-list-item.js.es6 index 564938e0566..e7ed6186b34 100644 --- a/app/assets/javascripts/discourse/components/topic-list-item.js.es6 +++ b/app/assets/javascripts/discourse/components/topic-list-item.js.es6 @@ -35,6 +35,47 @@ export const ListItemDefaults = { attributeBindings: ["data-topic-id"], "data-topic-id": Ember.computed.alias("topic.id"), + didInsertElement() { + this._super(...arguments); + + if (this.includeReadIndicator) { + this.messageBus.subscribe(this.readIndicatorChannel, data => { + const nodeClassList = document.querySelector( + `.indicator-topic-${data.topic_id}` + ).classList; + + if (data.show_indicator) { + nodeClassList.remove("unread"); + } else { + nodeClassList.add("unread"); + } + }); + } + }, + + willDestroyElement() { + this._super(...arguments); + + if (this.includeReadIndicator) { + this.messageBus.unsubscribe(this.readIndicatorChannel); + } + }, + + @computed("topic.id") + readIndicatorChannel(topicId) { + return `/private-messages/read-indicator/${topicId}`; + }, + + @computed("topic.read_by_group_member") + unreadClass(readByGroupMember) { + return readByGroupMember ? "" : "unread"; + }, + + @computed("topic.read_by_group_member") + includeReadIndicator(readByGroupMember) { + return typeof readByGroupMember !== "undefined"; + }, + @computed newDotText() { return this.currentUser && this.currentUser.trust_level > 0 diff --git a/app/assets/javascripts/discourse/controllers/topic.js.es6 b/app/assets/javascripts/discourse/controllers/topic.js.es6 index c1983bc4c16..25a635b48bf 100644 --- a/app/assets/javascripts/discourse/controllers/topic.js.es6 +++ b/app/assets/javascripts/discourse/controllers/topic.js.es6 @@ -1348,6 +1348,17 @@ export default Ember.Controller.extend(bufferedProperty("model"), { }) .then(() => refresh({ id: data.id, refreshLikes: true })); break; + case "read": + postStream + .triggerChangedPost(data.id, data.updated_at, { + preserveCooked: true + }) + .then(() => + refresh({ + id: data.id, + refreshReaders: topic.show_read_indicator + }) + ); case "revised": case "rebaked": { postStream diff --git a/app/assets/javascripts/discourse/lib/transform-post.js.es6 b/app/assets/javascripts/discourse/lib/transform-post.js.es6 index 7a1872b4fe5..5f882d8a933 100644 --- a/app/assets/javascripts/discourse/lib/transform-post.js.es6 +++ b/app/assets/javascripts/discourse/lib/transform-post.js.es6 @@ -71,7 +71,8 @@ export function transformBasicPost(post) { expandablePost: false, replyCount: post.reply_count, locked: post.locked, - userCustomFields: post.user_custom_fields + userCustomFields: post.user_custom_fields, + readCount: post.readers_count }; _additionalAttributes.forEach(a => (postAtts[a] = post[a])); diff --git a/app/assets/javascripts/discourse/models/group.js.es6 b/app/assets/javascripts/discourse/models/group.js.es6 index 5ea8f11616f..04898356354 100644 --- a/app/assets/javascripts/discourse/models/group.js.es6 +++ b/app/assets/javascripts/discourse/models/group.js.es6 @@ -178,7 +178,8 @@ const Group = RestModel.extend({ allow_membership_requests: this.allow_membership_requests, full_name: this.full_name, default_notification_level: this.default_notification_level, - membership_request_template: this.membership_request_template + membership_request_template: this.membership_request_template, + publish_read_state: this.publish_read_state }; if (!this.id) { diff --git a/app/assets/javascripts/discourse/templates/components/groups-form-interaction-fields.hbs b/app/assets/javascripts/discourse/templates/components/groups-form-interaction-fields.hbs index b2f254ca328..959e2e12d13 100644 --- a/app/assets/javascripts/discourse/templates/components/groups-form-interaction-fields.hbs +++ b/app/assets/javascripts/discourse/templates/components/groups-form-interaction-fields.hbs @@ -52,6 +52,16 @@ class="groups-form-messageable-level"}} +
+ +
+ {{#if showEmailSettings}}
diff --git a/app/assets/javascripts/discourse/templates/list/topic-list-item.raw.hbs b/app/assets/javascripts/discourse/templates/list/topic-list-item.raw.hbs index 6b6b7b2af14..f6d2ddfc382 100644 --- a/app/assets/javascripts/discourse/templates/list/topic-list-item.raw.hbs +++ b/app/assets/javascripts/discourse/templates/list/topic-list-item.raw.hbs @@ -23,6 +23,11 @@ {{~#if showTopicPostBadges}} {{~raw "topic-post-badges" unread=topic.unread newPosts=topic.displayNewPosts unseen=topic.unseen url=topic.lastUnreadUrl newDotText=newDotText}} {{~/if}} + {{~#if includeReadIndicator}} + + {{~d-icon "book-reader"}} + + {{~/if}}