Skip to content

Commit

Permalink
selection footer topic
Browse files Browse the repository at this point in the history
  • Loading branch information
sphinxrave committed Aug 23, 2024
1 parent 4a3f344 commit 24a8bf9
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 31 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import React, { useState } from "react";
import { Button } from "@/shadcn/ui/button";
import { useTranslation } from "react-i18next";
import { useVideoTopicMutation } from "@/services/video.service";
import { useVideoSelection } from "@/hooks/useVideoSelection";
import { TopicPicker } from "@/components/topic/TopicPicker";

const SelectionFooterTopicPicker: React.FC = () => {
const { t } = useTranslation();
const [topic, setTopic] = useState<string | undefined>(undefined);
const { mutate: topicMutate, isPending: topicPending } =
useVideoTopicMutation();
const { selectedVideos } = useVideoSelection();

const handleMultisetTopic = () => {
if (topic) {
selectedVideos.forEach((video) => {
topicMutate({ topicId: topic, videoId: video.id });
});
}
};

return (
<div className="flex w-full items-center space-x-2">
<div className="grow text-sm">
<TopicPicker
value={topic}
onSelect={setTopic}
buttonClass="h-6 text-sm"
/>
</div>
<Button
size="sm"
variant="primary"
disabled={topicPending}
onClick={handleMultisetTopic}
className="whitespace-nowrap"
>
{topicPending && (
<div className="i-lucide:loader-2 mr-2 animate-spin" />
)}
{topic
? t("component.multiset_topic.button", {
videos: selectedVideos.length,
topic: topic ?? "N/A",
})
: t("component.multiset_topic.unset", {
videos: selectedVideos.length,
})}
</Button>
</div>
);
};

export default SelectionFooterTopicPicker;
86 changes: 58 additions & 28 deletions packages/react/src/components/layout/SelectionFooter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { useTranslation } from "react-i18next";
import { makeYtThumbnailUrl } from "@/lib/utils";
import { VideoThumbnail } from "../video/VideoThumbnail";
import { SelectionEditShortcuts } from "../edit/selection/SelectionEditShortcuts";
import SelectionFooterTopicPicker from "../edit/selection/SelectionFooterTopicPicker";
const SelectedVideosModal = ({
isSmall,
open,
Expand Down Expand Up @@ -83,14 +84,14 @@ const SelectionFooter = () => {
/>

<Button
variant="outline"
size="sm"
className={`self-start transition-all ${
selectedVideos.length === 0 ? "h-10 w-10 p-0" : "w-auto"
variant="link"
size="icon"
className={`h-6 self-start transition-all hover:text-primary-10 ${
selectedVideos.length === 0 ? "w-20" : ""
}`}
onClick={exit}
>
<span className="i-mdi:close-circle text-xl" />
<div className="i-mdi:close-circle text-xl" />
</Button>

<div className="ml-4 space-y-2">
Expand All @@ -102,25 +103,29 @@ const SelectionFooter = () => {
variant="base-outline"
size="sm"
onClick={clearSelection}
className="flex items-center"
>
<span className="i-material-symbols:deselect mr-2" />
<span className="i-material-symbols:deselect" />
Deselect
</Button>

<Button
variant="base-outline"
size="sm"
onClick={() => setShowVideos(!showVideos)}
className="flex items-center"
>
<span className="i-mdi:select-search mr-2" />
<span className="i-mdi:select-search" />
Show {selectedVideos.length} Videos
</Button>
</>
)}

<Button variant="ghost" size="sm" disabled={!selectedVideos.length}>
<Button
variant="base-outline"
size="sm"
disabled={!selectedVideos.length}
// TODO: onclick behavior once Multiview is finished.
>
<span className="i-heroicons:rectangle-group" />
Open in Multiview
</Button>

Expand Down Expand Up @@ -181,30 +186,55 @@ const SelectionFooter = () => {
)}

{page !== 0 && (
<div className="text-sm">
<nav className="flex" aria-label="Breadcrumb">
<ol className="inline-flex items-center space-x-1 md:space-x-3">
<li className="inline-flex items-center">
<a
href="#"
className="text-gray-700 hover:text-blue-600"
<div className="flex items-center justify-between">
<nav className="flex items-center" aria-label="Breadcrumb">
<ol className="flex items-center space-x-2 px-2">
<li>
<div
onClick={() => setPage(0)}
className="flex cursor-pointer items-center text-sm font-medium"
>
Selection ({selectedVideos.length})
</a>
</li>
<li>
<div className="flex items-center">
<span className="mx-2 text-gray-400">/</span>
<span className="text-gray-500">
{page === 1 && "Mentions"}
{page === 2 && "Sources"}
{page === 3 && "Topic"}
</span>
<div className="i-lucide:chevron-left mr-1" />
Back
</div>
</li>
<li className="text-sm font-medium text-base-10">
| Selected ({selectedVideos.length}) |
</li>
<li className="text-sm font-medium">
{page === 1 && "Mentions"}
{page === 2 && "Sources"}
{page === 3 && "Set Topic: "}
</li>
</ol>
</nav>
<div className="flex items-center space-x-2">
{page === 1 && (
<>
<input
type="text"
placeholder="Search channels..."
className="rounded-md border px-2 py-1 text-sm"
/>
<Button size="sm" variant="outline">
Add Mention
</Button>
</>
)}
{page === 2 && (
<>
<input
type="text"
placeholder="Enter source URL..."
className="rounded-md border px-2 py-1 text-sm"
/>
<Button size="sm" variant="outline">
Add Source
</Button>
</>
)}
{page === 3 && <SelectionFooterTopicPicker />}
</div>
</div>
)}
</div>
Expand Down
13 changes: 10 additions & 3 deletions packages/react/src/components/topic/TopicPicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,14 @@ const { debouncedValueAtom, currentValueAtom } = atomWithDebounce("", 300);
interface TopicPickerProps {
value?: string;
onSelect: (topicId: string) => void;
buttonClass?: string;
}

export function TopicPicker({ value, onSelect }: TopicPickerProps) {
export function TopicPicker({
value,
onSelect,
buttonClass,
}: TopicPickerProps) {
const [debouncedValue, setDebouncedValue] = useAtom(debouncedValueAtom);
const currentValue = useAtomValue(currentValueAtom);
const { t } = useTranslation();
Expand Down Expand Up @@ -55,7 +60,9 @@ export function TopicPicker({ value, onSelect }: TopicPickerProps) {
role="combobox"
size="lg"
aria-expanded={open}
className="max-w-xs justify-between border-base px-4"
className={
"max-w-xs justify-between border-base px-4" + buttonClass
}
>
{value ?? t("component.topicPicker.pickLabel")}
<div className="i-heroicons:chevron-up-down ml-2 h-4 w-4 shrink-0 opacity-50 " />
Expand Down Expand Up @@ -105,7 +112,7 @@ export function TopicPicker({ value, onSelect }: TopicPickerProps) {
role="combobox"
size="lg"
aria-expanded={open}
className="max-w-xs justify-between border-base px-4"
className={"max-w-xs justify-between border-base px-4 " + buttonClass}
>
{value ?? t("component.topicPicker.pickLabel")}
<div className="i-heroicons:chevron-up-down ml-2 h-4 w-4 shrink-0 opacity-50" />
Expand Down
3 changes: 3 additions & 0 deletions packages/react/src/locales/en/ui.yml
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,9 @@ component:
pickLabel: Pick topics...
queue:
title: Queue
multiset_topic:
button: Set topic '{topic}' for {videos} videos
unset: Clear topic on {videos} videos
views:
channel:
video: Videos
Expand Down

0 comments on commit 24a8bf9

Please sign in to comment.