mirror of
https://github.com/lukevella/rallly.git
synced 2025-07-26 20:57:24 +02:00
Adjust permissions for unclaimed participants
This commit is contained in:
parent
5c991d7011
commit
ccc2896b2d
3 changed files with 31 additions and 24 deletions
|
@ -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
|
||||
|
|
|
@ -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 },
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue