@selfcommunity/react-core
Version:
React Core Components useful for integrating UI Community components (react-ui).
253 lines (251 loc) • 10.7 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const react_1 = require("react");
const api_services_1 = require("@selfcommunity/api-services");
const types_1 = require("@selfcommunity/types");
const useSCCachingManager_1 = tslib_1.__importDefault(require("./useSCCachingManager"));
const Errors_1 = require("../constants/Errors");
const utils_1 = require("@selfcommunity/utils");
const SCPreferencesProvider_1 = require("../components/provider/SCPreferencesProvider");
const Notification_1 = require("../constants/Notification");
const Preferences_1 = require("../constants/Preferences");
const use_deep_compare_effect_1 = require("use-deep-compare-effect");
const pubsub_js_1 = tslib_1.__importDefault(require("pubsub-js"));
/**
:::info
This custom hook is used to manage the groups followed.
:::
:::tip How to use it:
Follow these steps:
```jsx
1. const scUserContext: SCUserContextType = useSCUser();
2. const scSubscribedGroupsManager: SCSubscribedGroupsManagerType = scUserContext.manager.groups;
3. scSubscribedGroupsManager.isSubscribed(group)
```
:::
*/
function useSCSubscribedGroupsManager(user) {
const { cache, updateCache, emptyCache, data, setData, loading, setLoading, setUnLoading, isLoading } = (0, useSCCachingManager_1.default)();
const { preferences, features } = (0, SCPreferencesProvider_1.useSCPreferences)();
const authUserId = user ? user.id : null;
const groupsEnabled = (0, react_1.useMemo)(() => preferences &&
features &&
features.includes(types_1.SCFeatureName.TAGGING) &&
features.includes(types_1.SCFeatureName.GROUPING) &&
Preferences_1.CONFIGURATIONS_GROUPS_ENABLED in preferences &&
preferences[Preferences_1.CONFIGURATIONS_GROUPS_ENABLED].value, [preferences, features]);
const notificationInvitedToJoinGroup = (0, react_1.useRef)(null);
const notificationAddedToGroup = (0, react_1.useRef)(null);
/**
* Subscribe to notification types user_follow, user_unfollow
*/
(0, use_deep_compare_effect_1.useDeepCompareEffectNoCheck)(() => {
notificationInvitedToJoinGroup.current = pubsub_js_1.default.subscribe(`${types_1.SCNotificationTopicType.INTERACTION}.${types_1.SCNotificationTypologyType.USER_INVITED_TO_JOIN_GROUP}`, notificationSubscriber);
notificationAddedToGroup.current = pubsub_js_1.default.subscribe(`${types_1.SCNotificationTopicType.INTERACTION}.${types_1.SCNotificationTypologyType.USER_ADDED_TO_GROUP}`, notificationSubscriber);
return () => {
pubsub_js_1.default.unsubscribe(notificationInvitedToJoinGroup.current);
pubsub_js_1.default.unsubscribe(notificationAddedToGroup.current);
};
}, [data]);
/**
* Notification subscriber handler
* @param msg
* @param dataMsg
*/
const notificationSubscriber = (msg, dataMsg) => {
var _a;
if (dataMsg.data.group !== undefined) {
let _status;
switch (Notification_1.SCNotificationMapping[dataMsg.data.activity_type]) {
case types_1.SCNotificationTypologyType.USER_INVITED_TO_JOIN_GROUP:
_status = types_1.SCGroupSubscriptionStatusType.INVITED;
break;
case types_1.SCNotificationTypologyType.USER_ADDED_TO_GROUP:
if (dataMsg.data.notification_obj.group && ((_a = dataMsg.data.notification_obj.group.paywalls) === null || _a === void 0 ? void 0 : _a.length)) {
_status = types_1.SCGroupSubscriptionStatusType.PAYMENT_WAITING;
}
else {
_status = types_1.SCGroupSubscriptionStatusType.SUBSCRIBED;
}
break;
}
updateCache([dataMsg.data.group]);
setData((prev) => getDataUpdated(prev, dataMsg.data.group, _status));
}
};
/**
* Memoized refresh all groups
* It makes a single request to the server and retrieves
* all the groups followed by the user in a single solution
* It might be useful for multi-tab sync
*/
const refresh = (0, react_1.useMemo)(() => () => {
emptyCache();
if (user) {
// Only if user is authenticated
api_services_1.http
.request({
url: api_services_1.Endpoints.GetUserSubscribedGroups.url({ id: user.id }),
method: api_services_1.Endpoints.GetUserSubscribedGroups.method,
})
.then((res) => {
if (res.status >= 300) {
return Promise.reject(res);
}
const groupsIds = res.data.results.map((g) => g.id);
updateCache(groupsIds);
setData(res.data.results.map((g) => ({ [g.id]: g.subscription_status })));
return Promise.resolve(res.data);
})
.catch((e) => {
utils_1.Logger.error(Errors_1.SCOPE_SC_CORE, 'Unable to refresh the authenticated user groups.');
utils_1.Logger.error(Errors_1.SCOPE_SC_CORE, e);
});
}
}, [data, user, cache]);
/**
* Memoized subscribe Group
* Toggle action
*/
const subscribe = (0, react_1.useMemo)(() => (group) => {
setLoading(group.id);
return api_services_1.http
.request({
url: api_services_1.Endpoints.SubscribeToGroup.url({ id: group.id }),
method: api_services_1.Endpoints.SubscribeToGroup.method,
})
.then((res) => {
if (res.status >= 300) {
return Promise.reject(res);
}
updateCache([group.id]);
setData((prev) => getDataUpdated(prev, group.id, group.privacy === types_1.SCGroupPrivacyType.PRIVATE && group.subscription_status !== types_1.SCGroupSubscriptionStatusType.INVITED
? types_1.SCGroupSubscriptionStatusType.REQUESTED
: types_1.SCGroupSubscriptionStatusType.SUBSCRIBED));
setUnLoading(group.id);
return Promise.resolve(res.data);
});
}, [data, loading, cache]);
/**
* Memoized subscribe Group
* Toggle action
*/
const unsubscribe = (0, react_1.useMemo)(() => (group) => {
if (data[group.id] !== types_1.SCGroupSubscriptionStatusType.REQUESTED) {
setLoading(group.id);
return api_services_1.http
.request({
url: api_services_1.Endpoints.UnsubscribeFromGroup.url({ id: group.id }),
method: api_services_1.Endpoints.UnsubscribeFromGroup.method,
})
.then((res) => {
if (res.status >= 300) {
return Promise.reject(res);
}
updateCache([group.id]);
setData((prev) => getDataUpdated(prev, group.id, null));
setUnLoading(group.id);
return Promise.resolve(res.data);
});
}
}, [data, loading, cache]);
/**
* Check the authenticated user subscription status to the group
* Update the groups cached
* Update groups subscription statuses
* @param group
*/
const checkGroupSubscriptionStatus = (group) => {
setLoading(group.id);
return api_services_1.http
.request({
url: api_services_1.Endpoints.GetGroupSubscriptionStatus.url({ id: group.id }),
method: api_services_1.Endpoints.GetGroupSubscriptionStatus.method,
})
.then((res) => {
if (res.status >= 300) {
return Promise.reject(res);
}
setData((prev) => getDataUpdated(prev, group.id, res.data.status));
updateCache([group.id]);
setUnLoading(group.id);
return Promise.resolve(res.data);
})
.catch((e) => {
setUnLoading(group.id);
return Promise.reject(e);
});
};
/**
* Get updated data
* @param data
* @param groupId
* @param subscriptionStatus
*/
const getDataUpdated = (data, groupId, subscriptionStatus) => {
const _index = data.findIndex((k) => parseInt(Object.keys(k)[0]) === groupId);
let _data;
if (_index < 0) {
_data = [...data, ...[{ [groupId]: subscriptionStatus }]];
}
else {
_data = data.map((k, i) => {
if (parseInt(Object.keys(k)[0]) === groupId) {
return { [Object.keys(k)[0]]: subscriptionStatus };
}
return { [Object.keys(k)[0]]: data[i][Object.keys(k)[0]] };
});
}
return _data;
};
/**
* Return current group subscription status if exists,
* otherwise return null
*/
const getCurrentGroupCacheStatus = (0, react_1.useMemo)(() => (group) => {
const d = data.filter((k) => parseInt(Object.keys(k)[0]) === group.id);
return d.length ? d[0][group.id] : !data.length ? group.subscription_status : null;
}, [data]);
/**
* Bypass remote check if the group is subscribed
*/
const getSubscriptionStatus = (0, react_1.useMemo)(() => (group) => {
updateCache([group.id]);
setData((prev) => getDataUpdated(prev, group.id, group.subscription_status));
return group.subscription_status;
}, [data, cache]);
/**
* Memoized subscriptionStatus
* If group is already in cache -> check if the group is in groups,
* otherwise, check if user subscribe the group
*/
const subscriptionStatus = (0, react_1.useMemo)(() => (group) => {
// Cache is valid also for anonymous user
if (cache.includes(group.id)) {
return getCurrentGroupCacheStatus(group);
}
if (authUserId && group) {
if ('subscription_status' in group) {
return getSubscriptionStatus(group);
}
if (!isLoading(group)) {
checkGroupSubscriptionStatus(group);
}
}
return null;
}, [loading, cache, authUserId, getSubscriptionStatus, getCurrentGroupCacheStatus]);
/**
* Empty cache on logout
*/
(0, react_1.useEffect)(() => {
if (!authUserId) {
emptyCache();
}
}, [authUserId]);
if (!groupsEnabled || !user) {
return { groups: data, loading, isLoading };
}
return { groups: data, loading, isLoading, subscribe, unsubscribe, subscriptionStatus, refresh, emptyCache };
}
exports.default = useSCSubscribedGroupsManager;
;