Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add: Dashboard Missing Ep+Tmdb Link Shortcuts / Collection Tag Links and Sticky Searchbar+Sidebars #1093

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/components/Collection/Filter/FilterSidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ const FilterSidebar = () => {
return (
<ShokoPanel
title="Filter"
className="ml-8 w-full"
className="sticky top-24 ml-6 !h-[calc(100vh-18rem)] w-full"
harshithmohan marked this conversation as resolved.
Show resolved Hide resolved
contentClassName="gap-y-6"
options={<Options showModal={showCriteriaModal(true)} />}
>
Expand Down
2 changes: 1 addition & 1 deletion src/components/Collection/Group/EditGroupTabs/NameTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ const NameTab = React.memo(({ groupId }: Props) => {
<div className="shoko-scrollbar flex grow flex-col gap-y-2 overflow-y-auto bg-panel-input pr-4">
{seriesData?.map(series => (
<div
className="flex justify-between last:border-none hover:text-panel-text-primary"
className="flex justify-between transition-colors last:border-none hover:text-panel-text-primary"
key={series.IDs.ID}
onClick={() => setGroupName(series.Name)}
>
Expand Down
52 changes: 32 additions & 20 deletions src/components/Collection/ListViewItem.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useMemo } from 'react';
import { useDispatch } from 'react-redux';
import { Link } from 'react-router-dom';
import { Link, useNavigate } from 'react-router-dom';
import {
mdiAlertCircleOutline,
mdiCalendarMonthOutline,
Expand All @@ -17,11 +17,14 @@ import { reduce } from 'lodash';

import BackgroundImagePlaceholderDiv from '@/components/BackgroundImagePlaceholderDiv';
import { listItemSize } from '@/components/Collection/constants';
import Button from '@/components/Input/Button';
import { useSeriesTagsQuery } from '@/core/react-query/series/queries';
import { useSettingsQuery } from '@/core/react-query/settings/queries';
import { resetFilter, setFilterTag } from '@/core/slices/collection';
import { setGroupId } from '@/core/slices/modals/editGroup';
import { setSeriesId } from '@/core/slices/modals/editSeries';
import { dayjs, formatThousand } from '@/core/util';
import { addFilterCriteriaToStore } from '@/core/utilities/filter';
import useEventCallback from '@/hooks/useEventCallback';
import useMainPoster from '@/hooks/useMainPoster';

Expand All @@ -45,17 +48,29 @@ const renderFileSources = (sources: SeriesSizesFileSourcesType): string => {
return output.join(' | ');
};

const SeriesTag = ({ text, type }: { text: string, type: 'AniDB' | 'User' }) => (
<div
className={cx(
'text-xs font-semibold flex gap-x-2 items-center border-2 border-panel-tags rounded-lg p-2 whitespace-nowrap capitalize',
type === 'User' ? 'text-panel-text-important' : 'text-panel-text-primary',
)}
>
<Icon path={mdiTagTextOutline} size="1rem" />
<span className="text-panel-text">{text}</span>
</div>
);
const SeriesTag = React.memo(({ text, type }: { text: string, type: 'User' | 'AniDB' }) => {
const dispatch = useDispatch();
const navigate = useNavigate();
const handleClick = useEventCallback(() => {
dispatch(resetFilter());
dispatch(setFilterTag({ HasTag: [{ Name: text, isExcluded: false }] }));
addFilterCriteriaToStore('HasTag').catch(console.error);
navigate('/webui/collection');
});

return (
<Button
className={cx(
'pointer-events-auto text-xs font-semibold flex gap-x-2 items-center border-2 border-panel-tags rounded-lg p-2 whitespace-nowrap capitalize cursor-pointer',
type === 'User' ? 'text-panel-text-important' : 'text-panel-text-primary',
)}
onClick={handleClick}
>
<Icon path={mdiTagTextOutline} size="1rem" />
<span className="text-panel-text transition-colors hover:text-panel-text-primary">{text}</span>
</Button>
);
});

type Props = {
item: CollectionGroupType | SeriesType;
Expand Down Expand Up @@ -152,21 +167,18 @@ const ListViewItem = ({ groupExtras, isSeries, isSidebarOpen, item }: Props) =>
<Link to={viewRouteLink()}>
<BackgroundImagePlaceholderDiv
image={poster}
className="group h-[12.5625rem] w-[8.625rem] shrink-0 rounded-lg drop-shadow-md"
className="group h-[13.438rem] w-[9.25rem] shrink-0 rounded-lg drop-shadow-md"
hidePlaceholderOnHover
zoomOnHover
>
<div className="pointer-events-none z-10 flex h-full bg-panel-background-poster-overlay p-3 opacity-0 transition-opacity group-hover:pointer-events-auto group-hover:opacity-100">
<div
<Button
className="pointer-events-auto h-fit"
onClick={(isSeries || item.Size === 1) ? editSeriesModalCallback : editGroupModalCallback}
tooltip="Edit Series"
>
<Icon
path={mdiPencilCircleOutline}
size="2rem"
className="text-panel-icon"
/>
</div>
<Icon path={mdiPencilCircleOutline} size="2rem" />
</Button>
</div>
{showGroupIndicator && groupCount > 1 && (
<div className="absolute bottom-0 left-0 flex w-full justify-center rounded-bl-md bg-panel-background-overlay py-1.5 text-sm font-semibold opacity-100 transition-opacity group-hover:opacity-0">
Expand Down
12 changes: 5 additions & 7 deletions src/components/Collection/PosterViewItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Icon } from '@mdi/react';
import { reduce } from 'lodash';

import BackgroundImagePlaceholderDiv from '@/components/BackgroundImagePlaceholderDiv';
import Button from '@/components/Input/Button';
import { useSettingsQuery } from '@/core/react-query/settings/queries';
import { setGroupId } from '@/core/slices/modals/editGroup';
import { setSeriesId } from '@/core/slices/modals/editSeries';
Expand Down Expand Up @@ -84,16 +85,13 @@ const PosterViewItem = ({ isSeries = false, item }: Props) => {
</div>
)}
<div className="pointer-events-none z-10 flex h-full bg-panel-background-poster-overlay p-3 opacity-0 transition-opacity group-hover:pointer-events-auto group-hover:opacity-100">
<div
<Button
className="pointer-events-auto h-fit"
onClick={(isSeries || item.Size === 1) ? editSeriesModalCallback : editGroupModalCallback}
tooltip="Edit Series"
>
<Icon
path={mdiPencilCircleOutline}
size="2rem"
className="text-panel-icon"
/>
</div>
<Icon path={mdiPencilCircleOutline} size="2rem" />
</Button>
</div>
{showGroupIndicator && !isSeries && groupCount > 1 && (
<div className="absolute bottom-4 left-3 flex w-[90%] justify-center rounded-lg bg-panel-background-overlay py-2 text-sm font-semibold text-panel-text opacity-100 transition-opacity group-hover:opacity-0">
Expand Down
2 changes: 1 addition & 1 deletion src/components/Collection/Series/EditSeriesModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ const EditSeriesModal = () => {
className={cx(
activeTab === key
? 'w-[12rem] text-center bg-panel-menu-item-background p-3 rounded-lg text-panel-menu-item-text cursor-pointer'
: 'w-[12rem] text-center p-3 rounded-lg hover:bg-panel-menu-item-background-hover cursor-pointer',
: 'w-[12rem] text-center p-3 rounded-lg hover:bg-panel-menu-item-background-hover cursor-pointer transition-colors',
)}
key={key}
onClick={() => setActiveTab(key)}
Expand Down
2 changes: 1 addition & 1 deletion src/components/Collection/Series/EditSeriesTabs/Action.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const Action = (
) => (
<div
className={cx(
'flex flex-row justify-between gap-y-2 cursor-pointer hover:text-panel-text-primary',
'flex flex-row justify-between gap-y-2 cursor-pointer hover:text-panel-text-primary transition-colors',
scroll ? 'mr-4' : '',
)}
onClick={onClick}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ const NameTab = ({ seriesId }: Props) => {
<div className="shoko-scrollbar flex grow flex-col gap-y-2 overflow-y-auto bg-panel-input pr-4">
{seriesData?.AniDB?.Titles.map(title => (
<div
className="flex justify-between last:border-none hover:text-panel-text-primary"
className="flex justify-between transition-colors last:border-none hover:text-panel-text-primary"
key={title.Name + title.Language}
onClick={() => setName(title.Name)}
>
Expand Down
7 changes: 4 additions & 3 deletions src/components/Collection/SeriesTopPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import BackgroundImagePlaceholderDiv from '@/components/BackgroundImagePlacehold
import CleanDescription from '@/components/Collection/CleanDescription';
import SeriesInfo from '@/components/Collection/SeriesInfo';
import SeriesUserStats from '@/components/Collection/SeriesUserStats';
import Button from '@/components/Input/Button';
import ShokoPanel from '@/components/Panels/ShokoPanel';
import { useSeriesImagesQuery, useSeriesTagsQuery } from '@/core/react-query/series/queries';
import { useSettingsQuery } from '@/core/react-query/settings/queries';
Expand All @@ -33,16 +34,16 @@ const SeriesTag = React.memo(({ text, type }: { text: string, type: 'User' | 'An
});

return (
<div
<Button
className={cx(
'text-sm font-semibold flex gap-x-3 items-center border-2 border-panel-tags rounded-lg py-2 px-3 whitespace-nowrap capitalize h-fit cursor-pointer',
type === 'User' ? 'text-panel-icon-important' : 'text-panel-icon-action',
)}
onClick={handleClick}
>
<Icon path={mdiTagTextOutline} size="1.25rem" />
<span className="text-panel-text">{text}</span>
</div>
<span className="text-panel-text transition-colors hover:text-panel-text-primary">{text}</span>
</Button>
);
});

Expand Down
51 changes: 22 additions & 29 deletions src/components/Collection/TimelineSidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import React from 'react';
import { Link } from 'react-router-dom';
import { mdiLoading } from '@mdi/js';
import { Icon } from '@mdi/react';

import BackgroundImagePlaceholderDiv from '@/components/BackgroundImagePlaceholderDiv';
import ShokoPanel from '@/components/Panels/ShokoPanel';
import { SeriesTypeEnum } from '@/core/types/api/series';
import { dayjs } from '@/core/util';
import useMainPoster from '@/hooks/useMainPoster';
Expand All @@ -17,42 +16,36 @@ const TimelineItem = ({ series }: { series: SeriesType }) => {
: series.AniDB?.Type;

return (
<Link to={`/webui/collection/series/${series.IDs.ID}`}>
<div className="flex gap-x-3" key={series.IDs.ID}>
<div className="flex gap-x-3" key={series.IDs.ID}>
<Link to={`/webui/collection/series/${series.IDs.ID}`}>
natyusha marked this conversation as resolved.
Show resolved Hide resolved
<BackgroundImagePlaceholderDiv
image={mainPoster}
className="h-24 w-[4.4375rem] shrink-0 rounded-lg border border-panel-border drop-shadow-md"
className="group h-24 w-[4.4375rem] shrink-0 rounded-lg border border-panel-border drop-shadow-md"
overlayOnHover
zoomOnHover
/>
<div className="flex flex-col font-semibold">
<div className="flex gap-y-2">
{dayjs(series.AniDB?.AirDate).year()}
&nbsp;|&nbsp;
<div className="text-panel-text-important">{seriesType}</div>
</div>
<div className="line-clamp-2">{series.Name}</div>
</Link>
<div className="flex flex-col font-semibold">
<div className="flex gap-y-2">
{dayjs(series.AniDB?.AirDate).year()}
&nbsp;|&nbsp;
<div className="text-panel-text-important">{seriesType}</div>
</div>
<div className="line-clamp-2">{series.Name}</div>
</div>
</Link>
</div>
);
};

const TimelineSidebar = ({ isFetching, series }: { isFetching: boolean, series: SeriesType[] }) => (
<div className="flex min-h-full overflow-hidden transition-all">
<div className="ml-8 flex w-[26.125rem] grow flex-col gap-y-6 rounded-lg border border-panel-border bg-panel-background p-6">
<div className="text-xl font-semibold">Timeline</div>
{isFetching
? (
<div className="flex grow items-center justify-center text-panel-text-primary">
<Icon path={mdiLoading} size={3} spin />
</div>
)
: (
<div className="flex flex-col gap-y-3">
{series.map(item => <TimelineItem series={item} key={item.IDs.ID} />)}
</div>
)}
</div>
</div>
<ShokoPanel
title="Timeline"
className="sticky top-24 ml-6 !h-[calc(100vh-18rem)] w-[26.5rem]"
contentClassName="gap-y-3"
isFetching={isFetching}
>
{series.map(item => <TimelineItem series={item} key={item.IDs.ID} />)}
</ShokoPanel>
);

export default TimelineSidebar;
4 changes: 2 additions & 2 deletions src/components/Dashboard/DashboardSettingsModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ const DashboardSettingsModal = ({ onClose, show }: Props) => {
className={cx(
activeTab === 'widgets'
? 'w-[12rem] text-center bg-panel-menu-item-background p-3 rounded-lg text-panel-menu-item-text cursor-pointer'
: 'w-[12rem] text-center p-3 rounded-lg hover:bg-panel-menu-item-background-hover cursor-pointer',
: 'w-[12rem] text-center p-3 rounded-lg hover:bg-panel-menu-item-background-hover cursor-pointer transition-colors',
)}
key="widgets"
onClick={() => setActiveTab('widgets')}
Expand All @@ -124,7 +124,7 @@ const DashboardSettingsModal = ({ onClose, show }: Props) => {
className={cx(
activeTab === 'options'
? 'w-[12rem] text-center bg-panel-menu-item-background p-3 rounded-lg text-panel-menu-item-text cursor-pointer'
: 'w-[12rem] text-center p-3 rounded-lg hover:bg-panel-menu-item-background-hover cursor-pointer',
: 'w-[12rem] text-center p-3 rounded-lg hover:bg-panel-menu-item-background-hover cursor-pointer transition-colors',
)}
key="options"
onClick={() => setActiveTab('options')}
Expand Down
4 changes: 2 additions & 2 deletions src/components/Dialogs/ActionsModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ const Action = ({ actionKey, length }: { actionKey: string, length: number }) =>
return (
<div
className={cx(
'flex flex-row justify-between gap-y-2 cursor-pointer hover:text-panel-text-primary',
'flex flex-row justify-between gap-y-2 cursor-pointer hover:text-panel-text-primary transition-colors',
length > 5 ? 'mr-4' : '',
)}
onClick={handleAction}
Expand Down Expand Up @@ -138,7 +138,7 @@ function ActionsModal({ onClose, show }: Props) {
className={cx(
activeTab === key
? 'w-[7.5rem] text-center bg-panel-menu-item-background p-3 rounded-lg text-panel-menu-item-text cursor-pointer'
: 'w-[7.5rem] text-center p-3 rounded-lg hover:bg-panel-menu-item-background-hover cursor-pointer',
: 'w-[7.5rem] text-center p-3 rounded-lg hover:bg-panel-menu-item-background-hover cursor-pointer transition-colors',
)}
key={key}
onClick={() => setActiveTab(key)}
Expand Down
2 changes: 1 addition & 1 deletion src/components/Layout/TopNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ function TopNav() {
layoutEditMode && 'opacity-65 pointer-events-none',
)}
>
<div className="mx-auto flex w-full max-w-[120rem] items-center justify-between p-6">
<div className="mx-auto flex w-full max-w-[120rem] items-center justify-between px-6 py-2">
<Link to="/webui/dashboard" className="flex items-center gap-x-3">
<ShokoIcon className="w-20" />
<span className="mt-1 text-2xl font-semibold text-header-text">Shoko</span>
Expand Down
7 changes: 6 additions & 1 deletion src/components/Utilities/ReleaseManagement/Title.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@ import { mdiChevronRight } from '@mdi/js';
import { Icon } from '@mdi/react';

const TabButton = ({ id, name }: { id: string, name: string }) => (
<NavLink to={`../release-management/${id}`} className={({ isActive }) => (isActive ? 'text-panel-text-primary' : '')}>
<NavLink
to={`../release-management/${id}`}
className={(
{ isActive },
) => (isActive ? 'text-panel-text-primary' : 'hover:text-panel-text-primary transition-colors')}
>
{name}
</NavLink>
);
Expand Down
7 changes: 6 additions & 1 deletion src/components/Utilities/Unrecognized/Title.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@ import { mdiChevronRight } from '@mdi/js';
import { Icon } from '@mdi/react';

const TabButton = ({ id, name }: { id: string, name: string }) => (
<NavLink to={`../unrecognized/${id}`} className={({ isActive }) => (isActive ? 'text-panel-text-primary' : '')}>
<NavLink
to={`../unrecognized/${id}`}
className={(
{ isActive },
) => (isActive ? 'text-panel-text-primary' : 'hover:text-panel-text-primary transition-colors')}
>
{name}
</NavLink>
);
Expand Down
4 changes: 2 additions & 2 deletions src/pages/collection/Collection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ function Collection() {

return (
<div className="flex grow flex-col gap-y-6">
<div className="flex items-center justify-between rounded-lg border border-panel-border bg-panel-background p-6">
<div className="sticky -top-6 z-10 flex items-center justify-between rounded-lg border border-panel-border bg-panel-background p-6">
<CollectionTitle
// eslint-disable-next-line no-nested-ternary
count={(total === 0 && isFetching) ? -1 : (isSeries ? total : groupsTotal)}
Expand Down Expand Up @@ -232,7 +232,7 @@ function Collection() {
className={cx(
'flex items-start transition-all',
(!isSeries && showFilterSidebar)
? 'w-[28.84rem] opacity-100 overflow-auto '
? 'w-[28rem] opacity-100'
: 'w-0 opacity-0 overflow-hidden ',
)}
>
Expand Down
Loading