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(
}
);
export const removeBan = createAsyncAction(
export const unban = createAsyncAction(
/**
* @param {number} userId
*/
......
......@@ -25,6 +25,7 @@ const Post = ({
onDislike,
onHide,
onBanUser,
onUnbanUser,
onAnnounceProcedureProposal,
onAcceptProcedureProposal,
onRejectProcedureProposal,
......@@ -131,7 +132,8 @@ const Post = ({
const showRejectByChairmanAction =
type === "procedure-proposal" && ["announced", "pending"].includes(state);
const showEditAction = true;
const showBanAction = true;
const showBanAction = !author.isBanned;
const showUnbanAction = author.isBanned;
const showHideAction = !archived;
const showArchiveAction = !archived;
......@@ -225,6 +227,13 @@ const Post = ({
title="Zablokovat uživatele"
/>
)}
{showUnbanAction && (
<DropdownMenuItem
onClick={onUnbanUser}
icon="ico--lock-open"
title="Odblokovat uživatele"
/>
)}
{showHideAction && (
<DropdownMenuItem
onClick={onHide}
......
......@@ -12,6 +12,7 @@ const PostList = ({
onDislike,
onHide,
onBanUser,
onUnbanUser,
onAnnounceProcedureProposal,
onAcceptProcedureProposal,
onRejectProcedureProposal,
......@@ -31,6 +32,7 @@ const PostList = ({
const onPostEdit = buildHandler(onEdit);
const onPostHide = buildHandler(onHide);
const onPostBanUser = buildHandler(onBanUser);
const onPostUnbanUser = buildHandler(onUnbanUser);
const onPostArchive = buildHandler(onArchive);
const onPostAnnounceProcedureProposal = buildHandler(
onAnnounceProcedureProposal
......@@ -69,6 +71,7 @@ const PostList = ({
onDislike={onPostDislike(item)}
onHide={onPostHide(item)}
onBanUser={onPostBanUser(item)}
onUnbanUser={onPostUnbanUser(item)}
onAnnounceProcedureProposal={onPostAnnounceProcedureProposal(item)}
onAcceptProcedureProposal={onPostAcceptProcedureProposal(item)}
onRejectProcedureProposal={onPostRejectProcedureProposal(item)}
......
......@@ -14,7 +14,7 @@ import {
rejectProposal,
rejectProposalByChairman,
} from "actions/posts";
import { ban } from "actions/users";
import { ban, unban } from "actions/users";
import ErrorMessage from "components/ErrorMessage";
import ModalConfirm from "components/modals/ModalConfirm";
import PostEditModal from "components/posts/PostEditModal";
......@@ -33,6 +33,12 @@ const PostsContainer = ({ className }) => {
onBanUserConfirm,
onBanUserCancel,
] = useItemActionConfirm(ban);
const [
userToUnban,
setUserToUnban,
onUnbanUserConfirm,
onUnbanUserCancel,
] = useItemActionConfirm(unban);
const [
postToHide,
setPostToHide,
......@@ -79,6 +85,10 @@ const PostsContainer = ({ className }) => {
);
const [banningUser, banningUserError] = useActionState(ban, userToBan);
const [unbanningUser, unbanningUserError] = useActionState(
unban,
userToUnban
);
const [hidingPost, hidingPostError] = useActionState(hide, postToHide);
const [archivingPost, archivingPostError] = useActionState(
archive,
......@@ -134,6 +144,13 @@ const PostsContainer = ({ className }) => {
const onBanUser = (post) => {
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 sliceEnd = window.page * window.perPage;
......@@ -157,6 +174,7 @@ const PostsContainer = ({ className }) => {
dimArchived={!showingArchivedOnly}
onHide={setPostToHide}
onBanUser={onBanUser}
onUnbanUser={onUnbanUser}
onEdit={setPostToEdit}
onArchive={setPostToArchive}
onAnnounceProcedureProposal={setPostToAnnounce}
......@@ -176,6 +194,19 @@ const PostsContainer = ({ className }) => {
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?
</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
isOpen={!!postToHide}
onConfirm={onPostHideConfirm}
......
......@@ -126,7 +126,11 @@ export const announcementTypeMappingRev = {
*/
export const parseRawPost = (rawPost) => {
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),
datetime: parse(rawPost.datetime, "yyyy-MM-dd HH:mm:ss", new Date()),
historyLog: rawPost.history_log,
......
import has from "lodash/has";
import WaitQueue from "wait-queue";
import { GlobalInfoStore } from "stores";
......@@ -20,13 +19,6 @@ function Worker() {
try {
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) {
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 {
handleAnnouncementCreated,
handleAnnouncementDeleted,
} from "./announcements";
import { handleOnlineUsersUpdated } from "./global";
import {
handlePostChanged,
handlePostCreated,
......@@ -23,4 +24,5 @@ export const handlers = {
program_entry_changed: handleProgramEntryChanged,
user_banned: handleUserBanned,
user_unbanned: handleUserUnbanned,
online_users_updated: handleOnlineUsersUpdated,
};
import { AuthStore } from "stores";
import { AuthStore, PostStore } from "stores";
export const handleUserBanned = (payload) => {
AuthStore.update((state) => {
......@@ -6,6 +6,14 @@ export const handleUserBanned = (payload) => {
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) => {
......@@ -14,4 +22,12 @@ export const handleUserUnbanned = (payload) => {
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 {
name: string;
username: string;
group: string;
isBanned: boolean;
};
type: PostType;
content: string;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment