Skip to content

Reactions Component

charkhaw edited this page Apr 27, 2023 · 24 revisions

Overview

We are going to create a reactions component that will render the reactions block into each HTML element.

The component will take care of fetching all the reactions info, also to add remove reactions. We are going to cover widget side only in this scope, however possible integration to the CP may be available in the next sprint.

Implementation

NameSpace

buildfire.components.reactions

Data Model ReactionsSummary

  • Data will be saved in appData
  • Reserved tag : $$reactionsSummary
  • Model: ReactionsSummary
class ReactionsSummary {
 id,
 itemId,
 reactions : [{type, count, lastReactionBy}] // for now, lastReactionBy should be set when calling increment() only. when calling decrement() we should set it to null.
 _buildfire.index: {
	string1: itemId,
	array1 : [{string1: "reactionType-" + type}] // type = like, heart, ...
  }
}

DataAccess ReactionsSummaries

class ReactionsSummaries {
         get([itemIds]){

        },

         // reactionType: like, heart, ...
	increment({reactionSummaryId, reactionType}){
		filter: {
			id: reactionSummaryId,
			"reactions.type": reactionType
		},
		$inc : {"reactions.count" : 1} ...
            }
	}


	decrement({reactionSummaryId, reactionType}){
		filter: {
			id: reactionSummaryId,
			"reactions.type": reactionType
		},
		$inc : {"reactions.count" : -1} ...	
	}

}

Data Model Reaction

  • Data will be saved in appData
  • Reserved tag : $$reactions
  • Model: Reaction
Class Reaction {
 id,
 itemId,
 userId,
 reactions : [{type}] // object (type)
 _buildfire.index: {
	string1: itemId+"-"+userId,
	array1 : [{string1: "reactionType-" + itemId + "-" + type}]
 }
}

DataAccess Reactions

class Reactions {
  react(options) // options = {itemId, userId, reactionId=null, reactionType}
  unReact(options) // options = {itemId, userId, reactionId=null, reactionType}
  unReactReact(options) // options = {itemId, userId, reactionId=null, reactionType}
  get({itemId, groupeName, pageIndex, pageSize}){} // fetch who reacted for specific item
  getByUserId(userId, [itemIds]) // array of item ids
}

UI Init

let postReactions = new buildfire.components.reactions({
 itemId, 
 selector, // make sure that selector is valid
 groupName,
 showCount: false, // default false
 showUsersReactions: false, // show who reacted for each reaction
 onReaction :  (event) => {
  event.reactionType, ...
 }
}
<div bf-reactions="{itemId, groupName, showCount, showUsersReactions}"></div>

or

<div bf-reactions-itemid="item-id" bf-reactions-group-name="smileys" bf-reactions-on-reaction=""></div>

buildfire.components.reactions.build(selector)

Guidlines

1. Use of a Debouncer

  • Debounce the call of new buildfire.components.reactions(options) for (50ms) and concat the itemIds into an array that feed ReactionsSummaries.get() and Reactions.getByUserId()
  • Make sure to automatically apply the user events (react or cancel reaction) without waiting for the DB callback. Once the callback is ready we can rollback the reaction state if there is any error.

2. Group Name

  • groupName is optional, if not provided or does not exists load the first available group (default)

3. reactions plugin

  • If $$reactionsGroups does not exists console warn the user to add the Reaction plugin in order to use reactions
  • If ReactionsGroups.get() returned an empty array, warn the user to add at least one reaction group

Events

onReaction(event)

Analytics

We will track each reaction click action

Reactions plugin

In this plugin we will define the reactions groups, and for each group we will define the reactions list inside. The plugin will use AppData, and the created reaction groups could be accessed by any plugin inside the same app.

Implementation

Data Model ReactionsGroup

  • Data will be saved in appData
  • Reserved tag : $$reactionsGroups
  • Model: ReactionsGroup
Class ReactionsGroup{
 groups: [
	name, // should be unique and stored case sensitive | uniqueness check will be case insensitive
	reactions: [ReactionsTypes], // type should be unique only in the same group
	createdBy,
	lastUpdatedBy,
  ]
}

Data Model ReactionsTypes

  • Data will be saved inside ReactionsGroup.reactions
  • Reserved tag : -
  • Model: ReactionsTypes
class ReactionsTypes{
  id, // UUID
  selectedUrl,
  unSelectedUrl, 
  isActive
}

DataAccess ReactionsGroups

class ReactionsGroups {
    get()
    getByName(groupName) // groupName case insensitive
    insert(reactionsGroup) // modify createdBy  
    update(reactionsGroup)  // modify lastUpdatedBy
    delete(groupId)
}

Analytics

  • Register analytics for each reaction type inside insert
  • Don't unregister any event on delete (reaction type could be restored later on so we may be interested to see previous analytics)

Notes

  • Reactions Plugin should be singleton
  • For ReactionsGroups.getByName(groupName) if no group name is provided, or group name does not exists, return null

Clone this wiki locally