@chayns-components/person-finder
Version:
A set of beautiful React components for developing your own applications with chayns.
334 lines (332 loc) • 12.7 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.usePersonFinder = exports.default = exports.PersonFinderContext = void 0;
var _react = _interopRequireWildcard(require("react"));
var _lodash = _interopRequireDefault(require("lodash.throttle"));
var _personFinder = require("../types/personFinder");
var _get = require("../api/friends/get");
var _post = require("../api/friends/post");
var _delete = require("../api/friends/delete");
var _personFinder2 = require("../utils/personFinder");
var _uac = require("../utils/uac");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
const THROTTLE_INTERVAL = 500;
const PersonFinderContext = exports.PersonFinderContext = /*#__PURE__*/(0, _react.createContext)({
data: undefined,
updateData: undefined,
friends: undefined,
addFriend: undefined,
removeFriend: undefined,
activeFilter: undefined,
updateActiveFilter: undefined,
search: undefined,
updateSearch: undefined,
loadMore: undefined,
loadingState: undefined,
updateLoadingState: undefined,
tags: undefined,
setTags: undefined
});
PersonFinderContext.displayName = 'PersonFinderContext';
const usePersonFinder = () => (0, _react.useContext)(PersonFinderContext);
exports.usePersonFinder = usePersonFinder;
const PersonFinderProvider = ({
children,
friendsPriority,
filterTypes,
defaultEntries,
excludedEntryIds,
shouldShowOwnUser = false,
uacFilter
}) => {
const [data, setData] = (0, _react.useState)();
const [friends, setFriends] = (0, _react.useState)();
const [uacUsers, setUacUsers] = (0, _react.useState)();
const [activeFilter, setActiveFilter] = (0, _react.useState)();
const [search, setSearch] = (0, _react.useState)('');
const [tags, setTags] = (0, _react.useState)((defaultEntries === null || defaultEntries === void 0 ? void 0 : defaultEntries.map(({
id,
name
}) => ({
id,
text: name
}))) ?? []);
const [loadingState, setLoadingState] = (0, _react.useState)({
[_personFinder.PersonFinderFilterTypes.PERSON]: _personFinder.LoadingState.None,
[_personFinder.PersonFinderFilterTypes.SITE]: _personFinder.LoadingState.None
});
const dataRef = (0, _react.useRef)();
const updateActiveFilter = (0, _react.useCallback)(filter => {
setActiveFilter(filter);
}, []);
const updateData = (0, _react.useCallback)((key, newData) => {
setData(prevState => ({
...prevState,
[key]: newData
}));
}, []);
const appendData = (0, _react.useCallback)((key, newData) => {
setData(prevState => {
var _prevState$key, _prevState$key2;
const oldEntries = prevState && (_prevState$key = prevState[key]) !== null && _prevState$key !== void 0 && _prevState$key.entries ? (_prevState$key2 = prevState[key]) === null || _prevState$key2 === void 0 ? void 0 : _prevState$key2.entries : [];
return {
...prevState,
[key]: {
...newData,
entries: [...oldEntries, ...newData.entries]
}
};
});
}, []);
const updateLoadingState = (0, _react.useCallback)((key, state) => {
setLoadingState(prev => ({
...prev,
[key]: state
}));
}, []);
const updateSearch = (0, _react.useCallback)(value => {
setSearch(value);
}, []);
const loadMore = (0, _react.useCallback)(key => {
updateLoadingState(key, _personFinder.LoadingState.Pending);
const current = data === null || data === void 0 ? void 0 : data[key];
if (!current) {
updateLoadingState(key, _personFinder.LoadingState.Error);
return;
}
void (0, _personFinder2.loadData)({
searchString: search ?? '',
filter: [key],
skipMap: {
[key]: current.skip
}
}).then(result => {
const newData = result === null || result === void 0 ? void 0 : result[key];
if (newData) {
appendData(key, newData);
}
}).finally(() => {
updateLoadingState(key, _personFinder.LoadingState.Success);
});
}, [updateLoadingState, data, search, appendData]);
const addFriend = (0, _react.useCallback)(personId => {
void (0, _post.postFriends)(personId).then(result => {
if (result) {
const {
firstName,
lastName,
verificationState
} = result;
setFriends(prev => [...(prev ?? []), {
id: personId,
isVerified: verificationState === 1,
commonSites: 0,
firstName,
lastName,
type: _personFinder.PersonFinderFilterTypes.PERSON
}]);
}
});
}, []);
const removeFriend = (0, _react.useCallback)(personId => {
void (0, _delete.deleteFriends)(personId).then(wasSuccessful => {
if (wasSuccessful) {
setFriends(prev => prev === null || prev === void 0 ? void 0 : prev.filter(({
id
}) => id !== personId));
}
});
}, []);
(0, _react.useEffect)(() => {
if (!filterTypes.includes(_personFinder.PersonFinderFilterTypes.PERSON)) {
return;
}
void (0, _get.getFriends)().then(result => {
if (result) {
setFriends(result.map(({
personId,
firstName,
lastName,
verificationState
}) => ({
lastName,
firstName,
id: personId,
commonSites: 0,
isVerified: verificationState === 1,
type: _personFinder.PersonFinderFilterTypes.PERSON
})));
}
});
}, [filterTypes]);
const latestArgsRef = (0, _react.useRef)(null);
const latestHandledRequestRef = (0, _react.useRef)(0);
const throttledRequest = (0, _react.useRef)((0, _lodash.default)(async () => {
const args = latestArgsRef.current;
if (!args) return;
const {
search: searchString,
filter
} = args;
const requestTimestamp = Date.now();
filter.forEach(key => {
updateLoadingState(key, _personFinder.LoadingState.Pending);
});
const result = await (0, _personFinder2.loadData)({
searchString,
filter,
skipMap: {}
});
if (requestTimestamp < latestHandledRequestRef.current) {
return;
}
latestHandledRequestRef.current = requestTimestamp;
if (!result) return;
Object.entries(result).forEach(([keyString, value]) => {
const key = keyString;
if (key === _personFinder.PersonFinderFilterTypes.PERSON && friendsPriority === _personFinder.Priority.HIGH && friends) {
const friendIds = new Set(friends.map(f => f.id));
const serverFriendEntries = value.entries.filter(entry => friendIds.has(entry.id));
const serverFriendIds = new Set(serverFriendEntries.map(f => f.id));
const missingFriends = friends.filter(f => !serverFriendIds.has(f.id)).filter(f => {
var _f$firstName, _f$lastName;
return ((_f$firstName = f.firstName) === null || _f$firstName === void 0 ? void 0 : _f$firstName.toLowerCase().includes(searchString.toLowerCase())) || ((_f$lastName = f.lastName) === null || _f$lastName === void 0 ? void 0 : _f$lastName.toLowerCase().includes(searchString.toLowerCase()));
});
const otherEntries = value.entries.filter(entry => !friendIds.has(entry.id));
updateData(key, {
...value,
entries: [...serverFriendEntries, ...missingFriends, ...otherEntries]
});
} else {
updateData(key, value);
}
updateLoadingState(key, value.entries.length === 0 ? _personFinder.LoadingState.Error : _personFinder.LoadingState.Success);
});
}, THROTTLE_INTERVAL, {
leading: false,
trailing: true
})).current;
(0, _react.useEffect)(() => {
dataRef.current = data;
}, [data]);
const searchData = (0, _react.useCallback)(({
filter
}) => {
const tmpData = dataRef.current;
filter.forEach(key => {
updateLoadingState(key, _personFinder.LoadingState.Pending);
if (tmpData && tmpData[key]) {
// Add all Types that are not searched by a request
const entries = tmpData[key].entries;
const filteredEntries = entries.filter(({
name
}) => name.toLowerCase().includes(search.toLowerCase()));
updateData(key, {
entries: filteredEntries,
searchString: search,
count: filteredEntries.length,
skip: filteredEntries.length
});
updateLoadingState(key, filteredEntries.length === 0 ? _personFinder.LoadingState.Error : _personFinder.LoadingState.Success);
}
});
}, [search, updateData, updateLoadingState]);
const searchLocal = (0, _react.useCallback)(() => {
if (search.length < 3) {
return;
}
updateLoadingState(_personFinder.PersonFinderFilterTypes.PERSON, _personFinder.LoadingState.Pending);
const searchedUsers = [];
uacUsers === null || uacUsers === void 0 || uacUsers.forEach(entry => {
if (entry.firstName.toLowerCase().includes(search.toLowerCase()) || entry.lastName.toLowerCase().includes(search.toLowerCase()) || entry.id.toLowerCase().includes(search.toLowerCase())) {
searchedUsers.push(entry);
}
});
updateData(_personFinder.PersonFinderFilterTypes.PERSON, {
entries: searchedUsers,
searchString: search,
count: searchedUsers.length,
skip: searchedUsers.length
});
updateLoadingState(_personFinder.PersonFinderFilterTypes.PERSON, searchedUsers.length === 0 ? _personFinder.LoadingState.Error : _personFinder.LoadingState.Success);
}, [search, uacUsers, updateData, updateLoadingState]);
(0, _react.useEffect)(() => {
if (!search) return;
const active = activeFilter ?? filterTypes;
if (uacFilter) {
searchLocal();
} else if (active !== null && active !== void 0 && active.includes(_personFinder.PersonFinderFilterTypes.UAC)) {
searchData({
filter: [_personFinder.PersonFinderFilterTypes.UAC]
});
} else {
latestArgsRef.current = {
search,
filter: active
};
throttledRequest();
}
}, [filterTypes, search, activeFilter, friends, friendsPriority, updateData, updateLoadingState, throttledRequest, searchData, uacFilter, searchLocal]);
(0, _react.useEffect)(() => () => {
throttledRequest.cancel();
}, [throttledRequest]);
// load initial data
(0, _react.useEffect)(() => {
if (uacFilter) {
void (0, _uac.getUsersByGroups)(uacFilter).then(users => {
setUacUsers(users);
});
return;
}
if (filterTypes.includes(_personFinder.PersonFinderFilterTypes.UAC) && search === '') {
void (0, _uac.getUACGroups)().then(result => {
setData({
uac: {
entries: result,
searchString: '',
skip: result.length,
count: result.length
}
});
});
}
if (friendsPriority === _personFinder.Priority.HIGH && filterTypes.includes(_personFinder.PersonFinderFilterTypes.PERSON) && friends && search === '') {
setData({
person: {
entries: friends,
searchString: '',
skip: friends.length,
count: friends.length
}
});
}
}, [filterTypes, friends, friendsPriority, search, uacFilter]);
const providerValue = (0, _react.useMemo)(() => ({
data: (0, _personFinder2.filterDataByKeys)(data, activeFilter, {
excludedEntryIds,
shouldShowOwnUser
}),
updateData,
activeFilter,
updateActiveFilter,
friends,
addFriend,
removeFriend,
search,
updateSearch,
loadMore,
loadingState,
updateLoadingState,
setTags,
tags
}), [activeFilter, addFriend, data, excludedEntryIds, friends, loadMore, loadingState, removeFriend, search, shouldShowOwnUser, tags, updateActiveFilter, updateData, updateLoadingState, updateSearch]);
return /*#__PURE__*/_react.default.createElement(PersonFinderContext.Provider, {
value: providerValue
}, children);
};
PersonFinderProvider.displayName = 'PersonFinderProvider';
var _default = exports.default = PersonFinderProvider;
//# sourceMappingURL=PersonFinderProvider.js.map