-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Updating project documentation (#81)
- Loading branch information
1 parent
4561414
commit 2d273b8
Showing
6 changed files
with
253 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# Aura LWC wrappers | ||
Aura components are used in the project as an exception and only in cases when Aura wrapper is necessary for LWC due to some of the API not being ported to LWC yet. For example - `GameForceUtility` aura compoenent is a wrapper for `gameForceNotification` LWC component due to the fact that `lightning:utilityBarAPI` isn't available in LWC yet. | ||
|
||
## GameForceUtility | ||
### General information | ||
`GameForceUtility` is an Aura wrapper for `gameForceNotification` LWC component. It is necessary because `lightning:utilityBarAPI` API which is available in Aura components wasn't ported yet to LWC. | ||
|
||
### Technical design | ||
`GameForceUtility` is built around two APIs: `lightning:empApi` and `lightning:utilityBarAPI` | ||
- `lightning:empApi` is used to intercept [`AchievementReached__c`](../force-app/main/default/objects/AchievementReached__e/) platform events and to open the utility bar component without user input in case the intercepted event includes information about current user. See the [`GameForceUtility.cmp onInit()`](../force-app/main/default/aura/GameForceUtility/GameForceUtilityController.js) method for more information | ||
- `lightning:utilityBarAPI` is used to open the utility bar component automatically when new event is received and includes data relevant for current user | ||
|
||
All data processing and rendering is done in a child [gameForceNotification](../force-app/main/default/lwc/gameForceNotification/) LWC component |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
# Apex guidelines | ||
All the backend logic of GameForce is done using Apex Classes. Low-code tools are not used for development. | ||
This section is meant to explain some key concepts that are utilized across the GameForce code. | ||
|
||
## Using BaseSelector class to retrieve data instead of direct SOQL request | ||
GameForce relies on [`BaseSelector`](../../force-app/main/default/classes/BaseSelector.cls) class to retrieve data for different sObjects. Concreate realizations of the BaseSelector class are used to retrieve data for a specific sObject | ||
|
||
To create a concrete realization of a BaseSelector class, child class has to realize 3 methods: | ||
- `public String sObjectApiName()`: this method should return the API name of the sObject | ||
- `public override Set<String> fieldApiNames()`: returns a list of field API names that will be retrieved by Selector class | ||
|
||
`BaseSelector` class provides a set of methods that can be used to retrieve data without the need to create additional methods on the concrete selector class: | ||
### getByFieldValue(String filterFieldApiName, String compOperator, Object values) | ||
``` | ||
public List<sObject> getByFieldValue(String filterFieldApiName, String compOperator, Object values) | ||
``` | ||
|
||
Parameters: | ||
- `filterFieldApiName`: API name of the field that is going to be used for filtering SOQL request | ||
- `compOperator`: Comparison operator for data filtering | ||
- `values`: a value (set of values) that will be used for filtering data | ||
|
||
Example: | ||
``` | ||
getByFieldValue('Name', 'IN', new Set<String>{'Name 1', 'Name 2', 'Name 3'}) | ||
``` | ||
equals to this SOQL | ||
``` | ||
Set<String> names = new Set<String>{'Name 1', 'Name 2', 'Name 3'} | ||
[...WHERE Name IN :names] | ||
``` | ||
|
||
### getByIds(Set<Id> ids) | ||
``` | ||
public List<sObject> getByIds(Set<Id> ids) | ||
``` | ||
Parameters: | ||
- `ids`: API name of the field that is going to be used for filtering SOQL request | ||
|
||
Example: | ||
``` | ||
getByIds(new Set<Id>{'Id1', 'Id2', 'Id3'}) | ||
``` | ||
equals to this SOQL | ||
``` | ||
Set<Id> ids = new Set<Id>{'Id1', 'Id2', 'Id3'} | ||
[...WHERE Id IN :ids] | ||
``` | ||
|
||
### getAll() | ||
``` | ||
public List<sObject> getAll() | ||
``` | ||
|
||
Example: | ||
``` | ||
getAll() | ||
``` | ||
equals to this SOQL | ||
``` | ||
[SELECT ... FROM ... ] | ||
``` | ||
This method should be used with caution since it doesn't have any limitation and can result in SOQL query limit | ||
|
||
## Using Logger class to save information about exceptions | ||
`Logger` class is used to save information about issues that might have occured in a system. This class will be refined in future to allow storing more granular information about the issues. | ||
|
||
There are two main method of a Logger class that are used for storing runtime issues: | ||
### saveSingleLog(String log) | ||
``` | ||
public static void saveSingleLog(String log) | ||
``` | ||
Stores a single issue in a `Log__c` sObject. Asyncronous and can be called from cached LWC methods. | ||
Example: | ||
``` | ||
} catch (Exception e) { | ||
Logger.saveSingleLog('Error message'); | ||
} | ||
``` | ||
### addLog(String log) | ||
``` | ||
public void addLog(String log) | ||
``` | ||
Adds a new log record, but doesn't commit changes. `commitChanges()` has to be called once all issues are collected | ||
|
||
## Using ControllerResponse class to pass result of Apex controller to LWC components | ||
`ControllerResponse` class is used to wrap the result of the execution of backend controller and have a more control over the issues (expected and unexpected) that might occure during the backend controller execution. | ||
|
||
There are 3 methods that should be used to return result of a backend controller execution in a form of `Map<String, Object>`: | ||
|
||
### success(Object obj) | ||
``` | ||
public static Map<String, Object> success(Object obj) | ||
``` | ||
Example: | ||
``` | ||
@AuraEnabled(cacheable=true) | ||
public static Map<String, Object> method(){ | ||
... | ||
return ControllerResponse.success('value to pass to LWC'); | ||
} | ||
``` | ||
|
||
### error(String msg) | ||
``` | ||
public static Map<String, Object> error(String msg) | ||
``` | ||
Example: | ||
``` | ||
@AuraEnabled(cacheable=true) | ||
public static Map<String, Object> method(){ | ||
Map<String, Object> result = new Map<String, Object>(); | ||
try { | ||
... | ||
return ControllerResponse.success('value to pass to LWC'); | ||
} catch (Exception e) { | ||
... | ||
result = ControllerResponse.error('error message displayed to user'); | ||
} | ||
return result; | ||
} | ||
``` | ||
|
||
### warning(Object msg) | ||
``` | ||
public static Map<String, Object> warning(Object msg) | ||
``` | ||
Example: | ||
``` | ||
@AuraEnabled(cacheable=true) | ||
public static Map<String, Object> method(){ | ||
Map<String, Object> result = new Map<String, Object>(); | ||
try { | ||
if (all good) { | ||
return ControllerResponse.success('value to pass to LWC'); | ||
} else { | ||
return ControllerResponse.success('Handled issue'); | ||
} | ||
} catch (Exception e) { | ||
... | ||
result = ControllerResponse.error('error message displayed to user'); | ||
} | ||
return result; | ||
} | ||
``` | ||
|
||
## Trigger Handlers | ||
TBD |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
# GameForce data schema | ||
This section is meant to explain some key concepts related to data storage and relathionships between sObjects in GameForce. | ||
|
||
## Updating data in sObjects | ||
One key concept is that needs explanation is that in GameForce all the data should be either changed from the UI (by GameForce [admins](PERMISSIONSETSANDGROUPS.md)), or indirectly by firing a specific [platform event](PLATFORMEVENTS.md). | ||
|
||
## Measurement__c and UserMeasurement__c sObjects | ||
`Measurement__c` sObjects stores metrics that are tracked for each individual user, like "Number of converted leads". Specific values per each user are stored in `UserMeasurement__c` sObject. | ||
```mermaid | ||
classDiagram | ||
Measurement__c <|-- UserMeasurement__c | ||
User <|-- UserMeasurement__c | ||
class Measurement__c{ | ||
+UniqueIdentifier__c | ||
+Description__c | ||
} | ||
class UserMeasurement__c{ | ||
+Key__c, formula: User__c + Measurement__c | ||
+Measurement__c, lookup(Measurement__c) | ||
+User__c, lookup(User) | ||
Value__c | ||
} | ||
class User{ | ||
+Id | ||
} | ||
``` | ||
|
||
## Achievement__c sObject | ||
`Achievement__c` sObject stores achievements that are related to specific measurements. Achievement is considred to be reached by user once the value in a corresponding `UserMeasurement__c` record reaches or becomes greater then the value in `Achievement.Goal__c` sObject | ||
|
||
```mermaid | ||
classDiagram | ||
Measurement__c <|-- UserMeasurement__c | ||
Measurement__c <|-- Achievement__c | ||
class Measurement__c{ | ||
+UniqueIdentifier__c | ||
+Description__c | ||
} | ||
class UserMeasurement__c{ | ||
+Key__c, formula: User__c + Measurement__c | ||
+Measurement__c, lookup(Measurement__c) | ||
Value__c | ||
} | ||
class Achievement__c{ | ||
+Measurement__c, master-detail(Measurement__c) | ||
+Goal__c | ||
} | ||
``` | ||
|
||
This comparison is executed each time `UserMeasurement__c` is created or changed. [`AchievementReachedEventsManager`](../force-app/main/default/classes/AchievementReachedEventsManager.cls) does the comparison and checks if achievement was already reached by the user. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
# Permission Sets and Groups | ||
GameForce relies on on two main permission set groups to give users access to the functionality: | ||
|
||
## GameForce Admin | ||
Gives full access to a GameForce app including "Measurements" and "Achievements" tab so that admin users can setup new measurements and/or achievements | ||
|
||
NOTE: This permission set is meant to be assigned to user during the development of new functionality | ||
|
||
## GameForce User | ||
Gives access to main functionality of GameForce but doesn't include access to configuration of the achievements and measurements | ||
|
||
NOTE: All new functionality has to be tested using the user with this permission set group to make sure that regular users can properly use the GameForce |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# GameForce Platform events | ||
GameForce relies on platfomr events to track changes in user measurements as well as notifying users about unlocked achievements. Platform events are used as a means for integration with the logic outside of the GameForce and obfuscate complex data changes/validations that are required for GameForce to properly track users progress | ||
|
||
## AchievementReached__e | ||
`AchievementReached__e` platform event is fired whenever user reaches a specific achievement. | ||
|
||
Payload: | ||
- `AchievementId__c`: Id from `Achievement__c` sObject | ||
- `UserId__c`: User Id | ||
|
||
Whenever `AchievementReached__e` platform event is fired, `GameForceUtility` aura component handles the event, and shows a pop-up notification to a user, in case his user id matches the one in eent payload. | ||
Also, `AchievementReachedTrigger` fires a logic that stores the information about reached achievement in `AchievementReached__c` sObject. | ||
|
||
## UserMeasurementIncrement__e | ||
`UserMeasurementIncrement__e` platform event is fired whenever there has to be a change of user metric. It is meant to be fired by sObject triggers for a standard list of achievements, or by flows/triggers in case custom achievements are set in a system. | ||
|
||
Payload: | ||
- `MeasurementId__c`: Id from `Measurement__c` sObject that needs to be changed | ||
- `UserId__c`: User Id | ||
- `Increment__c`: numeric value that needs to be added/removed from a `UserMeasurement__c` sObject record |