Adding popover to flag text with labels

This commit is contained in:
BitterKanegul
2022-12-31 08:35:33 +05:30
parent 4841550cd4
commit dfcbbee444
3 changed files with 189 additions and 4 deletions
+182
View File
@@ -0,0 +1,182 @@
import poster from "src/lib/poster";
import {
Popover,
useBoolean,
PopoverAnchor,
Button,
PopoverTrigger,
PopoverContent,
PopoverBody,
Checkbox,
PopoverCloseButton,
PopoverArrow,
Flex,
Spacer,
Slider,
SliderTrack,
SliderFilledTrack,
SliderThumb,
} from "@chakra-ui/react";
import useSWRMutation from "swr/mutation";
import { QuestionMarkCircleIcon, FlagIcon } from "@heroicons/react/20/solid";
import {useState } from "react";
import { SubmitButton } from "./Buttons/Submit";
export type TextFlagProps = {
text: string;label_map
post_id:string;
};
type FlagRefs={
label: string;
value:number;
setValue;
isChecked:boolean;
setChecked;
};
export const FlaggableElement = (props) => {
const [isEditing, setIsEditing] = useBoolean();
const [hasCheck, setHasCheck] = useBoolean();
const { trigger, isMutating } = useSWRMutation("/api/v1/text_labels", poster, {
onSuccess: () => {
setIsEditing.off;
},
});
const submitResponse = (label_data) => {
trigger(label_data);
};
const label_refs:FlagRefs[] = TEXT_LABEL_FLAGS.map((flag) =>{
const [isChecked, setChecked] = useState(false);
const [value, setValue] = useState(1);
return({label:flag.attributeName, value:value, setValue:setValue, isChecked:isChecked, setChecked:setChecked});
});
const fetchData = () =>{
let label_map:Map<string, number> =new Map();
label_refs.filter((flagRef) => (flagRef.isChecked)).map((refs) =>{
label_map.set(refs.label, refs.value)
});
console.log(label_map);
return {post_id:props.post_id, label_map:Object.fromEntries(label_map), text:props.text}
}
return (
<Popover isOpen={isEditing} onOpen={setIsEditing.on} onClose={setIsEditing.off} closeOnBlur={false} isLazy lazyBehavior="keepMounted">
<div className="inline-block float-left">
<PopoverAnchor>
{props.children}
</PopoverAnchor>
<PopoverTrigger>
<Button h="20px" >
<FlagIcon className="h-5 w-5 ml-3 text-gray-400 group-hover:text-gray-500" aria-hidden="true" />
</Button>
</PopoverTrigger>
</div>
<PopoverContent width="fit-content">
<PopoverArrow />
<PopoverCloseButton />
<div className="flex mt-3 ">
<PopoverBody>
<ul>
{TEXT_LABEL_FLAGS.map((option, i) => {
return (
<FlagCheckboxLi
option={option}
key={i}
state={label_refs[i]}
></FlagCheckboxLi>
);
})}
</ul>
<div className="flex justify-center ml-auto">
<Button onClick={() => submitResponse(fetchData())} className="bg-indigo-600 text-black hover:bg-indigo-700">
Report
</Button>
</div>
</PopoverBody>
</div>
</PopoverContent>
</Popover>
);
};
function FlagCheckboxLi(props: { option: textFlagLabels, state:FlagRefs}): JSX.Element {
let AdditionalExplanation = null;
if (props.option.additionalExplanation) {
AdditionalExplanation = (
<a href="#" className="group flex items-center space-x-2.5 text-sm ">
<QuestionMarkCircleIcon className="flex h-5 w-5 ml-3 text-gray-400 group-hover:text-gray-500" aria-hidden="true" />
</a>
);
}
return (
<>
<li>
<Flex>
<Checkbox onChange={(e) => {props.state.setChecked(e.target.checked);}}/>
<label className=" ml-1 mr-1 text-sm form-check-label hover:cursor-pointer" htmlFor={props.option.attributeName}>
<span className="text-gray-800 hover:text-blue-700 float-left">
{props.option.labelText}
</span>
{AdditionalExplanation}
</label>
<Spacer />
<Slider width="100px" isDisabled={!props.state.isChecked} defaultValue={100} onChangeEnd={(val) => {props.state.setValue(val/100);}}>
<SliderTrack>
<SliderFilledTrack />
<SliderThumb />
</SliderTrack>
</Slider>
</Flex>
</li>
</>
);
}
interface textFlagLabels {
attributeName: string;
labelText: string;
additionalExplanation?: string;
}
const TEXT_LABEL_FLAGS: textFlagLabels[] = [
// For the time being this list is configured on the FE.
// In the future it may be provided by the API.
{
attributeName: "fails_task",
labelText: "Fails to follow the correct instruction / task",
additionalExplanation: "__TODO__",
},
{
attributeName: "not_customer_assistant_appropriate",
labelText: "Inappropriate for customer assistant",
additionalExplanation: "__TODO__",
},
{
attributeName: "contains_sexual_content",
labelText: "Contains sexual content",
},
{
attributeName: "contains_violent_content",
labelText: "Contains violent content",
},
{
attributeName: "encourages_violence",
labelText: "Encourages or fails to discourage violence/abuse/terrorism/self-harm",
},
{
attributeName: "denigrates_a_protected_class",
labelText: "Denigrates a protected class",
},
{
attributeName: "gives_harmful_advice",
labelText: "Fails to follow the correct instruction / task",
additionalExplanation:
"The advice given in the output is harmful or counter-productive. This may be in addition to, but is distinct from the question about encouraging violence/abuse/terrorism/self-harm.",
},
{
attributeName: "expresses_moral_judgement",
labelText: "Expresses moral judgement",
},
];
+6 -2
View File
@@ -1,3 +1,5 @@
import { FlaggableElement } from "./FlaggableElement";
export interface Message {
text: string;
is_assistant: boolean;
@@ -5,12 +7,14 @@ export interface Message {
const getColor = (isAssistant: boolean) => (isAssistant ? "bg-slate-800" : "bg-sky-900");
export const Messages = ({ messages }: { messages: Message[] }) => {
export const Messages = ({ messages , post_id}: { messages: Message[] , post_id:string}) => {
const items = messages.map(({ text, is_assistant }: Message, i: number) => {
return (
<div key={i + text} className={`${getColor(is_assistant)} p-4 my-1 rounded-xl text-white whitespace-pre-wrap`}>
<FlaggableElement text={text} post_id={post_id}>
<div key={i + text} className={`${getColor(is_assistant)} p-4 my-1 rounded-xl text-white whitespace-pre-wrap float-left mr-3`}>
{text}
</div>
</FlaggableElement>
);
});
// Maybe also show a legend of the colors?
+1 -2
View File
@@ -61,7 +61,7 @@ const UserReply = () => {
<>
<h5 className="text-lg font-semibold">Reply as a user</h5>
<p className="text-lg py-1">Given the following conversation, provide an adequate reply</p>
<Messages messages={task.conversation.messages} />
<Messages messages={task.conversation.messages} post_id={task.id}/>
{task.hint && <p className="text-lg py-1">Hint: {task.hint}</p>}
</>
<Textarea name="reply" placeholder="Reply..." ref={inputRef} />
@@ -69,7 +69,6 @@ const UserReply = () => {
<section className="mb-8 p-4 rounded-lg shadow-lg bg-white flex flex-row justify-items-stretch ">
<TaskInfo id={tasks[0].id} output="Submit your answer" />
<Flex justify="center" ml="auto" gap={2}>
<SkipButton>Skip</SkipButton>
{endTask.task.type !== "task_done" ? (