import React, { useRef, useState, useEffect } from 'react'; import PropTypes from 'prop-types'; import urlParse from 'url-parse'; import { deleteRequest, csrfToken } from '../../../utils/helpers/'; import { usePopup } from '../../../utils/hooks/'; import { PopupMain } from '../../_shared'; import { PendingItemsList } from '../../item-list/PendingItemsList.jsx'; import { renderManageItems } from './includes/functions'; import initManageItemsList from './includes/initManageItemsList'; import { ManageItemsListHandler } from './includes/ManageItemsListHandler'; import { translateString } from '../../../utils/helpers/'; import './ManageItemList.scss'; function useManageItemList(props, itemsListRef) { let previousItemsLength = 0; let itemsListInstance = null; const [items, setItems] = useState([]); const [countedItems, setCountedItems] = useState(false); const [listHandler, setListHandler] = useState(null); function onItemsLoad(itemsArray) { setItems([...itemsArray]); } function onItemsCount(totalItems) { setCountedItems(true); if (void 0 !== props.itemsCountCallback) { props.itemsCountCallback(totalItems); } } function addListItems() { if (previousItemsLength < items.length) { if (null === itemsListInstance) { itemsListInstance = initManageItemsList([itemsListRef.current])[0]; } // FIXME: Should get item elements from children components. const itemsElem = itemsListRef.current.querySelectorAll('.item'); if (!itemsElem || !itemsElem.length) { return; } let i = previousItemsLength; while (i < items.length) { itemsListInstance.appendItems(itemsElem[i]); i += 1; } previousItemsLength = items.length; } } useEffect(() => { if (void 0 !== props.itemsLoadCallback) { props.itemsLoadCallback(); } }, [items]); return [items, countedItems, listHandler, setListHandler, onItemsLoad, onItemsCount, addListItems]; } function useManageItemListSync(props) { const itemsListRef = useRef(null); const itemsListWrapperRef = useRef(null); const [items, countedItems, listHandler, setListHandler, onItemsLoad, onItemsCount, addListItems] = useManageItemList( { ...props, itemsCountCallback }, itemsListRef ); const [totalItems, setTotalItems] = useState(null); let classname = { list: 'manage-items-list', listOuter: 'items-list-outer' + ('string' === typeof props.className ? ' ' + props.className.trim() : ''), }; function onClickLoadMore() { listHandler.loadItems(); } function itemsCountCallback(itemsSumm) { setTotalItems(itemsSumm); } function afterItemsLoad() {} function renderBeforeListWrap() { return null; } function renderAfterListWrap() { if (!listHandler) { return null; } return 1 > listHandler.totalPages() || listHandler.loadedAllItems() ? null : ( ); } useEffect(() => { addListItems(); afterItemsLoad(); }, [items]); return [ countedItems, totalItems, items, listHandler, setListHandler, classname, itemsListWrapperRef, itemsListRef, onItemsCount, onItemsLoad, renderBeforeListWrap, renderAfterListWrap, ]; } function pageUrlQuery(baseQuery, pageNumber) { let queryParams = []; let pos = 0; if ('' !== baseQuery) { queryParams = baseQuery.split('?')[1].split('&'); let param; let i = 0; while (i < queryParams.length) { param = queryParams[i].split('='); if ('page' === param[0]) { pos = i; break; } i += 1; } } queryParams[pos] = 'page=' + pageNumber; return '?' + queryParams.join('&'); } function pageUrl(parsedUrl, query) { return parsedUrl.set('query', query).href; } function BulkActions(props) { const [popupContentRef, PopupContent, PopupTrigger] = usePopup(); const [selectedBulkAction, setSelectedBulkAction] = useState(''); const [selectedItemsSize, setSelectedItemsSize] = useState(props.selectedItemsSize); function onBulkActionSelect(ev) { setSelectedBulkAction(ev.currentTarget.value); } function onClickProceed() { if ('function' === typeof props.onProceedRemoval) { props.onProceedRemoval(); } popupContentRef.current.tryToHide(); } function onClickCancel() { popupContentRef.current.tryToHide(); } useEffect(() => { setSelectedItemsSize(props.selectedItemsSize); }, [props.selectedItemsSize]); return (
{!selectedItemsSize || !selectedBulkAction ? null : ( )}
Bulk removal You're willing to remove selected items permanently?

); } function ManageItemsOptions(props) { return (
{1 === props.pagesSize ? null : (
)}
); } function PaginationButtons(props) { const buttons = []; let i; let maxPagin = 11; const newPagesNumber = { last: Math.ceil(props.totalItems / props.pageItems), current: 1, }; if ('' !== props.query) { const queryParams = props.query.split('?')[1].split('&'); let param; let i = 0; while (i < queryParams.length) { param = queryParams[i].split('='); if ('page' === param[0]) { newPagesNumber.current = parseInt(param[1], 10); break; } i += 1; } } const paginButtonsData = paginationButtonsList(maxPagin, newPagesNumber); i = 0; while (i < paginButtonsData.length) { if ('button' === paginButtonsData[i].type) { buttons.push( ); } else if ('dots' === paginButtonsData[i].type) { buttons.push( ... ); } i += 1; } return buttons; } function paginationButtonsList(maxPagin, pagesNumber) { if (3 > maxPagin) { maxPagin = 3; } let i; let maxCurr; let maxEdge = 1; if (maxPagin >= pagesNumber.last) { maxPagin = pagesNumber.last; maxCurr = pagesNumber.last; maxEdge = 0; } else { if (5 < maxPagin) { if (7 >= maxPagin) { maxEdge = 2; } else { maxEdge = Math.floor(maxPagin / 4); } } maxCurr = maxPagin - 2 * maxEdge; } const currentArr = []; const firstArr = []; const lastArr = []; if (pagesNumber.current <= maxCurr + maxEdge - pagesNumber.current) { i = 1; while (i <= maxCurr + maxEdge) { currentArr.push(i); i += 1; } i = pagesNumber.last - maxPagin + currentArr.length + 1; while (i <= pagesNumber.last) { lastArr.push(i); i += 1; } } else if (pagesNumber.current > pagesNumber.last - (maxCurr + maxEdge - 1)) { i = pagesNumber.last - (maxCurr + maxEdge - 1); while (i <= pagesNumber.last) { currentArr.push(i); i += 1; } i = 1; while (i <= maxPagin - currentArr.length) { firstArr.push(i); i += 1; } } else { currentArr.push(pagesNumber.current); i = 1; while (maxCurr > currentArr.length) { currentArr.push(pagesNumber.current + i); if (maxCurr === currentArr.length) { break; } currentArr.unshift(pagesNumber.current - i); i += 1; } i = 1; while (i <= maxEdge) { firstArr.push(i); i += 1; } i = pagesNumber.last - (maxPagin - (firstArr.length + currentArr.length) - 1); while (i <= pagesNumber.last) { lastArr.push(i); i += 1; } } const ret = []; i = 0; while (i < firstArr.length) { ret.push({ type: 'button', number: firstArr[i], }); i += 1; } if (firstArr.length && currentArr.length && firstArr[firstArr.length - 1] + 1 < currentArr[0]) { ret.push({ type: 'dots', }); } i = 0; while (i < currentArr.length) { ret.push({ type: 'button', number: currentArr[i], }); i += 1; } if (currentArr.length && lastArr.length && currentArr[currentArr.length - 1] + 1 < lastArr[0]) { ret.push({ type: 'dots', }); } i = 0; while (i < lastArr.length) { ret.push({ type: 'button', number: lastArr[i], }); i += 1; } return ret; } export function ManageItemList(props) { const [ countedItems, totalItems, items, listHandler, setListHandler, classname, itemsListWrapperRef, itemsListRef, onItemsCount, onItemsLoad, ] = useManageItemListSync(props); const [selectedItems, setSelectedItems] = useState([]); const [selectedAllItems, setSelectedAllItems] = useState(false); const [parsedRequestUrl, setParsedRequestUrl] = useState(null); const [parsedRequestUrlQuery, setParsedRequestUrlQuery] = useState(null); function onPageButtonClick(ev) { const clickedPageUrl = pageUrl( parsedRequestUrl, pageUrlQuery(parsedRequestUrlQuery, ev.currentTarget.getAttribute('page')) ); if ('function' === typeof props.onPageChange) { props.onPageChange(clickedPageUrl, ev.currentTarget.getAttribute('page')); } } function onBulkItemsRemoval() { deleteSelectedItems(); } function onAllRowsCheck(selectedAllRows, tableType) { const newSelected = []; if (selectedAllRows) { if (items.length !== selectedItems.length) { let entry; if ('media' === tableType) { for (entry of items) { newSelected.push(entry.friendly_token); } } else if ('users' === tableType) { for (entry of items) { newSelected.push(entry.username); } } else if ('comments' === tableType) { for (entry of items) { newSelected.push(entry.uid); } } } } setSelectedItems(newSelected); setSelectedAllItems(newSelected.length === items.length); } function onRowCheck(token, isSelected) { if (void 0 !== token) { let newSelected; if (-1 === selectedItems.indexOf(token)) { if (isSelected) { newSelected = [...selectedItems, token]; setSelectedItems(newSelected); setSelectedAllItems(newSelected.length === items.length); } } else { if (!isSelected) { newSelected = []; let entry; for (entry of selectedItems) { if (token !== entry) { newSelected.push(entry); } } setSelectedItems(newSelected); setSelectedAllItems(newSelected.length === items.length); } } } } function removeBulkMediaResponse(response) { if (response && 204 === response.status) { setSelectedItems([]); setSelectedAllItems(false); if ('function' === typeof props.onRowsDelete) { props.onRowsDelete(true); } } } function removeBulkMediaFail() { if ('function' === typeof props.onRowsDeleteFail) { props.onRowsDeleteFail(true); } } function deleteItem(token, isManageComments) { deleteRequest( props.requestUrl.split('?')[0] + ('comments' === props.manageType ? '?comment_ids=' : '?tokens=') + token, { headers: { 'X-CSRFToken': csrfToken(), }, tokens: token, }, false, removeMediaResponse, removeMediaFail ); } function deleteSelectedItems() { deleteRequest( props.requestUrl.split('?')[0] + ('comments' === props.manageType ? '?comment_ids=' : '?tokens=') + selectedItems.join(','), { headers: { 'X-CSRFToken': csrfToken(), }, }, false, removeBulkMediaResponse, removeBulkMediaFail ); } function removeMediaResponse(response) { if (response && 204 === response.status) { props.onRowsDelete(false); } } function removeMediaFail() { props.onRowsDeleteFail(false); } useEffect(() => { if (parsedRequestUrl) { setParsedRequestUrlQuery(parsedRequestUrl.query); } }, [parsedRequestUrl]); useEffect(() => { setParsedRequestUrl(urlParse(props.requestUrl)); }, [props.requestUrl]); useEffect(() => { setListHandler( new ManageItemsListHandler(props.pageItems, props.maxItems, props.requestUrl, onItemsCount, onItemsLoad) ); return () => { if (listHandler) { listHandler.cancelAll(); setListHandler(null); } }; }, []); return !countedItems ? ( ) : !items.length ? null : (
{renderManageItems(items, { ...props, onAllRowsCheck: onAllRowsCheck, onRowCheck: onRowCheck, selectedItems: selectedItems, selectedAllItems: selectedAllItems, onDelete: deleteItem, })}
); } ManageItemList.defaultProps = { itemsCountCallback: PropTypes.func, maxItems: PropTypes.number.isRequired, pageItems: PropTypes.number.isRequired, requestUrl: PropTypes.string.isRequired, onPageChange: PropTypes.func, onRowsDelete: PropTypes.func, onRowsDeleteFail: PropTypes.func, pageItems: 24, }; ManageItemList.defaultProps = { maxItems: 99999, pageItems: 24, requestUrl: null, };