Skip to content

Commit

Permalink
Implemented a functional dropdown. State in sync with buttons. (#3)
Browse files Browse the repository at this point in the history
- Implemented a AnnotationTypeDropdown based on the antd dropdown. Notes:
  there is a good likelihood that this can be trimmed and used as a direct
  instance given the experience with it. Also, this needs to be reusable,
  so we may simply fallback into using "Dropdown" directly.
- Tried to set the styling for the dropdown, making a layout with a sidebar
on the left and the video on the right. However, it is currently not working
 as it seems the video is being forced to render ocupying all available
space. This may be forced somewhere in a higher level.
- Added another task instance in the journey, for simple testing.
  • Loading branch information
Kenneth-Funes-TU-Delft authored Feb 22, 2024
1 parent 3b8bab4 commit 9cf3f08
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 32 deletions.
49 changes: 49 additions & 0 deletions covfee/client/input/annotation_type_dropdown.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import React from "react";
import { DownOutlined } from "@ant-design/icons";
import type { MenuProps } from "antd";
import { Dropdown, Menu, Space, MenuInfo } from "antd";

interface AnnotationTypeDropdownProps {
annotation_types: string[];
itemClick: (item: string) => void;
selected_annotation: string;
}

export const AnnotationTypeDropdown: React.FC<AnnotationTypeDropdownProps> = ({
annotation_types,
itemClick,
selected_annotation,
}) => {
console.log("Selected annotation:" + selected_annotation);
const items: MenuProps["items"] = [
{
key: "1",
type: "group",
label: "Action Annotations",
children: annotation_types.map((annotation_type) => ({
key: annotation_type,
label: annotation_type,
onClick: (item: MenuInfo) => {
itemClick(item.key);
},
})),
},
];

return (
<Dropdown menu={{ items }}>
<a
onClick={(e) => {
e.preventDefault();
}}
>
<Space>
{selected_annotation}
<DownOutlined />
</Space>
</a>
</Dropdown>
);
};

export default AnnotationTypeDropdown;
31 changes: 31 additions & 0 deletions covfee/client/tasks/action_annotation/action_annotation.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
.action-annotation-task {
text-align: center;
font-size: calc(10px + 2vmin);
display: flex;
}

.sidebar {
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
width: 20%; /* Adjust as needed */
min-width: 200px; /* Set a minimum width */
background-color: #f0f0f0; /* Example background color */
}

.main-content {
background-color: #ffffff; /* Example background color */
width: 80%;
flex-direction: column;
}

.videoPlayer{
width: 50%;
}

.dropdown{
background-color: red;
}
76 changes: 45 additions & 31 deletions covfee/client/tasks/action_annotation/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,14 @@ import { AllPropsRequired } from "../../types/utils";
import { useDispatch } from "../../journey/state";
import { useSelector } from "react-redux";
import VideojsPlayer from "../../players/videojs";
import AnnotationTypeDropdown from "../../input/annotation_type_dropdown";
import { MenuProps } from "antd";
import styles from "./action_annotation.module.css";

interface Props extends CovfeeTaskProps<ActionAnnotationTaskSpec> {}

const annotation_types: string[] = ["speaking", "laughing"];

const ActionAnnotationTask: React.FC<Props> = (props) => {
// here we set the defaults for the task props
// we could use useMemo to avoid recomputing on every render
Expand Down Expand Up @@ -42,38 +47,47 @@ const ActionAnnotationTask: React.FC<Props> = (props) => {
// and we render the component
return (
<form>
<style jsx>{`
button:disabled {
background-color: darkorange;
}
`}</style>
<div>
<button
id="speaking"
value="speaking"
onClick={() => dispatch(actions.setActiveAnnotation("speaking"))}
disabled={active_annotation == "speaking"}
>
Speaking
</button>
</div>
<div>
<button
id="laughing"
value="laughing"
onClick={() => {
dispatch(actions.setActiveAnnotation("laughing"));
}}
disabled={active_annotation == "laughing"}
>
Laughing
</button>
<div className={styles.action_annotation_task}>
<div className={styles.sidebar}>
<AnnotationTypeDropdown
annotation_types={annotation_types}
itemClick={(item_key: string) =>
dispatch(actions.setActiveAnnotation(item_key))
}
selected_annotation={active_annotation}
/>
<div>
<button
id="speaking"
value="speaking"
onClick={() => dispatch(actions.setActiveAnnotation("speaking"))}
disabled={active_annotation == "speaking"}
>
Speaking
</button>
</div>
<div>
<button
id="laughing"
value="laughing"
onClick={() => {
dispatch(actions.setActiveAnnotation("laughing"));
}}
disabled={active_annotation == "laughing"}
>
Laughing
</button>
</div>
</div>
<div className={styles.main_content}>
<VideojsPlayer
className={styles.videoPlayer}
// {...args.spec.media}
{...my_video}
// onEnded={actions.enableForm}
/>
</div>
</div>
<VideojsPlayer
// {...args.spec.media}
{...my_video}
// onEnded={actions.enableForm}
/>
</form>
);
};
Expand Down
3 changes: 2 additions & 1 deletion samples/action_annotation/action_annotation.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
config.load_environment("local")

my_task_1 = tasks.ActionAnnotationTaskSpec(name="My Task 1", input=None, media=None)
my_task_2 = tasks.ActionAnnotationTaskSpec(name="My Task 1", input=None, media=None)

hit = HIT("Joint counter")
j1 = hit.add_journey(nodes=[my_task_1])
j1 = hit.add_journey(nodes=[my_task_1, my_task_2])

projects = [Project("My Project", email="[email protected]", hits=[hit])]
app = CovfeeApp(projects)

0 comments on commit 9cf3f08

Please sign in to comment.