Skip to content

Commit

Permalink
Merge pull request #149 from mgireesha/148-playlists-take-backup-befo…
Browse files Browse the repository at this point in the history
…re-running-every-fresh-library-build

Playlists - take backup before running every fresh library build
  • Loading branch information
mgireesha authored May 18, 2024
2 parents 8503950 + c3faadf commit 3f4df1b
Show file tree
Hide file tree
Showing 27 changed files with 631 additions and 49 deletions.
9 changes: 8 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
</parent>
<groupId>com.gmt</groupId>
<artifactId>g-player</artifactId>
<version>2.4.8</version>
<version>2.4.9</version>
<name>G-Player-SB</name>
<description>G-Player-SB</description>
<properties>
Expand Down Expand Up @@ -82,6 +82,13 @@
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.json/json -->
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20240303</version>
</dependency>


</dependencies>
<build>
Expand Down
15 changes: 13 additions & 2 deletions src/g-player-react/src/Components/CommnPopup.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,19 @@ export const CommonPopup = () => {
<div className="popup-footer">
<div className='buttons'>
<button type="button" className="popup-btn-secondary" onClick={closePopup}>Cancel</button>
<button type="button" className={`popup-btn-primary ${commonPopupObj.className} ${commonPopupObj.primaryClassName}`}
onClick={commonPopupObj.dispatchPayload ? ()=>dispatch(commonPopupObj.primaryBtnFun(commonPopupObj.payload)) : ()=>commonPopupObj.primaryBtnFun(commonPopupObj.args)}
<button type="button"
className={`popup-btn-primary ${commonPopupObj.className} ${commonPopupObj.primaryClassName}`}
onClick={
commonPopupObj.dispatchPayload ?
()=>dispatch(commonPopupObj.primaryBtnFun(commonPopupObj.payload))
:
()=>commonPopupObj.primaryBtnFun(
typeof commonPopupObj.args === "function" ?
commonPopupObj.args()
:
commonPopupObj.args
)
}
id={POPUP_PRIMARY_BTN}
>
{commonPopupObj.primaryBtnLabel?commonPopupObj.primaryBtnLabel:"Go"}
Expand Down
2 changes: 1 addition & 1 deletion src/g-player-react/src/Components/Home.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { fetchCurrentSontAndStatus, playASongSucc, setIsShuffle, setMediaVolumeS
import { getCookieDetails, getCookieValue, setCookies } from "./utilities/util";
import { ALBUM, ARTIST, GENRE, LANGUAGE, MAIN_CONTAINER, PLAYLIST, RECENT_PLAYS, TRACK_LIST } from "./redux/GPActionTypes";
import { Route, Routes } from "react-router-dom";
import { Library } from "./library/Library";
import { Library } from "./library/LibraryV2";
import { Search } from "./search/Search";
import { RecentPlays } from "./history/RecentPlays";
import { Playlist } from "./playlist/Playlist";
Expand Down
73 changes: 73 additions & 0 deletions src/g-player-react/src/Components/library/ArtistImageDownload.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import React, { useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { ARTIST_IMG_DOWNLOAD_STATUS, COMPLETED, COMPONENT, RUNNING } from "../redux/GPActionTypes";
import { initiArtistImageDownload, setCommonPopupObj } from "../redux/library/LibraryActions";
import loading_icon from '../images/Loading.gif';

export const ArtistImageDownload = () => {
const dispatch = useDispatch();
const artistImageDownloadSummary = useSelector(state => state.library.artistImageDownloadSummary);

const [artistIImgDownloadStat, setArtistIImgDownloadStat] = useState({});


useEffect(()=>{
if(artistImageDownloadSummary && artistImageDownloadSummary.length > 0){
const status = artistImageDownloadSummary.find(elem => {return elem.name === ARTIST_IMG_DOWNLOAD_STATUS});
setArtistIImgDownloadStat(status);
}
},[artistImageDownloadSummary]);



const initiateArtistImageDownload = () => {
const artistImgDownloadOtnSlct = document.getElementById("ARTIST_IMAGE_DOWNLOAD_OPTIONS_SELECT");
if(!artistImgDownloadOtnSlct){
return false;
}
if(window.confirm("Initiate Download ?")===true){
const tempArtistIImgDownloadStat = {
"name": "ARTIST_IMG_DOWNLOAD_STATUS",
"value": "RUNNING",
"type": "ARTIST_IMG_DOWNLOAD_STATUS"
}
setArtistIImgDownloadStat(tempArtistIImgDownloadStat);
dispatch(initiArtistImageDownload(artistImgDownloadOtnSlct.value));
dispatch(setCommonPopupObj({showPopup: false}));
}
}
const getArtistImgPopupObj = () => ({
showPopup: true,
title: "Download Artist Images",
contentType: COMPONENT,
component: ()=>{
return(
<div className="artist-image-download-popup-content">
<p style={{marginBottom:10}}>Select download option</p>
<select className="gp-select" style={{width:'60%'}} id="ARTIST_IMAGE_DOWNLOAD_OPTIONS_SELECT">
<option value="IGNORE_EXISTING_AND_TRIED_AND_FAILED">Ignore existing and failed in previous download</option>
<option value="DOWNLOAD_ALL">Download all</option>
<option value="DOWNLOAD_ALL_AND_OVERRIDE">Download all - Override existing</option>
<option value="DOWNLOAD_LATEST" disabled>Download latest</option>
</select>
</div>
)
},
primaryBtnFun: initiateArtistImageDownload,
primaryBtnLabel: "Download"
})
return(
<div className="library-artist-download">
<label>Download Artist Images</label>
<p style={{marginTop:10}}>Download Status: &nbsp;
<>
{artistIImgDownloadStat && artistIImgDownloadStat.value === RUNNING && <>{RUNNING} <img src={loading_icon} style={{height:12}} /></>}
{artistIImgDownloadStat && artistIImgDownloadStat.value === COMPLETED && COMPLETED}
</>
</p>
<div className="btn-container">
<a className="library-btn" onClick={()=>dispatch(setCommonPopupObj(getArtistImgPopupObj()))}>Initiate Download</a>
</div>
</div>
);
}
104 changes: 104 additions & 0 deletions src/g-player-react/src/Components/library/BuildLibrary.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import React, { useEffect, useState } from "react";
import { ARTIST_IMG_DOWNLOAD_STATUS, BUILD_STATUS, COMPLETED, COMPONENT, CURRENT_PAGE, GP_LIBRARY_DESCRIPTION, GP_LIBRARY_DESC_TEXT_1, INIT, INITIATED, LIBRARY, LIBRARY_BUILD, LIBRARY_LABEL, MUSIC_PATH, RUNNING } from "../redux/GPActionTypes";
import { fetchBuildStatusSucc, initLibraryBuild, setCommonPopupObj } from "../redux/library/LibraryActions";
import { useDispatch, useSelector } from "react-redux";
import { setCookies } from "../utilities/util";
import loading_icon from '../images/Loading.gif';
import { BuildLibraryPopup } from "./BuildLibraryPopup";


export const BuildLibrary = () => {
const dispatch = useDispatch();

const buildStatusList = useSelector(state => state.library.buildStatus);

const [isBuildRunning, setIsBuildRunning] = useState(false);
const [isBuildInit, setIsBuildInit] = useState(false);
const [buildStatusL, setBuildStatusL] = useState(null);

useEffect(()=>{
if(buildStatusList.length > 0){
const buildStatus = [...buildStatusList].find(bs=>bs.name===BUILD_STATUS);
if(buildStatus)setIsBuildRunning(buildStatus.value === RUNNING ? true : false);

let tempBuildStatusL = {};
if(buildStatusList.length>0){
buildStatusList.forEach(element => {
tempBuildStatusL[element.name]=element.value;
});
setBuildStatusL(tempBuildStatusL);
}
}
},[buildStatusList])

const onInitLibraryBuild = (isTakePlBkp) => {

if(window.confirm("Build library ?")===true){
dispatch(initLibraryBuild(isTakePlBkp));
const tempBuildStatus = [...buildStatusList].filter(bs=>bs.name!==BUILD_STATUS);
tempBuildStatus.push({
"name": BUILD_STATUS,
"value": RUNNING,
"type": BUILD_STATUS
});
console.log("tempBuildStatus: ",tempBuildStatus)
dispatch(fetchBuildStatusSucc(tempBuildStatus));
setCookies(LIBRARY_BUILD, INITIATED);
}
}
const showBuildLibPopup = () => {
const commonPopupObj = {
showPopup: true,
title: "Build Library",
component: BuildLibraryPopup,
contentType: COMPONENT,
primaryBtnFun: onInitLibraryBuild,
primaryBtnLabel:"Build",
args : () => {
return document.getElementById("build_playlist_backup_chkbox").checked;
}

}
const buildStatus = [...buildStatusList].find(bs=>bs.name===BUILD_STATUS);
buildStatus.value=INIT;
const tempBuildStatus = [...buildStatusList].filter(bs=>bs.name!==BUILD_STATUS);
tempBuildStatus.push(buildStatus);
dispatch(fetchBuildStatusSucc(tempBuildStatus));
dispatch(setCommonPopupObj(commonPopupObj));
}
return(
<div className="library-build">
<h4>Build Library</h4>
<div className="content">
<p>{GP_LIBRARY_DESCRIPTION}</p>
<p>{GP_LIBRARY_DESC_TEXT_1}</p>
</div>
<div className="status">
{!isBuildRunning && buildStatusL &&
<div className="completed">
<label>Summary of current build</label>
<label><span>Total tracks</span><span>:&nbsp;&nbsp;&nbsp;&nbsp;{buildStatusL.TOTAL_TRACKS}</span></label>
<label><span>Total albums</span><span>:&nbsp;&nbsp;&nbsp;&nbsp;{buildStatusL.ALBUM_COUNT}</span></label>
<label><span>Artists found</span><span>:&nbsp;&nbsp;&nbsp;&nbsp;{buildStatusL.ARTIST_COUNT}</span></label>
<label><span>Album Artists found</span><span>:&nbsp;&nbsp;&nbsp;&nbsp;{buildStatusL.ALBUM_ARTIST_COUNT}</span></label>
<label><span>Time took to finish</span><span>:&nbsp;&nbsp;&nbsp;&nbsp;{Math.floor(buildStatusL.FILES_READ_TIME/1000)} Secs</span></label>
</div>
}
{isBuildRunning && buildStatusL &&
<div className="running">
<label>Status</label>
{!isBuildInit && <>
<label><span>Rading files:</span><span>{buildStatusL.FILES_TO_READ} remaining.</span></label>
<label><span>Build status:</span><span>{buildStatusL.BUILD_STATUS}&nbsp;<img src={loading_icon} style={{height:12}} /></span></label>
<label><span style={{width:'100%'}}>{buildStatusL.BUILD_STATUS_STEP}</span></label>
</>}
{isBuildInit && <label><span>Build Initiated</span></label>}
</div>
}
</div>
<div className="btn-container">
<a className={!isBuildRunning?"library-btn":"library-btn disabled-click"} onClick={showBuildLibPopup}>Build Library</a>
</div>
</div>
);
}
48 changes: 48 additions & 0 deletions src/g-player-react/src/Components/library/BuildLibraryPopup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import React, { useEffect, useState } from "react";
import { ARTIST_IMG_DOWNLOAD_STATUS, BUILD_STATUS, COMPLETED, COMPONENT, CURRENT_PAGE, GP_LIBRARY_DESCRIPTION, GP_LIBRARY_DESC_TEXT_1, INIT, INITIATED, LIBRARY, LIBRARY_BUILD, LIBRARY_LABEL, MUSIC_PATH, RUNNING } from "../redux/GPActionTypes";
import { initLibraryBuild, setCommonPopupObj } from "../redux/library/LibraryActions";
import { useDispatch, useSelector } from "react-redux";
import { setCookies } from "../utilities/util";
import loading_icon from '../images/Loading.gif';
import { Spinner } from "../utilities/Spinner";


export const BuildLibraryPopup = () => {
const dispatch = useDispatch();

const buildStatusList = useSelector(state => state.library.buildStatus);
const [isBuildRunning, setIsBuildRunning] = useState(false);
const [isBuildCompleted, setIsBuildCompleted] = useState(false);
const [isBuildInit, setIsBuildInit] = useState(false);

console.log("isBuildRunning:", isBuildRunning)

useEffect(()=>{
if(buildStatusList.length > 0){
const buildStatus = [...buildStatusList].find(bs=>bs.name===BUILD_STATUS);
if(buildStatus){
setIsBuildRunning(buildStatus.value === RUNNING ? true : false);
setIsBuildCompleted(buildStatus.value === COMPLETED ? true : false);
setIsBuildInit(buildStatus.value === INIT ? true : false);
}
}
console.log("buildStatusList: ",buildStatusList)
},[buildStatusList])

useEffect(()=>{
if(isBuildCompleted)dispatch(setCommonPopupObj({
showPopup: false
}));
},[isBuildCompleted])
return (
<>
{!isBuildRunning &&
<div className="flexbox-align-center" style={{columnGap:10}}>
<span>Take backup of playlists before build ?</span>
<input type="checkbox" id="build_playlist_backup_chkbox" className="custom-checkbox" style={{border:'1px solid', borderRadius:3}} />
</div>
}
{(isBuildRunning) && <div className="flex-align-center-100"><Spinner spinnerInp={{classSize:'sm', text:"Builing"}} /></div>}
</>
);
}
35 changes: 35 additions & 0 deletions src/g-player-react/src/Components/library/LibraryV2.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import React, { useEffect, useState } from "react";

import { useDispatch } from "react-redux";
import { fetchBuildStatus, fetchMessagesByType, fetchMusicPath} from "../redux/library/LibraryActions";
import { ARTIST_IMG_DOWNLOAD_STATUS,bCURRENT_PAGE, CURRENT_PAGE, LIBRARY, LIBRARY_LABEL} from "../redux/GPActionTypes";

import { Header } from "../header/Header";
import { setCookies } from "../utilities/util";
import { ArtistImageDownload } from "./ArtistImageDownload";
import { MusicLibraryPath } from "./MusicLibraryPath";
import { BuildLibrary } from "./BuildLibrary";

export const Library = () => {

const dispatch = useDispatch();

useEffect(()=>{
dispatch(fetchMusicPath());
dispatch(fetchBuildStatus());
setCookies(CURRENT_PAGE, JSON.stringify({type:LIBRARY}));
dispatch(fetchMessagesByType(ARTIST_IMG_DOWNLOAD_STATUS));
},[])


return(
<div className="library-v2">
<Header headerLbl={LIBRARY_LABEL} />
<div className="body">
<BuildLibrary />
<MusicLibraryPath />
<ArtistImageDownload />
</div>
</div>
);
}
54 changes: 54 additions & 0 deletions src/g-player-react/src/Components/library/MusicLibraryPath.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import React, { useEffect } from "react";
import { MUSIC_PATH } from "../redux/GPActionTypes";
import { useDispatch, useSelector } from "react-redux";
import { deleteMusicPath, saveMusicPath } from "../redux/library/LibraryActions";
import {RiDeleteBinLine} from 'react-icons/ri';
import { LIBRARY_SAVE_MUSIC_PATH_SUCCESS } from "../redux/library/LibraryActionTypes";

export const MusicLibraryPath = () => {
const dispatch = useDispatch();

const musicPaths = useSelector(state => state.library.musicPaths);
const libraryPhase = useSelector(state => state.library.phase);

useEffect(()=>{
if(libraryPhase===LIBRARY_SAVE_MUSIC_PATH_SUCCESS){
document.getElementById('music_path').value = "";
}
},[libraryPhase]);

const onSaveMusicPath = () => {
const mPath = document.getElementById('music_path').value;
if(mPath===""){
alert("Path cannot be empty");
return;
}
const musicPath = {
name : MUSIC_PATH,
type: MUSIC_PATH,
value: mPath
}
try {
dispatch(saveMusicPath(musicPath));
} catch (error) {
console.log(error)
}
}
return(
<div className="library-list">
<h4>Library List</h4>
<div className="content">
<p>Add all the music folders' full path.</p>
<div className="input-container">
<input id="music_path" placeholder="Paste music path" />
<a className="library-btn" onClick={onSaveMusicPath}>Add</a>
</div>
</div>
<div className="existing-lib-paths">
{musicPaths && musicPaths.map((musicPath, index)=>
<label key={index}>{musicPath.value}<RiDeleteBinLine onClick={()=>dispatch(deleteMusicPath(musicPath))} /></label>
)}
</div>
</div>
);
}
7 changes: 6 additions & 1 deletion src/g-player-react/src/Components/main.scss
Original file line number Diff line number Diff line change
Expand Up @@ -1970,7 +1970,7 @@ a.disabled-click{
height: 74%;
}

.library {
.library, .library-v2 {
width: 78vw;
.header{
margin-left: 10px;
Expand Down Expand Up @@ -3185,6 +3185,11 @@ a.disabled-click{
align-items: center;
justify-content: center;
}

.flexbox-align-center{
display: flex;
align-items: center;
}
//common classes - end
//GLobal components styling - end

Expand Down
Loading

0 comments on commit 3f4df1b

Please sign in to comment.