Skip to content

Commit

Permalink
feat(series): add season titles as filters
Browse files Browse the repository at this point in the history
- add season titles to filters
- fix content type casing
  • Loading branch information
AntonLantukh committed Jun 1, 2023
1 parent 906f2e9 commit c42f9ad
Show file tree
Hide file tree
Showing 8 changed files with 35 additions and 32 deletions.
3 changes: 0 additions & 3 deletions src/components/Dropdown/Dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ type Props = {
defaultLabel?: string;
options?: (string | { value: string; label: string })[];
optionsStyle?: string;
valuePrefix?: string;
label?: string;
fullWidth?: boolean;
size?: 'small' | 'medium';
Expand All @@ -34,7 +33,6 @@ const Dropdown: React.FC<Props & React.AriaAttributes> = ({
optionsStyle,
label,
fullWidth,
valuePrefix,
error,
helperText,
required = false,
Expand Down Expand Up @@ -66,7 +64,6 @@ const Dropdown: React.FC<Props & React.AriaAttributes> = ({
key={typeof option === 'string' ? option : option.value}
value={typeof option === 'string' ? option : option.value}
>
{valuePrefix}
{typeof option === 'string' ? option : option.label}
</option>
))}
Expand Down
22 changes: 15 additions & 7 deletions src/components/Filter/Filter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,23 @@ import Dropdown from '#components/Dropdown/Dropdown';
import Button from '#components/Button/Button';
import useBreakpoint, { Breakpoint } from '#src/hooks/useBreakpoint';

type FilterOption =
| {
label: string;
value: string;
}
| string;

type Props = {
name: string;
value: string;
valuePrefix?: string;
defaultLabel: string;
options: string[];
options: FilterOption[];
forceDropdown?: boolean;
setValue: (value: string) => void;
};

const Filter: FC<Props> = ({ name, value, defaultLabel, options, setValue, valuePrefix = '', forceDropdown = false }) => {
const Filter: FC<Props> = ({ name, value, defaultLabel, options, setValue, forceDropdown = false }) => {
const { t } = useTranslation('common');
const breakpoint: Breakpoint = useBreakpoint();

Expand All @@ -32,9 +38,12 @@ const Filter: FC<Props> = ({ name, value, defaultLabel, options, setValue, value
<Fragment>
{showFilterRow ? (
<div className={styles.filterRow} role="listbox" aria-label={t('filter_videos_by', { name })}>
{options.map((option) => (
<Button label={`${valuePrefix}${option}`} onClick={() => setValue(option)} key={option} active={value === option} role="option" />
))}
{options.map((option) => {
const optionLabel = typeof option === 'string' ? option : option.label;
const optionValue = typeof option === 'string' ? option : option.value;

return <Button label={optionLabel} onClick={() => setValue(optionValue)} key={optionValue} active={value === optionValue} role="option" />;
})}
<Button label={defaultLabel} onClick={() => setValue('')} active={value === ''} key={defaultLabel} role="option" />
</div>
) : (
Expand All @@ -44,7 +53,6 @@ const Filter: FC<Props> = ({ name, value, defaultLabel, options, setValue, value
size="small"
options={options}
defaultLabel={defaultLabel}
valuePrefix={valuePrefix}
name={name}
value={value}
onChange={handleChange}
Expand Down
14 changes: 2 additions & 12 deletions src/components/VideoLayout/VideoLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,9 @@ import type { AccessModel } from '#types/Config';

type FilterProps = {
filterMetadata?: React.ReactNode;
filters?: string[];
filters?: (string | { label: string; value: string })[];
currentFilter?: string;
defaultFilterLabel?: string;
filterValuePrefix?: string;
setFilter?: (value: string) => void;
};

Expand Down Expand Up @@ -91,7 +90,6 @@ const VideoLayout: React.FC<Props> = ({
filters,
setFilter,
filterMetadata,
filterValuePrefix,
currentFilter = '',
defaultFilterLabel = '',
children,
Expand All @@ -109,15 +107,7 @@ const VideoLayout: React.FC<Props> = ({
<div className={classNames(styles.filters, { [styles.filtersInline]: inlineLayout })}>
{!!filterMetadata && inlineLayout && <span className={styles.filterMetadata}>{filterMetadata}</span>}
{showFilters && (
<Filter
name="season"
value={currentFilter}
valuePrefix={filterValuePrefix}
defaultLabel={defaultFilterLabel}
options={filters}
setValue={setFilter}
forceDropdown={forceDropdown}
/>
<Filter name="season" value={currentFilter} defaultLabel={defaultFilterLabel} options={filters} setValue={setFilter} forceDropdown={forceDropdown} />
)}
</div>
);
Expand Down
3 changes: 1 addition & 2 deletions src/pages/LegacySeries/LegacySeries.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ const LegacySeries = () => {
const inlineLayout = Boolean(custom?.inlinePlayer);

// Filters
const filters = useMemo(() => getFiltersFromSeries(seriesPlaylist), [seriesPlaylist]);
const filters = useMemo(() => getFiltersFromSeries(seriesPlaylist, t), [seriesPlaylist, t]);
const [seasonFilter, setSeasonFilter] = useState<string | undefined>(undefined);

const firstEpisode = useMemo(() => seriesPlaylist?.playlist?.[0], [seriesPlaylist]);
Expand Down Expand Up @@ -193,7 +193,6 @@ const LegacySeries = () => {
onItemClick={onCardClick}
setFilter={setSeasonFilter}
currentFilter={seasonFilter}
filterValuePrefix={t('season_prefix')}
defaultFilterLabel={t('all_seasons')}
activeLabel={t('current_episode')}
watchHistory={watchHistoryDictionary}
Expand Down
12 changes: 10 additions & 2 deletions src/pages/LegacySeries/utils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import type { TFunction } from 'i18next';

import { legacySeriesURL } from '#src/utils/formatting';
import { secondsToISO8601 } from '#src/utils/datetime';
import type { Playlist, PlaylistItem } from '#types/playlist';
Expand All @@ -6,11 +8,17 @@ import type { EpisodeMetadata } from '#types/series';
/**
* Get an array of options for a season filter
*/
export const getFiltersFromSeries = (playlist: Playlist | undefined): string[] => {
export const getFiltersFromSeries = (playlist: Playlist | undefined, t: TFunction): string[] => {
// Old series doesn't have sorting supported and just aggregates all episodes in one playlist
// So we need to sort the playlist manually based on the selected filter (season).
return (playlist?.playlist || [])
.reduce((filters: string[], item) => (item.seasonNumber && filters.includes(item.seasonNumber) ? filters : filters.concat(item.seasonNumber || '')), [])
.reduce(
(filters: string[], item) =>
item.seasonNumber && filters.includes(item.seasonNumber)
? filters
: filters.concat(item.seasonNumber ? `${t('season_prefix')} ${item.seasonNumber}` : ''),
[],
)
.slice()
.sort();
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ const MediaSeries: ScreenComponent<PlaylistItem> = ({ data: seriesMedia }) => {

if (!episodeId && !seasonFilter) {
// No episode is selected
setSeasonFilter(filters[0] || '');
setSeasonFilter(filters[0]?.value || '');
return;
}

Expand Down Expand Up @@ -253,7 +253,6 @@ const MediaSeries: ScreenComponent<PlaylistItem> = ({ data: seriesMedia }) => {
onItemClick={onCardClick}
setFilter={setSeasonFilter}
currentFilter={seasonFilter}
filterValuePrefix={t('season_prefix')}
defaultFilterLabel={t('all_seasons')}
activeLabel={t('current_episode')}
watchHistory={watchHistoryDictionary}
Expand Down
4 changes: 2 additions & 2 deletions src/utils/media.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ export const isLegacySeriesFlow = (item: PlaylistItem) => {

// For the new series flow we use contentType custom param to define media item to be series
// In this case media item and series item have the same id
export const isSeriesContentType = (item: PlaylistItem) => item.contentType === CONTENT_TYPE.series;
export const isSeriesContentType = (item: PlaylistItem) => item.contentType?.toLowerCase() === CONTENT_TYPE.series;

export const isSeries = (item: PlaylistItem) => isLegacySeriesFlow(item) || isSeriesContentType(item);

export const isEpisode = (item: PlaylistItem) => {
return typeof item?.episodeNumber !== 'undefined' || item?.contentType === CONTENT_TYPE.episode;
return typeof item?.episodeNumber !== 'undefined' || item?.contentType?.toLowerCase() === CONTENT_TYPE.episode;
};

export const getLegacySeriesPlaylistIdFromEpisodeTags = (item: PlaylistItem | undefined) => {
Expand Down
6 changes: 4 additions & 2 deletions src/utils/series.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ import { getEpisodes, getSeasonWithEpisodes } from '#src/services/api.service';
/**
* Get an array of options for a season filter
*/
export const getFiltersFromSeries = (series: Series | undefined): string[] => {
return series && 'seasons' in series ? series.seasons.map((season) => String(season.season_number)) : [];
export const getFiltersFromSeries = (series: Series | undefined): { label: string; value: string }[] => {
return series && 'seasons' in series
? series.seasons.map((season) => ({ label: season.season_title || String(season.season_number), value: String(season.season_number) }))
: [];
};

/**
Expand Down

0 comments on commit c42f9ad

Please sign in to comment.