@@ -3781,6 +3781,129 @@ def migration_036_add_episodecount_column(conn, db_type: str):
37813781 cursor .close ()
37823782
37833783
3784+ @register_migration ("037" , "add_saved_folders_functionality" , "Add saved folders functionality to organize saved episodes" , requires = ["007" ])
3785+ def migration_037_add_saved_folders (conn , db_type : str ):
3786+ """Create SavedFolders and SavedEpisodeFolders tables for organizing saved episodes
3787+
3788+ This migration adds the ability for users to organize their saved episodes into folders.
3789+ Features include:
3790+ - Custom folders with names, colors, and icons
3791+ - Episodes can belong to multiple folders
3792+ - Auto-categorization based on podcast categories
3793+ - Position ordering for folder display
3794+ """
3795+ cursor = conn .cursor ()
3796+
3797+ try :
3798+ logger .info ("Creating saved folders tables" )
3799+
3800+ if db_type == "postgresql" :
3801+ # Create SavedFolders table
3802+ cursor .execute ("""
3803+ CREATE TABLE IF NOT EXISTS "SavedFolders" (
3804+ folderid SERIAL PRIMARY KEY,
3805+ userid INT NOT NULL,
3806+ foldername VARCHAR(255) NOT NULL,
3807+ foldercolor VARCHAR(50),
3808+ iconname VARCHAR(100) DEFAULT 'ph-folder',
3809+ autoaddcategory VARCHAR(255),
3810+ position INT DEFAULT 0,
3811+ created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
3812+ lastupdated TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
3813+ FOREIGN KEY (userid) REFERENCES "Users"(userid) ON DELETE CASCADE,
3814+ UNIQUE(userid, foldername)
3815+ )
3816+ """ )
3817+ logger .info ("Created SavedFolders table (PostgreSQL)" )
3818+
3819+ # Create SavedEpisodeFolders junction table
3820+ cursor .execute ("""
3821+ CREATE TABLE IF NOT EXISTS "SavedEpisodeFolders" (
3822+ savedepisodefolderid SERIAL PRIMARY KEY,
3823+ saveid INT NOT NULL,
3824+ folderid INT NOT NULL,
3825+ dateadded TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
3826+ FOREIGN KEY (saveid) REFERENCES "SavedEpisodes"(saveid) ON DELETE CASCADE,
3827+ FOREIGN KEY (folderid) REFERENCES "SavedFolders"(folderid) ON DELETE CASCADE,
3828+ UNIQUE(saveid, folderid)
3829+ )
3830+ """ )
3831+ logger .info ("Created SavedEpisodeFolders junction table (PostgreSQL)" )
3832+
3833+ # Create indexes for better performance
3834+ cursor .execute ("""
3835+ CREATE INDEX IF NOT EXISTS idx_saved_folders_userid ON "SavedFolders"(userid);
3836+ CREATE INDEX IF NOT EXISTS idx_saved_folders_position ON "SavedFolders"(userid, position);
3837+ CREATE INDEX IF NOT EXISTS idx_saved_episode_folders_saveid ON "SavedEpisodeFolders"(saveid);
3838+ CREATE INDEX IF NOT EXISTS idx_saved_episode_folders_folderid ON "SavedEpisodeFolders"(folderid);
3839+ """ )
3840+ logger .info ("Created indexes for saved folders (PostgreSQL)" )
3841+
3842+ else : # MySQL/MariaDB
3843+ # Create SavedFolders table
3844+ cursor .execute ("""
3845+ CREATE TABLE IF NOT EXISTS SavedFolders (
3846+ FolderID INT AUTO_INCREMENT PRIMARY KEY,
3847+ UserID INT NOT NULL,
3848+ FolderName VARCHAR(255) NOT NULL,
3849+ FolderColor VARCHAR(50),
3850+ IconName VARCHAR(100) DEFAULT 'ph-folder',
3851+ AutoAddCategory VARCHAR(255),
3852+ Position INT DEFAULT 0,
3853+ Created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
3854+ LastUpdated TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
3855+ FOREIGN KEY (UserID) REFERENCES Users(UserID) ON DELETE CASCADE,
3856+ UNIQUE KEY unique_user_folder (UserID, FolderName)
3857+ )
3858+ """ )
3859+ logger .info ("Created SavedFolders table (MySQL/MariaDB)" )
3860+
3861+ # Create SavedEpisodeFolders junction table
3862+ cursor .execute ("""
3863+ CREATE TABLE IF NOT EXISTS SavedEpisodeFolders (
3864+ SavedEpisodeFolderID INT AUTO_INCREMENT PRIMARY KEY,
3865+ SaveID INT NOT NULL,
3866+ FolderID INT NOT NULL,
3867+ DateAdded TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
3868+ FOREIGN KEY (SaveID) REFERENCES SavedEpisodes(SaveID) ON DELETE CASCADE,
3869+ FOREIGN KEY (FolderID) REFERENCES SavedFolders(FolderID) ON DELETE CASCADE,
3870+ UNIQUE KEY unique_save_folder (SaveID, FolderID)
3871+ )
3872+ """ )
3873+ logger .info ("Created SavedEpisodeFolders junction table (MySQL/MariaDB)" )
3874+
3875+ # Create indexes for better performance
3876+ try :
3877+ cursor .execute ("CREATE INDEX idx_saved_folders_userid ON SavedFolders(UserID)" )
3878+ except :
3879+ logger .info ("Index idx_saved_folders_userid already exists" )
3880+
3881+ try :
3882+ cursor .execute ("CREATE INDEX idx_saved_folders_position ON SavedFolders(UserID, Position)" )
3883+ except :
3884+ logger .info ("Index idx_saved_folders_position already exists" )
3885+
3886+ try :
3887+ cursor .execute ("CREATE INDEX idx_saved_episode_folders_saveid ON SavedEpisodeFolders(SaveID)" )
3888+ except :
3889+ logger .info ("Index idx_saved_episode_folders_saveid already exists" )
3890+
3891+ try :
3892+ cursor .execute ("CREATE INDEX idx_saved_episode_folders_folderid ON SavedEpisodeFolders(FolderID)" )
3893+ except :
3894+ logger .info ("Index idx_saved_episode_folders_folderid already exists" )
3895+
3896+ logger .info ("Created indexes for saved folders (MySQL/MariaDB)" )
3897+
3898+ logger .info ("Saved folders migration completed successfully" )
3899+
3900+ except Exception as e :
3901+ logger .error (f"Error in migration 037: { e } " )
3902+ raise
3903+ finally :
3904+ cursor .close ()
3905+
3906+
37843907if __name__ == "__main__" :
37853908 # Register all migrations and run them
37863909 register_all_migrations ()
0 commit comments