Skip to content
Snippets Groups Projects
Commit 6ad9e229 authored by xaralis's avatar xaralis
Browse files

feat: properly handle unbanning

parent b90ce7eb
No related branches found
No related tags found
No related merge requests found
...@@ -51,7 +51,7 @@ export const ban = createAsyncAction( ...@@ -51,7 +51,7 @@ export const ban = createAsyncAction(
} }
); );
export const removeBan = createAsyncAction( export const unban = createAsyncAction(
/** /**
* @param {number} userId * @param {number} userId
*/ */
......
...@@ -25,6 +25,7 @@ const Post = ({ ...@@ -25,6 +25,7 @@ const Post = ({
onDislike, onDislike,
onHide, onHide,
onBanUser, onBanUser,
onUnbanUser,
onAnnounceProcedureProposal, onAnnounceProcedureProposal,
onAcceptProcedureProposal, onAcceptProcedureProposal,
onRejectProcedureProposal, onRejectProcedureProposal,
...@@ -131,7 +132,8 @@ const Post = ({ ...@@ -131,7 +132,8 @@ const Post = ({
const showRejectByChairmanAction = const showRejectByChairmanAction =
type === "procedure-proposal" && ["announced", "pending"].includes(state); type === "procedure-proposal" && ["announced", "pending"].includes(state);
const showEditAction = true; const showEditAction = true;
const showBanAction = true; const showBanAction = !author.isBanned;
const showUnbanAction = author.isBanned;
const showHideAction = !archived; const showHideAction = !archived;
const showArchiveAction = !archived; const showArchiveAction = !archived;
...@@ -225,6 +227,13 @@ const Post = ({ ...@@ -225,6 +227,13 @@ const Post = ({
title="Zablokovat uživatele" title="Zablokovat uživatele"
/> />
)} )}
{showUnbanAction && (
<DropdownMenuItem
onClick={onUnbanUser}
icon="ico--lock-open"
title="Odblokovat uživatele"
/>
)}
{showHideAction && ( {showHideAction && (
<DropdownMenuItem <DropdownMenuItem
onClick={onHide} onClick={onHide}
......
...@@ -12,6 +12,7 @@ const PostList = ({ ...@@ -12,6 +12,7 @@ const PostList = ({
onDislike, onDislike,
onHide, onHide,
onBanUser, onBanUser,
onUnbanUser,
onAnnounceProcedureProposal, onAnnounceProcedureProposal,
onAcceptProcedureProposal, onAcceptProcedureProposal,
onRejectProcedureProposal, onRejectProcedureProposal,
...@@ -31,6 +32,7 @@ const PostList = ({ ...@@ -31,6 +32,7 @@ const PostList = ({
const onPostEdit = buildHandler(onEdit); const onPostEdit = buildHandler(onEdit);
const onPostHide = buildHandler(onHide); const onPostHide = buildHandler(onHide);
const onPostBanUser = buildHandler(onBanUser); const onPostBanUser = buildHandler(onBanUser);
const onPostUnbanUser = buildHandler(onUnbanUser);
const onPostArchive = buildHandler(onArchive); const onPostArchive = buildHandler(onArchive);
const onPostAnnounceProcedureProposal = buildHandler( const onPostAnnounceProcedureProposal = buildHandler(
onAnnounceProcedureProposal onAnnounceProcedureProposal
...@@ -69,6 +71,7 @@ const PostList = ({ ...@@ -69,6 +71,7 @@ const PostList = ({
onDislike={onPostDislike(item)} onDislike={onPostDislike(item)}
onHide={onPostHide(item)} onHide={onPostHide(item)}
onBanUser={onPostBanUser(item)} onBanUser={onPostBanUser(item)}
onUnbanUser={onPostUnbanUser(item)}
onAnnounceProcedureProposal={onPostAnnounceProcedureProposal(item)} onAnnounceProcedureProposal={onPostAnnounceProcedureProposal(item)}
onAcceptProcedureProposal={onPostAcceptProcedureProposal(item)} onAcceptProcedureProposal={onPostAcceptProcedureProposal(item)}
onRejectProcedureProposal={onPostRejectProcedureProposal(item)} onRejectProcedureProposal={onPostRejectProcedureProposal(item)}
......
...@@ -14,7 +14,7 @@ import { ...@@ -14,7 +14,7 @@ import {
rejectProposal, rejectProposal,
rejectProposalByChairman, rejectProposalByChairman,
} from "actions/posts"; } from "actions/posts";
import { ban } from "actions/users"; import { ban, unban } from "actions/users";
import ErrorMessage from "components/ErrorMessage"; import ErrorMessage from "components/ErrorMessage";
import ModalConfirm from "components/modals/ModalConfirm"; import ModalConfirm from "components/modals/ModalConfirm";
import PostEditModal from "components/posts/PostEditModal"; import PostEditModal from "components/posts/PostEditModal";
...@@ -33,6 +33,12 @@ const PostsContainer = ({ className }) => { ...@@ -33,6 +33,12 @@ const PostsContainer = ({ className }) => {
onBanUserConfirm, onBanUserConfirm,
onBanUserCancel, onBanUserCancel,
] = useItemActionConfirm(ban); ] = useItemActionConfirm(ban);
const [
userToUnban,
setUserToUnban,
onUnbanUserConfirm,
onUnbanUserCancel,
] = useItemActionConfirm(unban);
const [ const [
postToHide, postToHide,
setPostToHide, setPostToHide,
...@@ -79,6 +85,10 @@ const PostsContainer = ({ className }) => { ...@@ -79,6 +85,10 @@ const PostsContainer = ({ className }) => {
); );
const [banningUser, banningUserError] = useActionState(ban, userToBan); const [banningUser, banningUserError] = useActionState(ban, userToBan);
const [unbanningUser, unbanningUserError] = useActionState(
unban,
userToUnban
);
const [hidingPost, hidingPostError] = useActionState(hide, postToHide); const [hidingPost, hidingPostError] = useActionState(hide, postToHide);
const [archivingPost, archivingPostError] = useActionState( const [archivingPost, archivingPostError] = useActionState(
archive, archive,
...@@ -134,6 +144,13 @@ const PostsContainer = ({ className }) => { ...@@ -134,6 +144,13 @@ const PostsContainer = ({ className }) => {
const onBanUser = (post) => { const onBanUser = (post) => {
setUserToBan(post.author); setUserToBan(post.author);
}; };
/**
* Ban a post's author.
* @param {CF2021.Post} post
*/
const onUnbanUser = (post) => {
setUserToUnban(post.author);
};
const sliceStart = (window.page - 1) * window.perPage; const sliceStart = (window.page - 1) * window.perPage;
const sliceEnd = window.page * window.perPage; const sliceEnd = window.page * window.perPage;
...@@ -157,6 +174,7 @@ const PostsContainer = ({ className }) => { ...@@ -157,6 +174,7 @@ const PostsContainer = ({ className }) => {
dimArchived={!showingArchivedOnly} dimArchived={!showingArchivedOnly}
onHide={setPostToHide} onHide={setPostToHide}
onBanUser={onBanUser} onBanUser={onBanUser}
onUnbanUser={onUnbanUser}
onEdit={setPostToEdit} onEdit={setPostToEdit}
onArchive={setPostToArchive} onArchive={setPostToArchive}
onAnnounceProcedureProposal={setPostToAnnounce} onAnnounceProcedureProposal={setPostToAnnounce}
...@@ -176,6 +194,19 @@ const PostsContainer = ({ className }) => { ...@@ -176,6 +194,19 @@ const PostsContainer = ({ className }) => {
Uživatel <strong>{userToBan ? userToBan.name : null}</strong> bude Uživatel <strong>{userToBan ? userToBan.name : null}</strong> bude
zablokován a nebude dále moci vkládat nové příspěvky. Opravdu to chcete? zablokován a nebude dále moci vkládat nové příspěvky. Opravdu to chcete?
</ModalConfirm> </ModalConfirm>
<ModalConfirm
isOpen={!!userToUnban}
onConfirm={onUnbanUserConfirm}
onCancel={onUnbanUserCancel}
confirming={unbanningUser}
error={unbanningUserError}
title={`Odblokovat uživatele ${userToUnban ? userToUnban.name : null}?`}
yesActionLabel="Odblokovat"
>
Uživatel <strong>{userToUnban ? userToUnban.name : null}</strong> bude
odblokován a bude mu opět umožněno přidávat nové příspěvky. Opravdu to
chcete?
</ModalConfirm>
<ModalConfirm <ModalConfirm
isOpen={!!postToHide} isOpen={!!postToHide}
onConfirm={onPostHideConfirm} onConfirm={onPostHideConfirm}
......
...@@ -126,7 +126,11 @@ export const announcementTypeMappingRev = { ...@@ -126,7 +126,11 @@ export const announcementTypeMappingRev = {
*/ */
export const parseRawPost = (rawPost) => { export const parseRawPost = (rawPost) => {
const post = { const post = {
...pick(rawPost, ["id", "content", "author"]), ...pick(rawPost, ["id", "content"]),
author: {
...pick(rawPost.author, ["id", "name", "username", "group"]),
isBanned: rawPost.author.is_banned === 1,
},
contentHtml: markdownConverter.makeHtml(rawPost.content), contentHtml: markdownConverter.makeHtml(rawPost.content),
datetime: parse(rawPost.datetime, "yyyy-MM-dd HH:mm:ss", new Date()), datetime: parse(rawPost.datetime, "yyyy-MM-dd HH:mm:ss", new Date()),
historyLog: rawPost.history_log, historyLog: rawPost.history_log,
......
import has from "lodash/has";
import WaitQueue from "wait-queue"; import WaitQueue from "wait-queue";
import { GlobalInfoStore } from "stores"; import { GlobalInfoStore } from "stores";
...@@ -20,13 +19,6 @@ function Worker() { ...@@ -20,13 +19,6 @@ function Worker() {
try { try {
const data = JSON.parse(event.data); const data = JSON.parse(event.data);
// Special message, TODO: fix
if (has(data, "online_users")) {
return GlobalInfoStore.update((state) => {
state.onlineUsers = data["online_users"];
});
}
if (!data.event) { if (!data.event) {
return console.error("[ws][worker] Missing `event` field"); return console.error("[ws][worker] Missing `event` field");
} }
......
import isNumber from "lodash/isNumber";
import { GlobalInfoStore } from "stores";
export const handleOnlineUsersUpdated = (onlineUserCount) => {
GlobalInfoStore.update((state) => {
state.onlineUsers = isNumber(onlineUserCount) ? onlineUserCount : 0;
});
};
...@@ -3,6 +3,7 @@ import { ...@@ -3,6 +3,7 @@ import {
handleAnnouncementCreated, handleAnnouncementCreated,
handleAnnouncementDeleted, handleAnnouncementDeleted,
} from "./announcements"; } from "./announcements";
import { handleOnlineUsersUpdated } from "./global";
import { import {
handlePostChanged, handlePostChanged,
handlePostCreated, handlePostCreated,
...@@ -23,4 +24,5 @@ export const handlers = { ...@@ -23,4 +24,5 @@ export const handlers = {
program_entry_changed: handleProgramEntryChanged, program_entry_changed: handleProgramEntryChanged,
user_banned: handleUserBanned, user_banned: handleUserBanned,
user_unbanned: handleUserUnbanned, user_unbanned: handleUserUnbanned,
online_users_updated: handleOnlineUsersUpdated,
}; };
import { AuthStore } from "stores"; import { AuthStore, PostStore } from "stores";
export const handleUserBanned = (payload) => { export const handleUserBanned = (payload) => {
AuthStore.update((state) => { AuthStore.update((state) => {
...@@ -6,6 +6,14 @@ export const handleUserBanned = (payload) => { ...@@ -6,6 +6,14 @@ export const handleUserBanned = (payload) => {
state.user.isBanned = true; state.user.isBanned = true;
} }
}); });
PostStore.update((state) => {
Object.keys(state.items).forEach((key) => {
if (state.items[key].author.id === payload.id) {
state.items[key].author.isBanned = true;
}
});
});
}; };
export const handleUserUnbanned = (payload) => { export const handleUserUnbanned = (payload) => {
...@@ -14,4 +22,12 @@ export const handleUserUnbanned = (payload) => { ...@@ -14,4 +22,12 @@ export const handleUserUnbanned = (payload) => {
state.user.isBanned = false; state.user.isBanned = false;
} }
}); });
PostStore.update((state) => {
Object.keys(state.items).forEach((key) => {
if (state.items[key].author.id === payload.id) {
state.items[key].author.isBanned = false;
}
});
});
}; };
...@@ -88,6 +88,7 @@ declare namespace CF2021 { ...@@ -88,6 +88,7 @@ declare namespace CF2021 {
name: string; name: string;
username: string; username: string;
group: string; group: string;
isBanned: boolean;
}; };
type: PostType; type: PostType;
content: string; content: string;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment