Adjust permissions for unclaimed participants

This commit is contained in:
Luke Vella 2022-05-09 08:43:40 +01:00
parent 5c991d7011
commit ccc2896b2d
3 changed files with 31 additions and 24 deletions

View file

@ -13,7 +13,6 @@ import {
CreateCommentPayload,
} from "../../api-client/create-comment";
import { requiredString } from "../../utils/form-validation";
import Badge from "../badge";
import Button from "../button";
import CompactButton from "../compact-button";
import Dropdown, { DropdownItem } from "../dropdown";
@ -24,7 +23,7 @@ import TruncatedLinkify from "../poll/truncated-linkify";
import UserAvatar from "../poll/user-avatar";
import { usePoll } from "../poll-context";
import { usePreferences } from "../preferences/use-preferences";
import { useSession } from "../session";
import { isUnclaimed, useSession } from "../session";
export interface DiscussionProps {
pollId: string;
@ -125,7 +124,9 @@ const Discussion: React.VoidFunctionComponent<DiscussionProps> = ({
<AnimatePresence initial={false}>
{comments.map((comment) => {
const canDelete =
poll.role === "admin" || session.ownsObject(comment);
poll.role === "admin" ||
session.ownsObject(comment) ||
isUnclaimed(comment);
return (
<motion.div

View file

@ -15,11 +15,10 @@ import Trash from "@/components/icons/trash.svg";
import { usePoll } from "@/components/poll-context";
import { requiredString } from "../../utils/form-validation";
import Badge from "../badge";
import Button from "../button";
import { styleMenuItem } from "../menu-styles";
import NameInput from "../name-input";
import { useSession } from "../session";
import { isUnclaimed, useSession } from "../session";
import TimeZonePicker from "../time-zone-picker";
import PollOptions from "./mobile-poll/poll-options";
import TimeSlotOptions from "./mobile-poll/time-slot-options";
@ -66,7 +65,7 @@ const MobilePoll: React.VoidFunctionComponent<PollProps> = ({ pollId }) => {
? participantById[selectedParticipantId]
: undefined;
const [editable, setEditable] = React.useState(false);
const [isEditing, setIsEditing] = React.useState(false);
const [shouldShowSaveButton, setShouldShowSaveButton] = React.useState(false);
const formRef = React.useRef<HTMLFormElement>(null);
@ -129,7 +128,7 @@ const MobilePoll: React.VoidFunctionComponent<PollProps> = ({ pollId }) => {
{
onSuccess: () => {
resolve(data);
setEditable(false);
setIsEditing(false);
},
onError: reject,
},
@ -139,7 +138,7 @@ const MobilePoll: React.VoidFunctionComponent<PollProps> = ({ pollId }) => {
onSuccess: (newParticipant) => {
setSelectedParticipantId(newParticipant.id);
resolve(data);
setEditable(false);
setIsEditing(false);
},
onError: reject,
});
@ -152,13 +151,13 @@ const MobilePoll: React.VoidFunctionComponent<PollProps> = ({ pollId }) => {
<Listbox
value={selectedParticipantId}
onChange={setSelectedParticipantId}
disabled={editable}
disabled={isEditing}
>
<div className="menu min-w-0 grow">
<Listbox.Button
as={Button}
className="w-full"
disabled={!editable}
disabled={!isEditing}
data-testid="participant-selector"
>
<div className="min-w-0 grow text-left">
@ -206,14 +205,16 @@ const MobilePoll: React.VoidFunctionComponent<PollProps> = ({ pollId }) => {
</Listbox.Options>
</div>
</Listbox>
{!poll.closed && !editable ? (
{!poll.closed && !isEditing ? (
selectedParticipant &&
(role === "admin" || session.ownsObject(selectedParticipant)) ? (
(role === "admin" ||
session.ownsObject(selectedParticipant) ||
isUnclaimed(selectedParticipant)) ? (
<div className="flex space-x-3">
<Button
icon={<Pencil />}
onClick={() => {
setEditable(true);
setIsEditing(true);
reset({
name: selectedParticipant.name,
votes: selectedParticipant.votes.map(
@ -241,17 +242,17 @@ const MobilePoll: React.VoidFunctionComponent<PollProps> = ({ pollId }) => {
icon={<PlusCircle />}
onClick={() => {
reset({ name: "", votes: [] });
setEditable(true);
setIsEditing(true);
}}
>
New
</Button>
)
) : null}
{editable ? (
{isEditing ? (
<Button
onClick={() => {
setEditable(false);
setIsEditing(false);
reset();
}}
>
@ -273,7 +274,7 @@ const MobilePoll: React.VoidFunctionComponent<PollProps> = ({ pollId }) => {
<PollOptions
selectedParticipantId={selectedParticipantId}
options={pollContext.options}
editable={editable}
editable={isEditing}
/>
);
case "timeSlot":
@ -281,13 +282,13 @@ const MobilePoll: React.VoidFunctionComponent<PollProps> = ({ pollId }) => {
<TimeSlotOptions
selectedParticipantId={selectedParticipantId}
options={pollContext.options}
editable={editable}
editable={isEditing}
/>
);
}
})()}
<AnimatePresence>
{shouldShowSaveButton && editable ? (
{shouldShowSaveButton && isEditing ? (
<motion.button
type="button"
variants={{
@ -309,7 +310,7 @@ const MobilePoll: React.VoidFunctionComponent<PollProps> = ({ pollId }) => {
) : null}
</AnimatePresence>
<AnimatePresence>
{editable ? (
{isEditing ? (
<motion.div
variants={{
hidden: { opacity: 0, y: -100, height: 0 },

View file

@ -11,14 +11,16 @@ export type SessionProps = {
user: UserSessionData | null;
};
type ParticipantOrComment = {
userId: string | null;
guestId: string | null;
};
type SessionContextValue = {
logout: () => Promise<void>;
user: (UserSessionData & { shortName: string }) | null;
refresh: () => void;
ownsObject: (obj: {
userId: string | null;
guestId: string | null;
}) => boolean;
ownsObject: (obj: ParticipantOrComment) => boolean;
isLoading: boolean;
};
@ -101,3 +103,6 @@ export const withSession = <P extends SessionProps>(
ComposedComponent.displayName = component.displayName;
return ComposedComponent;
};
export const isUnclaimed = (obj: ParticipantOrComment) =>
!obj.guestId && !obj.userId;