mirror of
https://github.com/lidarr/lidarr.git
synced 2025-07-07 13:32:17 -07:00
New: Added album disambiguation to UI and Naming [ex. Weezer (Blue Album)] (#431)
This commit is contained in:
parent
54d1d90e16
commit
e6a43b2dc0
19 changed files with 73 additions and 39 deletions
|
@ -114,6 +114,7 @@ class HistoryRow extends Component {
|
||||||
<AlbumTitleLink
|
<AlbumTitleLink
|
||||||
foreignAlbumId={album.foreignAlbumId}
|
foreignAlbumId={album.foreignAlbumId}
|
||||||
title={album.title}
|
title={album.title}
|
||||||
|
disambiguation={album.disambiguation}
|
||||||
/>
|
/>
|
||||||
</TableRowCell>
|
</TableRowCell>
|
||||||
);
|
);
|
||||||
|
|
|
@ -158,6 +158,7 @@ class QueueRow extends Component {
|
||||||
<AlbumTitleLink
|
<AlbumTitleLink
|
||||||
foreignAlbumId={album.foreignAlbumId}
|
foreignAlbumId={album.foreignAlbumId}
|
||||||
title={album.title}
|
title={album.title}
|
||||||
|
disambiguation={album.disambiguation}
|
||||||
/>
|
/>
|
||||||
</TableRowCell>
|
</TableRowCell>
|
||||||
);
|
);
|
||||||
|
|
|
@ -2,19 +2,20 @@ import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Link from 'Components/Link/Link';
|
import Link from 'Components/Link/Link';
|
||||||
|
|
||||||
function AlbumTitleLink({ foreignAlbumId, title }) {
|
function AlbumTitleLink({ foreignAlbumId, title, disambiguation }) {
|
||||||
const link = `/album/${foreignAlbumId}`;
|
const link = `/album/${foreignAlbumId}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Link to={link}>
|
<Link to={link}>
|
||||||
{title}
|
{title}{disambiguation ? ` (${disambiguation})` : ''}
|
||||||
</Link>
|
</Link>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
AlbumTitleLink.propTypes = {
|
AlbumTitleLink.propTypes = {
|
||||||
foreignAlbumId: PropTypes.string.isRequired,
|
foreignAlbumId: PropTypes.string.isRequired,
|
||||||
title: PropTypes.string.isRequired
|
title: PropTypes.string.isRequired,
|
||||||
|
disambiguation: PropTypes.string
|
||||||
};
|
};
|
||||||
|
|
||||||
export default AlbumTitleLink;
|
export default AlbumTitleLink;
|
||||||
|
|
|
@ -136,6 +136,7 @@ class AlbumDetails extends Component {
|
||||||
const {
|
const {
|
||||||
id,
|
id,
|
||||||
title,
|
title,
|
||||||
|
disambiguation,
|
||||||
albumType,
|
albumType,
|
||||||
statistics,
|
statistics,
|
||||||
monitored,
|
monitored,
|
||||||
|
@ -251,7 +252,7 @@ class AlbumDetails extends Component {
|
||||||
<div className={styles.info}>
|
<div className={styles.info}>
|
||||||
<div className={styles.titleContainer}>
|
<div className={styles.titleContainer}>
|
||||||
<div className={styles.title}>
|
<div className={styles.title}>
|
||||||
{title}
|
{title}{disambiguation ? ` (${disambiguation})` : ''}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={styles.artistNavigationButtons}>
|
<div className={styles.artistNavigationButtons}>
|
||||||
|
@ -444,6 +445,7 @@ AlbumDetails.propTypes = {
|
||||||
id: PropTypes.number.isRequired,
|
id: PropTypes.number.isRequired,
|
||||||
foreignAlbumId: PropTypes.string.isRequired,
|
foreignAlbumId: PropTypes.string.isRequired,
|
||||||
title: PropTypes.string.isRequired,
|
title: PropTypes.string.isRequired,
|
||||||
|
disambiguation: PropTypes.string,
|
||||||
albumType: PropTypes.string.isRequired,
|
albumType: PropTypes.string.isRequired,
|
||||||
statistics: PropTypes.object.isRequired,
|
statistics: PropTypes.object.isRequired,
|
||||||
releaseDate: PropTypes.string.isRequired,
|
releaseDate: PropTypes.string.isRequired,
|
||||||
|
|
|
@ -76,6 +76,7 @@ class AlbumRow extends Component {
|
||||||
secondaryTypes,
|
secondaryTypes,
|
||||||
title,
|
title,
|
||||||
ratings,
|
ratings,
|
||||||
|
disambiguation,
|
||||||
isSaving,
|
isSaving,
|
||||||
artistMonitored,
|
artistMonitored,
|
||||||
foreignAlbumId,
|
foreignAlbumId,
|
||||||
|
@ -124,8 +125,9 @@ class AlbumRow extends Component {
|
||||||
className={styles.title}
|
className={styles.title}
|
||||||
>
|
>
|
||||||
<AlbumTitleLink
|
<AlbumTitleLink
|
||||||
title={title}
|
|
||||||
foreignAlbumId={foreignAlbumId}
|
foreignAlbumId={foreignAlbumId}
|
||||||
|
title={title}
|
||||||
|
disambiguation={disambiguation}
|
||||||
/>
|
/>
|
||||||
</TableRowCell>
|
</TableRowCell>
|
||||||
);
|
);
|
||||||
|
@ -239,6 +241,7 @@ AlbumRow.propTypes = {
|
||||||
duration: PropTypes.number.isRequired,
|
duration: PropTypes.number.isRequired,
|
||||||
title: PropTypes.string.isRequired,
|
title: PropTypes.string.isRequired,
|
||||||
ratings: PropTypes.object.isRequired,
|
ratings: PropTypes.object.isRequired,
|
||||||
|
disambiguation: PropTypes.string,
|
||||||
secondaryTypes: PropTypes.arrayOf(PropTypes.string).isRequired,
|
secondaryTypes: PropTypes.arrayOf(PropTypes.string).isRequired,
|
||||||
foreignAlbumId: PropTypes.string.isRequired,
|
foreignAlbumId: PropTypes.string.isRequired,
|
||||||
isSaving: PropTypes.bool,
|
isSaving: PropTypes.bool,
|
||||||
|
|
|
@ -187,6 +187,7 @@ class ArtistIndexRow extends Component {
|
||||||
>
|
>
|
||||||
<AlbumTitleLink
|
<AlbumTitleLink
|
||||||
title={nextAlbum.title}
|
title={nextAlbum.title}
|
||||||
|
disambiguation={nextAlbum.disambiguation}
|
||||||
foreignAlbumId={nextAlbum.foreignAlbumId}
|
foreignAlbumId={nextAlbum.foreignAlbumId}
|
||||||
/>
|
/>
|
||||||
</VirtualTableRowCell>
|
</VirtualTableRowCell>
|
||||||
|
@ -211,6 +212,7 @@ class ArtistIndexRow extends Component {
|
||||||
>
|
>
|
||||||
<AlbumTitleLink
|
<AlbumTitleLink
|
||||||
title={lastAlbum.title}
|
title={lastAlbum.title}
|
||||||
|
disambiguation={lastAlbum.disambiguation}
|
||||||
foreignAlbumId={lastAlbum.foreignAlbumId}
|
foreignAlbumId={lastAlbum.foreignAlbumId}
|
||||||
/>
|
/>
|
||||||
</VirtualTableRowCell>
|
</VirtualTableRowCell>
|
||||||
|
|
|
@ -134,7 +134,9 @@ class NamingModal extends Component {
|
||||||
|
|
||||||
{ token: '{Album CleanTitle}', example: 'Album Title' },
|
{ token: '{Album CleanTitle}', example: 'Album Title' },
|
||||||
|
|
||||||
{ token: '{Album Type}', example: 'Album Type' }
|
{ token: '{Album Type}', example: 'Album Type' },
|
||||||
|
|
||||||
|
{ token: '{Album Disambiguation}', example: 'Disambiguation' }
|
||||||
];
|
];
|
||||||
|
|
||||||
const mediumTokens = [
|
const mediumTokens = [
|
||||||
|
|
|
@ -21,6 +21,7 @@ function CutoffUnmetRow(props) {
|
||||||
foreignAlbumId,
|
foreignAlbumId,
|
||||||
albumType,
|
albumType,
|
||||||
title,
|
title,
|
||||||
|
disambiguation,
|
||||||
isSelected,
|
isSelected,
|
||||||
columns,
|
columns,
|
||||||
onSelectedChange
|
onSelectedChange
|
||||||
|
@ -62,6 +63,7 @@ function CutoffUnmetRow(props) {
|
||||||
<AlbumTitleLink
|
<AlbumTitleLink
|
||||||
foreignAlbumId={foreignAlbumId}
|
foreignAlbumId={foreignAlbumId}
|
||||||
title={title}
|
title={title}
|
||||||
|
disambiguation={disambiguation}
|
||||||
/>
|
/>
|
||||||
</TableRowCell>
|
</TableRowCell>
|
||||||
);
|
);
|
||||||
|
@ -140,6 +142,7 @@ CutoffUnmetRow.propTypes = {
|
||||||
foreignAlbumId: PropTypes.string.isRequired,
|
foreignAlbumId: PropTypes.string.isRequired,
|
||||||
albumType: PropTypes.string.isRequired,
|
albumType: PropTypes.string.isRequired,
|
||||||
title: PropTypes.string.isRequired,
|
title: PropTypes.string.isRequired,
|
||||||
|
disambiguation: PropTypes.string,
|
||||||
isSelected: PropTypes.bool,
|
isSelected: PropTypes.bool,
|
||||||
columns: PropTypes.arrayOf(PropTypes.object).isRequired,
|
columns: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||||
onSelectedChange: PropTypes.func.isRequired
|
onSelectedChange: PropTypes.func.isRequired
|
||||||
|
|
|
@ -20,6 +20,7 @@ function MissingRow(props) {
|
||||||
albumType,
|
albumType,
|
||||||
foreignAlbumId,
|
foreignAlbumId,
|
||||||
title,
|
title,
|
||||||
|
disambiguation,
|
||||||
isSelected,
|
isSelected,
|
||||||
columns,
|
columns,
|
||||||
onSelectedChange
|
onSelectedChange
|
||||||
|
@ -55,30 +56,13 @@ function MissingRow(props) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (name === 'episode') {
|
|
||||||
// return (
|
|
||||||
// <TableRowCell
|
|
||||||
// key={name}
|
|
||||||
// className={styles.episode}
|
|
||||||
// >
|
|
||||||
// <SeasonEpisodeNumber
|
|
||||||
// seasonNumber={seasonNumber}
|
|
||||||
// episodeNumber={episodeNumber}
|
|
||||||
// absoluteEpisodeNumber={absoluteEpisodeNumber}
|
|
||||||
// sceneSeasonNumber={sceneSeasonNumber}
|
|
||||||
// sceneEpisodeNumber={sceneEpisodeNumber}
|
|
||||||
// sceneAbsoluteEpisodeNumber={sceneAbsoluteEpisodeNumber}
|
|
||||||
// />
|
|
||||||
// </TableRowCell>
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (name === 'albumTitle') {
|
if (name === 'albumTitle') {
|
||||||
return (
|
return (
|
||||||
<TableRowCell key={name}>
|
<TableRowCell key={name}>
|
||||||
<AlbumTitleLink
|
<AlbumTitleLink
|
||||||
foreignAlbumId={foreignAlbumId}
|
foreignAlbumId={foreignAlbumId}
|
||||||
title={title}
|
title={title}
|
||||||
|
disambiguation={disambiguation}
|
||||||
/>
|
/>
|
||||||
</TableRowCell>
|
</TableRowCell>
|
||||||
);
|
);
|
||||||
|
@ -101,21 +85,6 @@ function MissingRow(props) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (name === 'status') {
|
|
||||||
// return (
|
|
||||||
// <TableRowCell
|
|
||||||
// key={name}
|
|
||||||
// className={styles.status}
|
|
||||||
// >
|
|
||||||
// <EpisodeStatusConnector
|
|
||||||
// albumId={id}
|
|
||||||
// trackFileId={trackFileId}
|
|
||||||
// albumEntity={albumEntities.WANTED_MISSING}
|
|
||||||
// />
|
|
||||||
// </TableRowCell>
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (name === 'actions') {
|
if (name === 'actions') {
|
||||||
return (
|
return (
|
||||||
<AlbumSearchCellConnector
|
<AlbumSearchCellConnector
|
||||||
|
@ -144,6 +113,7 @@ MissingRow.propTypes = {
|
||||||
foreignAlbumId: PropTypes.string.isRequired,
|
foreignAlbumId: PropTypes.string.isRequired,
|
||||||
albumType: PropTypes.string.isRequired,
|
albumType: PropTypes.string.isRequired,
|
||||||
title: PropTypes.string.isRequired,
|
title: PropTypes.string.isRequired,
|
||||||
|
disambiguation: PropTypes.string,
|
||||||
isSelected: PropTypes.bool,
|
isSelected: PropTypes.bool,
|
||||||
columns: PropTypes.arrayOf(PropTypes.object).isRequired,
|
columns: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||||
onSelectedChange: PropTypes.func.isRequired
|
onSelectedChange: PropTypes.func.isRequired
|
||||||
|
|
|
@ -12,6 +12,7 @@ namespace Lidarr.Api.V1.Albums
|
||||||
public class AlbumResource : RestResource
|
public class AlbumResource : RestResource
|
||||||
{
|
{
|
||||||
public string Title { get; set; }
|
public string Title { get; set; }
|
||||||
|
public string Disambiguation { get; set; }
|
||||||
public int ArtistId { get; set; }
|
public int ArtistId { get; set; }
|
||||||
public List<string> AlbumLabel { get; set; }
|
public List<string> AlbumLabel { get; set; }
|
||||||
public string ForeignAlbumId { get; set; }
|
public string ForeignAlbumId { get; set; }
|
||||||
|
@ -66,6 +67,7 @@ namespace Lidarr.Api.V1.Albums
|
||||||
ReleaseDate = model.ReleaseDate,
|
ReleaseDate = model.ReleaseDate,
|
||||||
Genres = model.Genres,
|
Genres = model.Genres,
|
||||||
Title = model.Title,
|
Title = model.Title,
|
||||||
|
Disambiguation = model.Disambiguation,
|
||||||
Images = model.Images,
|
Images = model.Images,
|
||||||
Ratings = model.Ratings,
|
Ratings = model.Ratings,
|
||||||
Duration = model.Duration,
|
Duration = model.Duration,
|
||||||
|
@ -87,6 +89,7 @@ namespace Lidarr.Api.V1.Albums
|
||||||
Id = resource.Id,
|
Id = resource.Id,
|
||||||
ForeignAlbumId = resource.ForeignAlbumId,
|
ForeignAlbumId = resource.ForeignAlbumId,
|
||||||
Title = resource.Title,
|
Title = resource.Title,
|
||||||
|
Disambiguation = resource.Disambiguation,
|
||||||
Images = resource.Images,
|
Images = resource.Images,
|
||||||
Monitored = resource.Monitored,
|
Monitored = resource.Monitored,
|
||||||
CurrentRelease = resource.CurrentRelease
|
CurrentRelease = resource.CurrentRelease
|
||||||
|
|
|
@ -33,6 +33,8 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests
|
||||||
_album = Builder<Album>
|
_album = Builder<Album>
|
||||||
.CreateNew()
|
.CreateNew()
|
||||||
.With(s => s.Title = "Hybrid Theory")
|
.With(s => s.Title = "Hybrid Theory")
|
||||||
|
.With(s => s.AlbumType = "Album")
|
||||||
|
.With(s => s.Disambiguation = "The Best Album")
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
|
|
||||||
|
@ -147,6 +149,24 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests
|
||||||
.Should().Be("Hybrid Theory");
|
.Should().Be("Hybrid Theory");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_replace_Album_Type()
|
||||||
|
{
|
||||||
|
_namingConfig.StandardTrackFormat = "{Album Type}";
|
||||||
|
|
||||||
|
Subject.BuildTrackFileName(new List<Track> { _track1 }, _artist, _album, _trackFile)
|
||||||
|
.Should().Be("Album");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_replace_Album_Disambiguation()
|
||||||
|
{
|
||||||
|
_namingConfig.StandardTrackFormat = "{Album Disambiguation}";
|
||||||
|
|
||||||
|
Subject.BuildTrackFileName(new List<Track> { _track1 }, _artist, _album, _trackFile)
|
||||||
|
.Should().Be("The Best Album");
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void should_replace_Album_underscore_Title()
|
public void should_replace_Album_underscore_Title()
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
using FluentMigrator;
|
||||||
|
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Datastore.Migration
|
||||||
|
{
|
||||||
|
[Migration(18)]
|
||||||
|
public class album_disambiguation : NzbDroneMigrationBase
|
||||||
|
{
|
||||||
|
protected override void MainDbUpgrade()
|
||||||
|
{
|
||||||
|
Alter.Table("Albums").AddColumn("Disambiguation").AsString().Nullable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,6 +19,7 @@ namespace NzbDrone.Core.MetadataSource.SkyHook.Resource
|
||||||
public DateTime ReleaseDate { get; set; }
|
public DateTime ReleaseDate { get; set; }
|
||||||
public List<ImageResource> Images { get; set; }
|
public List<ImageResource> Images { get; set; }
|
||||||
public string Title { get; set; }
|
public string Title { get; set; }
|
||||||
|
public string Disambiguation { get; set; }
|
||||||
public string Overview { get; set; }
|
public string Overview { get; set; }
|
||||||
public List<string> Genres { get; set; }
|
public List<string> Genres { get; set; }
|
||||||
public List<string> Labels { get; set; }
|
public List<string> Labels { get; set; }
|
||||||
|
|
|
@ -262,6 +262,7 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
|
||||||
{
|
{
|
||||||
Album album = new Album();
|
Album album = new Album();
|
||||||
album.Title = resource.Title;
|
album.Title = resource.Title;
|
||||||
|
album.Disambiguation = resource.Disambiguation;
|
||||||
album.ForeignAlbumId = resource.Id;
|
album.ForeignAlbumId = resource.Id;
|
||||||
album.ReleaseDate = resource.ReleaseDate;
|
album.ReleaseDate = resource.ReleaseDate;
|
||||||
album.CleanTitle = Parser.Parser.CleanArtistName(album.Title);
|
album.CleanTitle = Parser.Parser.CleanArtistName(album.Title);
|
||||||
|
|
|
@ -22,6 +22,7 @@ namespace NzbDrone.Core.Music
|
||||||
public string ForeignAlbumId { get; set; }
|
public string ForeignAlbumId { get; set; }
|
||||||
public int ArtistId { get; set; }
|
public int ArtistId { get; set; }
|
||||||
public string Title { get; set; }
|
public string Title { get; set; }
|
||||||
|
public string Disambiguation { get; set; }
|
||||||
public string CleanTitle { get; set; }
|
public string CleanTitle { get; set; }
|
||||||
public DateTime? ReleaseDate { get; set; }
|
public DateTime? ReleaseDate { get; set; }
|
||||||
public List<string> Label { get; set; }
|
public List<string> Label { get; set; }
|
||||||
|
|
|
@ -92,6 +92,7 @@ namespace NzbDrone.Core.Music
|
||||||
album.LastInfoSync = DateTime.UtcNow;
|
album.LastInfoSync = DateTime.UtcNow;
|
||||||
album.CleanTitle = albumInfo.CleanTitle;
|
album.CleanTitle = albumInfo.CleanTitle;
|
||||||
album.Title = albumInfo.Title ?? "Unknown";
|
album.Title = albumInfo.Title ?? "Unknown";
|
||||||
|
album.Disambiguation = albumInfo.Disambiguation;
|
||||||
album.AlbumType = albumInfo.AlbumType;
|
album.AlbumType = albumInfo.AlbumType;
|
||||||
album.SecondaryTypes = albumInfo.SecondaryTypes;
|
album.SecondaryTypes = albumInfo.SecondaryTypes;
|
||||||
album.Genres = albumInfo.Genres;
|
album.Genres = albumInfo.Genres;
|
||||||
|
|
|
@ -189,6 +189,7 @@
|
||||||
<Compile Include="Datastore\Migration\015_remove_fanzub.cs" />
|
<Compile Include="Datastore\Migration\015_remove_fanzub.cs" />
|
||||||
<Compile Include="Datastore\Migration\016_update_artist_history_indexes.cs" />
|
<Compile Include="Datastore\Migration\016_update_artist_history_indexes.cs" />
|
||||||
<Compile Include="Datastore\Migration\017_remove_nma.cs" />
|
<Compile Include="Datastore\Migration\017_remove_nma.cs" />
|
||||||
|
<Compile Include="Datastore\Migration\018_album_disambiguation.cs" />
|
||||||
<Compile Include="Datastore\Migration\Framework\MigrationContext.cs" />
|
<Compile Include="Datastore\Migration\Framework\MigrationContext.cs" />
|
||||||
<Compile Include="Datastore\Migration\Framework\MigrationController.cs" />
|
<Compile Include="Datastore\Migration\Framework\MigrationController.cs" />
|
||||||
<Compile Include="Datastore\Migration\Framework\MigrationDbFactory.cs" />
|
<Compile Include="Datastore\Migration\Framework\MigrationDbFactory.cs" />
|
||||||
|
|
|
@ -269,6 +269,12 @@ namespace NzbDrone.Core.Organizer
|
||||||
tokenHandlers["{Album CleanTitle}"] = m => CleanTitle(album.Title);
|
tokenHandlers["{Album CleanTitle}"] = m => CleanTitle(album.Title);
|
||||||
tokenHandlers["{Album TitleThe}"] = m => TitleThe(album.Title);
|
tokenHandlers["{Album TitleThe}"] = m => TitleThe(album.Title);
|
||||||
tokenHandlers["{Album Type}"] = m => album.AlbumType;
|
tokenHandlers["{Album Type}"] = m => album.AlbumType;
|
||||||
|
|
||||||
|
if (album.Disambiguation != null)
|
||||||
|
{
|
||||||
|
tokenHandlers["{Album Disambiguation}"] = m => album.Disambiguation;
|
||||||
|
}
|
||||||
|
|
||||||
if (album.ReleaseDate.HasValue)
|
if (album.ReleaseDate.HasValue)
|
||||||
{
|
{
|
||||||
tokenHandlers["{Release Year}"] = m => album.ReleaseDate.Value.Year.ToString();
|
tokenHandlers["{Release Year}"] = m => album.ReleaseDate.Value.Year.ToString();
|
||||||
|
|
|
@ -38,6 +38,7 @@ namespace NzbDrone.Core.Organizer
|
||||||
Title = "The Album Title",
|
Title = "The Album Title",
|
||||||
ReleaseDate = System.DateTime.Today,
|
ReleaseDate = System.DateTime.Today,
|
||||||
AlbumType = "Album",
|
AlbumType = "Album",
|
||||||
|
Disambiguation = "The Best Album",
|
||||||
Media = new List<Medium>
|
Media = new List<Medium>
|
||||||
{
|
{
|
||||||
new Medium
|
new Medium
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue