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

feat: show and highlight current post score

parent ea3c0619
No related branches found
No related tags found
No related merge requests found
Pipeline #1961 passed
...@@ -78,6 +78,38 @@ export const steps = [ ...@@ -78,6 +78,38 @@ export const steps = [
</Chip> </Chip>
. .
</p> </p>
<p>
U příspěvků se též zobrazuje celková míra podpory. Legenda barevného
odlišení je následující:
</p>
<ul className="unordered-list unordered-list--dense">
<li>
<div className="px-1 text-sm font-bold inline-block bg-green-400 text-white">
Zelenou
</div>{" "}
je označen příspěvek, na kterém je konsensus, nebo takový, který
získal podporu skupiny členů.
</li>
<li>
<div className="px-1 text-sm font-bold inline-block bg-yellow-400 text-grey-300">
Žlutou
</div>{" "}
je označen příspěvek, který podporu teprve sbírá.
</li>
<li>
<div className="px-1 text-sm font-bold inline-block bg-red-600 text-white">
Červeně
</div>{" "}
je označen příspěvek, který má spíše negativní odezvu.
</li>
<li>
<div className="px-1 text-sm font-bold inline-block bg-grey-125 text-grey-200">
Šedivě
</div>{" "}
je označen příspěvek, který zatím není ohodnocen.
</li>
</ul>
</div> </div>
</> </>
), ),
......
...@@ -5,6 +5,7 @@ import { format, isToday } from "date-fns"; ...@@ -5,6 +5,7 @@ import { format, isToday } from "date-fns";
import Chip from "components/Chip"; import Chip from "components/Chip";
import { DropdownMenu, DropdownMenuItem } from "components/dropdown-menu"; import { DropdownMenu, DropdownMenuItem } from "components/dropdown-menu";
import PostScore from "components/posts/PostScore";
import Thumbs from "components/Thumbs"; import Thumbs from "components/Thumbs";
const Post = ({ const Post = ({
...@@ -20,6 +21,7 @@ const Post = ({ ...@@ -20,6 +21,7 @@ const Post = ({
state, state,
dimIfArchived = true, dimIfArchived = true,
currentUser, currentUser,
supportThreshold,
canThumb, canThumb,
onLike, onLike,
onDislike, onDislike,
...@@ -82,28 +84,53 @@ const Post = ({ ...@@ -82,28 +84,53 @@ const Post = ({
labels.push( labels.push(
{ {
pending: ( pending: (
<Chip key="state__pending" condensed color="grey-500"> <Chip
key="state__pending"
condensed
color="grey-500"
title="Návrh čekající na zpracování"
>
Čeká na zpracování Čeká na zpracování
</Chip> </Chip>
), ),
announced: ( announced: (
<Chip key="state__announced" condensed color="blue-300"> <Chip
key="state__announced"
condensed
color="blue-300"
title="Návrh k hlasování"
>
K hlasování K hlasování
</Chip> </Chip>
), ),
accepted: ( accepted: (
<Chip key="state__accepted" condensed color="green-400"> <Chip
key="state__accepted"
condensed
color="green-400"
title="Schválený návrh"
>
Schválený Schválený
</Chip> </Chip>
), ),
rejected: ( rejected: (
<Chip key="state__rejected" condensed color="red-600"> <Chip
key="state__rejected"
condensed
color="red-600"
title="Zamítnutý návrh"
>
Zamítnutý Zamítnutý
</Chip> </Chip>
), ),
"rejected-by-chairman": ( "rejected-by-chairman": (
<Chip key="state__rejected-by-chairmen" condensed color="red-600"> <Chip
Zamítnutý předsedajícím key="state__rejected-by-chairmen"
condensed
color="red-600"
title="Návrh zamítnutý předsedajícím"
>
Zamítnutý předs.
</Chip> </Chip>
), ),
}[state] }[state]
...@@ -159,8 +186,7 @@ const Post = ({ ...@@ -159,8 +186,7 @@ const Post = ({
__html: content, __html: content,
}; };
const thumbsEnabled = const thumbsVisible = !archived && (type === "post" || state === "announced");
canThumb && !archived && (type === "post" || state === "announced");
return ( return (
<div className={wrapperClassName} ref={ref}> <div className={wrapperClassName} ref={ref}>
...@@ -177,14 +203,14 @@ const Post = ({ ...@@ -177,14 +203,14 @@ const Post = ({
<span className="font-bold">{author.name}</span> <span className="font-bold">{author.name}</span>
<div className="mt-1 xl:mt-0 xl:ml-2 leading-tight"> <div className="mt-1 xl:mt-0 xl:ml-2 leading-tight">
<span className="text-grey-200 text-sm">{author.group}</span> <span className="text-grey-200 text-sm">{author.group}</span>
<span className="text-grey-200 ml-1 text-sm"> <span className="text-grey-200 ml-1 text-xs">
@{" "} @{" "}
{format( {format(
datetime, datetime,
isToday(datetime) ? "H:mm" : "dd. MM. H:mm" isToday(datetime) ? "H:mm" : "dd. MM. H:mm"
)} )}
{modified && ( {modified && (
<span className="text-grey-200 text-sm block md:inline md:ml-2"> <span className="text-grey-200 text-xs block md:inline md:ml-2">
(upraveno) (upraveno)
</span> </span>
)} )}
...@@ -196,14 +222,23 @@ const Post = ({ ...@@ -196,14 +222,23 @@ const Post = ({
</div> </div>
</div> </div>
<div className="flex items-center"> <div className="flex items-center">
{thumbsVisible && (
<Thumbs <Thumbs
likes={ranking.likes} likes={ranking.likes}
dislikes={ranking.dislikes} dislikes={ranking.dislikes}
readOnly={!thumbsEnabled} readOnly={!canThumb}
onLike={onLike} onLike={onLike}
onDislike={onDislike} onDislike={onDislike}
myVote={ranking.myVote} myVote={ranking.myVote}
/> />
)}
<PostScore
className="ml-2"
score={ranking.score}
hasDislikes={ranking.dislikes > 0}
rankingReadonly={!thumbsVisible}
supportThreshold={supportThreshold}
/>
{showActions && ( {showActions && (
<DropdownMenu right className="pl-4"> <DropdownMenu right className="pl-4">
{showAnnounceAction && ( {showAnnounceAction && (
......
...@@ -8,6 +8,7 @@ const PostList = ({ ...@@ -8,6 +8,7 @@ const PostList = ({
items, items,
showAddPostCta, showAddPostCta,
currentUser, currentUser,
supportThreshold,
canThumb, canThumb,
dimArchived, dimArchived,
onLike, onLike,
...@@ -67,6 +68,7 @@ const PostList = ({ ...@@ -67,6 +68,7 @@ const PostList = ({
archived={item.archived} archived={item.archived}
dimIfArchived={dimArchived} dimIfArchived={dimArchived}
currentUser={currentUser} currentUser={currentUser}
supportThreshold={supportThreshold}
canThumb={canThumb} canThumb={canThumb}
onLike={onPostLike(item)} onLike={onPostLike(item)}
onDislike={onPostDislike(item)} onDislike={onPostDislike(item)}
......
import React from "react";
import classNames from "classnames";
const PostScore = ({
score,
hasDislikes,
supportThreshold,
rankingReadonly,
className,
}) => {
const coloring = rankingReadonly
? "bg-grey-125 text-grey-200"
: {
"bg-red-600 text-white": score < 0,
"bg-grey-125 text-grey-200": score === 0,
"bg-yellow-400 text-grey-300":
score > 0 && hasDislikes && score < supportThreshold,
"bg-green-400 text-white":
score >= supportThreshold || (score > 0 && !hasDislikes),
};
return (
<span
className={classNames(
"p-1 text-sm flex items-center space-x-1",
coloring,
className
)}
title={`Míra podpory je ${score}.`}
>
<i className="ico--power" />
<span className="font-bold">{score}</span>
</span>
);
};
export default React.memo(PostScore);
...@@ -22,7 +22,7 @@ import ModalWithActions from "components/modals/ModalWithActions"; ...@@ -22,7 +22,7 @@ import ModalWithActions from "components/modals/ModalWithActions";
import PostEditModal from "components/posts/PostEditModal"; import PostEditModal from "components/posts/PostEditModal";
import PostList from "components/posts/PostList"; import PostList from "components/posts/PostList";
import { useActionState, useItemActionConfirm } from "hooks"; import { useActionState, useItemActionConfirm } from "hooks";
import { AuthStore, PostStore } from "stores"; import { AuthStore, GlobalInfoStore, PostStore } from "stores";
const PostsContainer = ({ className, showAddPostCta }) => { const PostsContainer = ({ className, showAddPostCta }) => {
const [ const [
...@@ -98,13 +98,18 @@ const PostsContainer = ({ className, showAddPostCta }) => { ...@@ -98,13 +98,18 @@ const PostsContainer = ({ className, showAddPostCta }) => {
archive, archive,
})); }));
const { isAuthenticated, user } = AuthStore.useState(); const { isAuthenticated, user } = AuthStore.useState((state) =>
pick(state, ["isAuthenticated", "user"])
);
const { window, items } = PostStore.useState((state) => const { window, items } = PostStore.useState((state) =>
pick(state, ["window", "items"]) pick(state, ["window", "items"])
); );
const showingArchivedOnly = PostStore.useState( const showingArchivedOnly = PostStore.useState(
(state) => state.filters.flags === "archived" (state) => state.filters.flags === "archived"
); );
const groupSizeHalf = GlobalInfoStore.useState(
(state) => state.groupSizeHalf
);
const [acceptingProposal, acceptingProposalError] = useActionState( const [acceptingProposal, acceptingProposalError] = useActionState(
acceptProposal, acceptProposal,
...@@ -184,6 +189,7 @@ const PostsContainer = ({ className, showAddPostCta }) => { ...@@ -184,6 +189,7 @@ const PostsContainer = ({ className, showAddPostCta }) => {
className={className} className={className}
dimArchived={!showingArchivedOnly} dimArchived={!showingArchivedOnly}
currentUser={user} currentUser={user}
supportThreshold={groupSizeHalf}
onHide={setPostToHide} onHide={setPostToHide}
onBanUser={onBanUser} onBanUser={onBanUser}
onUnbanUser={onUnbanUser} onUnbanUser={onUnbanUser}
......
...@@ -6,6 +6,7 @@ const globalInfoStoreInitial = { ...@@ -6,6 +6,7 @@ const globalInfoStoreInitial = {
connectionState: "connecting", connectionState: "connecting",
onlineMembers: 0, onlineMembers: 0,
onlineUsers: 0, onlineUsers: 0,
groupSizeHalf: null,
websocketUrl: null, websocketUrl: null,
streamUrl: null, streamUrl: null,
protocolUrl: null, protocolUrl: null,
......
...@@ -6,5 +6,8 @@ export const handleOnlineUsersUpdated = (payload) => { ...@@ -6,5 +6,8 @@ export const handleOnlineUsersUpdated = (payload) => {
GlobalInfoStore.update((state) => { GlobalInfoStore.update((state) => {
state.onlineUsers = isNumber(payload.all) ? payload.all : 0; state.onlineUsers = isNumber(payload.all) ? payload.all : 0;
state.onlineMembers = isNumber(payload.members) ? payload.members : 0; state.onlineMembers = isNumber(payload.members) ? payload.members : 0;
state.groupSizeHalf = isNumber(payload.group_size_half)
? payload.group_size_half
: null;
}); });
}; };
declare namespace CF2021 { declare namespace CF2021 {
export interface GlobalInfoStorePayload { export interface GlobalInfoStorePayload {
connectionState: "connected" | "offline" | "connecting"; connectionState: "connected" | "offline" | "connecting";
onlineMembers: number;
onlineUsers: number; onlineUsers: number;
websocketUrl: string; websocketUrl: string;
groupSizeHalf?: number;
streamUrl?: string; streamUrl?: string;
protocolUrl?: string; protocolUrl?: string;
protocol?: string; protocol?: string;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment