import React, { useEffect, useState, useContext, ReactElement } from 'react'; import { Table, Avatar, Button, Tabs } from 'antd'; import { ColumnsType, SortOrder } from 'antd/lib/table/interface'; import format from 'date-fns/format'; import dynamic from 'next/dynamic'; import { ServerStatusContext } from '../../../utils/server-status-context'; import { FOLLOWERS, FOLLOWERS_PENDING, SET_FOLLOWER_APPROVAL, FOLLOWERS_BLOCKED, fetchData, } from '../../../utils/apis'; import { isEmptyObject } from '../../../utils/format'; import { AdminLayout } from '../../../components/layouts/AdminLayout'; // Lazy loaded components const UserAddOutlined = dynamic(() => import('@ant-design/icons/UserAddOutlined'), { ssr: false, }); const UserDeleteOutlined = dynamic(() => import('@ant-design/icons/UserDeleteOutlined'), { ssr: false, }); export interface Follower { link: string; username: string; image: string; name: string; timestamp: Date; approved: Date; } const FollowersTable = ({ data, tableColumns, totalCount, setCurrentPage }) => ( row.link} pagination={{ pageSize: 25, hideOnSinglePage: true, showSizeChanger: false, total: totalCount, }} onChange={pagination => { const page = pagination.current; setCurrentPage(page); }} /> ); export default function FediverseFollowers() { const [followersPending, setFollowersPending] = useState([]); const [followersBlocked, setFollowersBlocked] = useState([]); const [followers, setFollowers] = useState([]); const [totalCount, setTotalCount] = useState(0); const [currentPage, setCurrentPage] = useState(0); const serverStatusData = useContext(ServerStatusContext); const { serverConfig } = serverStatusData || {}; const { federation } = serverConfig; const { isPrivate } = federation; const getFollowers = async () => { try { const limit = 25; const offset = currentPage * limit; const u = `${FOLLOWERS}?offset=${offset}&limit=${limit}`; // Active followers const result = await fetchData(u, { auth: true }); const { results, total } = result; if (isEmptyObject(results)) { setFollowers([]); } else { setTotalCount(total); setFollowers(results); } // Pending follow requests const pendingFollowersResult = await fetchData(FOLLOWERS_PENDING, { auth: true }); if (isEmptyObject(pendingFollowersResult)) { setFollowersPending([]); } else { setFollowersPending(pendingFollowersResult); } // Blocked/rejected followers const blockedFollowersResult = await fetchData(FOLLOWERS_BLOCKED, { auth: true }); if (isEmptyObject(followersBlocked)) { setFollowersBlocked([]); } else { setFollowersBlocked(blockedFollowersResult); } } catch (error) { console.log('==== error', error); } }; useEffect(() => { getFollowers(); }, [currentPage]); const columns: ColumnsType = [ { title: '', dataIndex: 'image', key: 'image', width: 90, render: image => , }, { title: 'Name', dataIndex: 'name', key: 'name', render: (_, follower) => ( {follower.name || follower.username} ), }, { title: 'URL', dataIndex: 'link', key: 'link', render: (_, follower) => ( {follower.link} ), }, ]; async function approveFollowRequest(request) { try { await fetchData(SET_FOLLOWER_APPROVAL, { auth: true, method: 'POST', data: { actorIRI: request.link, approved: true, }, }); // Refetch and update the current data. getFollowers(); } catch (err) { console.error(err); } } async function rejectFollowRequest(request) { try { await fetchData(SET_FOLLOWER_APPROVAL, { auth: true, method: 'POST', data: { actorIRI: request.link, approved: false, }, }); // Refetch and update the current data. getFollowers(); } catch (err) { console.error(err); } } const pendingColumns: ColumnsType = [...columns]; pendingColumns.unshift( { title: 'Approve', dataIndex: null, key: null, render: request => (
row.link} /> ); const blockedTabTitle = ( Blocked {followersBlocked.length > 0 && `(${followersBlocked.length})`} ); const blockedTab = ( <>

The following people were either rejected or blocked by you. You can approve them as a follower.

row.link} />

); const items = [ { label: followersTabTitle, key: '1', children: followersTab }, isPrivate && { label: pendingRequestsTabTitle, key: '2', children: pendingRequestsTab }, { label: blockedTabTitle, key: '3', children: blockedTab }, ]; return (
); } FediverseFollowers.getLayout = function getLayout(page: ReactElement) { return ; };