mirror of
https://github.com/jeffvli/feishin.git
synced 2026-06-23 20:37:42 +02:00
join releasetypes on 'all' mode on artist page
This commit is contained in:
@@ -900,6 +900,8 @@ const AlbumSection = ({ albums, controls, cq, releaseType, rows, title }: AlbumS
|
|||||||
|
|
||||||
type GroupingType = 'all' | 'primary';
|
type GroupingType = 'all' | 'primary';
|
||||||
|
|
||||||
|
const PRIMARY_RELEASE_TYPES = ['album', 'broadcast', 'ep', 'other', 'single'];
|
||||||
|
|
||||||
const groupAlbumsByReleaseType = (
|
const groupAlbumsByReleaseType = (
|
||||||
albums: Album[],
|
albums: Album[],
|
||||||
routeId: string,
|
routeId: string,
|
||||||
@@ -933,13 +935,21 @@ const groupAlbumsByReleaseType = (
|
|||||||
// Group by all release types
|
// Group by all release types
|
||||||
const releaseTypes = album.releaseTypes || [];
|
const releaseTypes = album.releaseTypes || [];
|
||||||
if (releaseTypes.length > 0) {
|
if (releaseTypes.length > 0) {
|
||||||
releaseTypes.forEach((type) => {
|
// Sort release types: primaries first (alphabetically), then secondaries (alphabetically)
|
||||||
const normalizedType = type.toLowerCase();
|
const normalizedTypes = releaseTypes.map((type) => type.toLowerCase());
|
||||||
if (!acc[normalizedType]) {
|
const primaryTypes = normalizedTypes
|
||||||
acc[normalizedType] = [];
|
.filter((type) => PRIMARY_RELEASE_TYPES.includes(type))
|
||||||
|
.sort();
|
||||||
|
const secondaryTypes = normalizedTypes
|
||||||
|
.filter((type) => !PRIMARY_RELEASE_TYPES.includes(type))
|
||||||
|
.sort();
|
||||||
|
const sortedTypes = [...primaryTypes, ...secondaryTypes];
|
||||||
|
|
||||||
|
const combinedKey = sortedTypes.join('/');
|
||||||
|
if (!acc[combinedKey]) {
|
||||||
|
acc[combinedKey] = [];
|
||||||
}
|
}
|
||||||
acc[normalizedType].push(album);
|
acc[combinedKey].push(album);
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
// If no release types, use "album" as fallback
|
// If no release types, use "album" as fallback
|
||||||
const albumKey = 'album';
|
const albumKey = 'album';
|
||||||
@@ -1116,11 +1126,114 @@ const ArtistAlbums = ({ albumsQuery }: ArtistAlbumsProps) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const getDisplayNameForType = (releaseType: string): string => {
|
||||||
|
switch (releaseType) {
|
||||||
|
case 'album':
|
||||||
|
return t('releaseType.primary.album', {
|
||||||
|
postProcess: 'sentenceCase',
|
||||||
|
});
|
||||||
|
case 'appears-on':
|
||||||
|
return t('page.albumArtistDetail.appearsOn', {
|
||||||
|
postProcess: 'sentenceCase',
|
||||||
|
});
|
||||||
|
case 'audiobook':
|
||||||
|
return t('releaseType.secondary.audiobook', {
|
||||||
|
postProcess: 'sentenceCase',
|
||||||
|
});
|
||||||
|
case 'audio drama':
|
||||||
|
return t('releaseType.secondary.audioDrama', {
|
||||||
|
postProcess: 'sentenceCase',
|
||||||
|
});
|
||||||
|
case 'broadcast':
|
||||||
|
return t('releaseType.primary.broadcast', {
|
||||||
|
postProcess: 'sentenceCase',
|
||||||
|
});
|
||||||
|
case 'compilation':
|
||||||
|
return t('releaseType.secondary.compilation', {
|
||||||
|
postProcess: 'sentenceCase',
|
||||||
|
});
|
||||||
|
case 'demo':
|
||||||
|
return t('releaseType.secondary.demo', {
|
||||||
|
postProcess: 'sentenceCase',
|
||||||
|
});
|
||||||
|
case 'dj-mix':
|
||||||
|
return t('releaseType.secondary.djMix', {
|
||||||
|
postProcess: 'sentenceCase',
|
||||||
|
});
|
||||||
|
case 'ep':
|
||||||
|
return t('releaseType.primary.ep', {
|
||||||
|
postProcess: 'upperCase',
|
||||||
|
});
|
||||||
|
case 'field recording':
|
||||||
|
return t('releaseType.secondary.fieldRecording', {
|
||||||
|
postProcess: 'sentenceCase',
|
||||||
|
});
|
||||||
|
case 'interview':
|
||||||
|
return t('releaseType.secondary.interview', {
|
||||||
|
postProcess: 'sentenceCase',
|
||||||
|
});
|
||||||
|
case 'live':
|
||||||
|
return t('releaseType.secondary.live', {
|
||||||
|
postProcess: 'sentenceCase',
|
||||||
|
});
|
||||||
|
case 'mixtape/street':
|
||||||
|
return t('releaseType.secondary.mixtape', {
|
||||||
|
postProcess: 'sentenceCase',
|
||||||
|
});
|
||||||
|
case 'other':
|
||||||
|
return t('releaseType.primary.other', {
|
||||||
|
postProcess: 'sentenceCase',
|
||||||
|
});
|
||||||
|
case 'remix':
|
||||||
|
return t('releaseType.secondary.remix', {
|
||||||
|
postProcess: 'sentenceCase',
|
||||||
|
});
|
||||||
|
case 'single':
|
||||||
|
return t('releaseType.primary.single', {
|
||||||
|
postProcess: 'sentenceCase',
|
||||||
|
});
|
||||||
|
case 'soundtrack':
|
||||||
|
return t('releaseType.secondary.soundtrack', {
|
||||||
|
postProcess: 'sentenceCase',
|
||||||
|
});
|
||||||
|
case 'spokenword':
|
||||||
|
return t('releaseType.secondary.spokenWord', {
|
||||||
|
postProcess: 'sentenceCase',
|
||||||
|
});
|
||||||
|
default:
|
||||||
|
return titleCase(releaseType);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const getPriority = (releaseType: string) => {
|
const getPriority = (releaseType: string) => {
|
||||||
|
if (releaseType.includes('/')) {
|
||||||
|
const types = releaseType.split('/');
|
||||||
|
// Check if there's a primary type in the joined types
|
||||||
|
const primaryTypes = types.filter((type) => PRIMARY_RELEASE_TYPES.includes(type));
|
||||||
|
|
||||||
|
if (primaryTypes.length > 0) {
|
||||||
|
// Use the primary type's priority (first primary if multiple)
|
||||||
|
const primaryPriority = priorityMap.get(primaryTypes[0]) ?? 999;
|
||||||
|
return primaryPriority;
|
||||||
|
} else {
|
||||||
|
// Only secondary types - use minimum priority from settings
|
||||||
|
const priorities = types
|
||||||
|
.map((type) => priorityMap.get(type) ?? 999)
|
||||||
|
.filter((p) => p !== 999);
|
||||||
|
return priorities.length > 0 ? Math.min(...priorities) : 999;
|
||||||
|
}
|
||||||
|
}
|
||||||
return priorityMap.get(releaseType) ?? 999;
|
return priorityMap.get(releaseType) ?? 999;
|
||||||
};
|
};
|
||||||
|
|
||||||
const isReleaseTypeEnabled = (releaseType: string): boolean => {
|
const isReleaseTypeEnabled = (releaseType: string): boolean => {
|
||||||
|
if (releaseType.includes('/')) {
|
||||||
|
const types = releaseType.split('/');
|
||||||
|
return types.some((type) => {
|
||||||
|
const enumValue = releaseTypeToEnumMap[type];
|
||||||
|
return enumValue ? enabledReleaseTypeEnums.has(enumValue) : false;
|
||||||
|
});
|
||||||
|
}
|
||||||
const enumValue = releaseTypeToEnumMap[releaseType];
|
const enumValue = releaseTypeToEnumMap[releaseType];
|
||||||
return enumValue ? enabledReleaseTypeEnums.has(enumValue) : false;
|
return enumValue ? enabledReleaseTypeEnums.has(enumValue) : false;
|
||||||
};
|
};
|
||||||
@@ -1129,103 +1242,30 @@ const ArtistAlbums = ({ albumsQuery }: ArtistAlbumsProps) => {
|
|||||||
.filter(([releaseType]) => isReleaseTypeEnabled(releaseType))
|
.filter(([releaseType]) => isReleaseTypeEnabled(releaseType))
|
||||||
.map(([releaseType, albums]) => {
|
.map(([releaseType, albums]) => {
|
||||||
let displayName: React.ReactNode | string;
|
let displayName: React.ReactNode | string;
|
||||||
switch (releaseType) {
|
|
||||||
case 'album':
|
if (releaseType.includes('/')) {
|
||||||
displayName = t('releaseType.primary.album', {
|
const types = releaseType.split('/');
|
||||||
postProcess: 'sentenceCase',
|
const displayNames = types.map((type) => getDisplayNameForType(type));
|
||||||
});
|
displayName = displayNames.join('/');
|
||||||
break;
|
} else {
|
||||||
case 'appears-on':
|
displayName = getDisplayNameForType(releaseType);
|
||||||
displayName = t('page.albumArtistDetail.appearsOn', {
|
|
||||||
postProcess: 'sentenceCase',
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case 'audiobook':
|
|
||||||
displayName = t('releaseType.secondary.audiobook', {
|
|
||||||
postProcess: 'sentenceCase',
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case 'audio drama':
|
|
||||||
displayName = t('releaseType.secondary.audioDrama', {
|
|
||||||
postProcess: 'sentenceCase',
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case 'broadcast':
|
|
||||||
displayName = t('releaseType.primary.broadcast', {
|
|
||||||
postProcess: 'sentenceCase',
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case 'compilation':
|
|
||||||
displayName = t('releaseType.secondary.compilation', {
|
|
||||||
postProcess: 'sentenceCase',
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case 'demo':
|
|
||||||
displayName = t('releaseType.secondary.demo', {
|
|
||||||
postProcess: 'sentenceCase',
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case 'dj-mix':
|
|
||||||
displayName = t('releaseType.secondary.djMix', {
|
|
||||||
postProcess: 'sentenceCase',
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case 'ep':
|
|
||||||
displayName = t('releaseType.primary.ep', {
|
|
||||||
postProcess: 'upperCase',
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case 'field recording':
|
|
||||||
displayName = t('releaseType.secondary.fieldRecording', {
|
|
||||||
postProcess: 'sentenceCase',
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case 'interview':
|
|
||||||
displayName = t('releaseType.secondary.interview', {
|
|
||||||
postProcess: 'sentenceCase',
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case 'live':
|
|
||||||
displayName = t('releaseType.secondary.live', {
|
|
||||||
postProcess: 'sentenceCase',
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case 'mixtape/street':
|
|
||||||
displayName = t('releaseType.secondary.mixtape', {
|
|
||||||
postProcess: 'sentenceCase',
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case 'other':
|
|
||||||
displayName = t('releaseType.primary.other', {
|
|
||||||
postProcess: 'sentenceCase',
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case 'remix':
|
|
||||||
displayName = t('releaseType.secondary.remix', {
|
|
||||||
postProcess: 'sentenceCase',
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case 'single':
|
|
||||||
displayName = t('releaseType.primary.single', {
|
|
||||||
postProcess: 'sentenceCase',
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case 'soundtrack':
|
|
||||||
displayName = t('releaseType.secondary.soundtrack', {
|
|
||||||
postProcess: 'sentenceCase',
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case 'spokenword':
|
|
||||||
displayName = t('releaseType.secondary.spokenWord', {
|
|
||||||
postProcess: 'sentenceCase',
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
displayName = titleCase(releaseType);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return { albums, displayName, releaseType };
|
return { albums, displayName, releaseType };
|
||||||
})
|
})
|
||||||
.sort((a, b) => getPriority(a.releaseType) - getPriority(b.releaseType));
|
.sort((a, b) => {
|
||||||
|
const priorityA = getPriority(a.releaseType);
|
||||||
|
const priorityB = getPriority(b.releaseType);
|
||||||
|
|
||||||
|
// First sort by priority
|
||||||
|
if (priorityA !== priorityB) {
|
||||||
|
return priorityA - priorityB;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If priorities are equal (e.g., both have the same primary type),
|
||||||
|
// sort alphabetically by the release type key
|
||||||
|
return a.releaseType.localeCompare(b.releaseType);
|
||||||
|
});
|
||||||
}, [albumsByReleaseType, artistReleaseTypeItems, t]);
|
}, [albumsByReleaseType, artistReleaseTypeItems, t]);
|
||||||
|
|
||||||
const cq = useContainerQuery({
|
const cq = useContainerQuery({
|
||||||
|
|||||||
@@ -12,6 +12,6 @@ const BaseGrid = ({ classNames, style, ...props }: GridProps) => {
|
|||||||
|
|
||||||
BaseGrid.displayName = 'Grid';
|
BaseGrid.displayName = 'Grid';
|
||||||
|
|
||||||
export const Grid = memo(BaseGrid);
|
export const Grid = memo(BaseGrid) as unknown as typeof BaseGrid & { Col: typeof MantineGrid.Col };
|
||||||
|
|
||||||
(Grid as typeof Grid & { Col: typeof MantineGrid.Col }).Col = MantineGrid.Col;
|
(Grid as typeof Grid & { Col: typeof MantineGrid.Col }).Col = MantineGrid.Col;
|
||||||
|
|||||||
Reference in New Issue
Block a user