{"version":3,"sources":["generic/ExclusiveButtonGroup.tsx","util/windowDimensions.ts","track/TrackHeader.tsx","generic/ChipGroup.tsx","util/util_api.js","dtos/base.dto.ts","dtos/keyword.dto.ts","dtos/nethost.dto.ts","util/utilities.ts","dtos/trackoverview.dto.ts","dtos/trackdetail.dto.ts","dtos/release.dto.ts","dtos/trackonnethost.dto.ts","dtos/releaseGroupOnNetHost.dto.ts","api/api_keyword.ts","track/TrackFilterParams.tsx","util/track.util.ts","track/TrackTable.tsx","util/css.util.ts","track/TrackBrowser.tsx","track/ReleaseNameDisplay.tsx","track/TrackInfo.tsx","api/api_nethost.ts","embed/EmbedButtons.tsx","embed/BandcampEmbed.tsx","embed/SoundCloudEmbed.tsx","embed/YouTubeEmbed.tsx","embed/SpotifyEmbed.tsx","embed/AppleMusicEmbed.tsx","track/TrackDetail.tsx","api/api_track.ts","util/util_embed.js","track/ReleaseGroupsOnNetHost.tsx","track/TracksPageComponent.tsx","api/api_release.ts","pages/AboutCylob.tsx","pages/AboutCylobIndustries.tsx","pages/AboutThisWebsite.tsx","pages/AboutHistory.tsx","pages/AboutEasterEggs.tsx","pages/AboutPage.tsx","SiteHeader.tsx","App.js","serviceWorker.js","util/history.js","index.js"],"names":["ExclusiveButtonGroup","props","buttonWasClicked","index","optionWasSelected","buttonGroup","useIcons","optionIcons","ButtonGroup","map","icon","variant","selectedIndex","Button","style","width","key","color","size","buttonSize","disableElevation","onClick","optionNames","name","getWindowDimensions","window","innerWidth","height","innerHeight","useWindowDimensions","useState","windowDimensions","setWindowDimensions","useEffect","handleResize","addEventListener","removeEventListener","useStyles","makeStyles","header","innerWrapper","randomButton","buttonsWrapper","margin","tracksText","fontWeight","fontSize","maxWidth","TrackHeader","classes","selectedTableIndex","setSelectedTableIndex","totalDurationString","setTotalDurationString","originalTableOptionNames","findIndex","optionName","selectedUserOption","Date","totalDurationInSecs","toISOString","substr","thisWidth","showTotals","buttonStyle","paddingTop","randomLegend","tableOptionIcons","id","className","totalNoOfTracks","onUserOptionSelected","Tooltip","title","aria-label","onRandomTrackRequested","chip","marginRight","marginBottom","ChipGroupComponent","handleDelete","chipDeletedAtIndex","chipNames","splice","chipNamesUpdated","removeChipAtIndex","chipName","Chip","label","canClick","chipNameWasClicked","handleChipClicked","undefined","onDelete","canDelete","sendRequest","method","endpoint","a","params","token","url","process","headers","fetchParams","mode","cache","credentials","redirect","referrerPolicy","body","JSON","stringify","fetch","response","Base","this","object","instance","Keyword","NetHost","baseAddr","iconFileName","Object","assign","stringIsEmptyOrNull","str","length","match","getPaddedString","num","noOfPlaces","s","TrackOverview","trackId","count","artistName","bpm","isEasterEgg","_titleMain","_titleSecondary","_displayTitle","keywordIds","Array","visible","_durationSecs","_displayDuration","titleMain","titleSecondary","getDisplayTitle","durationSecs","showHours","hours","Math","floor","h","minutes","m","getDisplayDuration","other","propertyName","thisProperty","otherProperty","displayTitle","displayDuration","result","newVal","_updateDisplayTitle","_updateDisplayDuration","dto","TrackDetail","artistId","trackOverview","remixOfTrackId","remixArtistId","artistIdSecondary","createFromDto","Release","versionDescription","releaseGroupId","catNo","releaseDate","labelId","TrackOnNetHost","netHostId","embeddedInfoJson","ReleaseGroupOnNetHost","linkAddr","keywords","fetchKeywords","onSuccessCallbackFunc","onErrorCallbackFunc","err","getApiBaseAddr","then","json","objects","forEach","keywordObject","keyword","push","error","textAndKeywordSearchWrapper","searchTextField","searchForKeyword","marginTop","TrackFilterParamsComponent","keywordStringsForTrack","setKeywordStringsForTrack","allKeywordStrings","setAllKeywordStrings","currentlyEnteredNewKeyword","setCurrentlyEnteredNewKeyword","keywordTextFieldChanged","event","onKeywordTextFieldKeyPress","e","sort","keywordsChanged","keywordMenu","compact","FormControl","InputLabel","htmlFor","NativeSelect","onChange","target","value","inputProps","k","Autocomplete","options","onInputChange","reason","renderInput","TextField","onKeyPress","filterText","filterTextChanged","IconButton","indexOf","_keywordStringsForTrack","addNewKeyword","randomWords","require","capitalize","lower","toLowerCase","replace","toUpperCase","getReleaseImageSrcForCatNo","getRandomTrackOverview","rndWords","noOfWords","random","i","trim","TrackTable","tableRef","setKeywordIds","filteredResults","setFilteredResults","sortedResults","setSortedResults","sortBy","setSortBy","sortDirection","setSortDirection","updateTableCount","setUpdateTableCount","scrollToIndex","setScrollToIndex","trackIdToTableRowIndexDict","setTrackIdToTableRowIndexDict","showArtist","showTime","showBpm","artistWidth","titleWidth","timeWidth","bpmWidth","tableDisplayParams","setTableDisplayParams","showHeader","setShowHeader","p","tableWidth","tableHeight","totalWidth","uiChangeCount","filterResults","selectedTrackId","trackOverviews","trackUpdateCount","_keywordIds","keywordId","compareName","indexOfKeyword","getKeywordIdForName","sortResults","forceUpdateGrid","_filteredResults","filter","titleSearchTrackFound","otherStr","subStrings","split","includes","stringIsInOtherString","keywordsMatch","trackKeywordIds","thisId","keywordsDoMatch","_sortedResults","trackOverviewArray","b","sortTrackOverviews","_trackIdToTableRowIndexDict","ref","headerHeight","rowHeight","rowCount","rowGetter","indexObject","onRowClick","rowData","trackSelected","rowRenderer","args","defaultRowRenderer","dataKey","outerWidth","element","offsetWidth","getComputedStyle","side","parseInt","reduce","total","respondToParentWidth","wrapperId","onCalcFunc","el","document","getElementById","parentElement","getModalStyles","modalWidth","modalHeight","position","padding","top","left","transform","backgroundColor","overflowY","explainText","TrackBrowserComponent","trackOverviewHistory","setTrackOverviewHistory","similarTracks","setSimilarTracks","trackTableUiChangeCount","setTrackTableUiChangeCount","setTableWidth","setTableHeight","searchIsCompact","setSearchIsCompact","getHistoryIdArray","historyIds","localStorage","getItem","historyIdArray","parse","convertHistoryTrackIdsToTrackOverviewArray","trackIds","find","_tableHeight","_tableWidth","trackBrowserElement","getBoundingClientRect","trackBrowserOptionalUI","offsetHeight","outerHeight","calcTableDimensions","_similarTracks","similarTrackIds","setItem","addTrackToHistory","thisFilterText","thisKeywords","optionalUi","similarDescription","ReleaseNameDisplayComponent","release","includeVersionDescription","LayoutType","paper","propertyText","section","cellKey","minWidth","cellKeyText","cellValue","tableContainer","releaseImg","marginLeft","chipWrapper","chipWrapperClosed","maxHeight","overflow","chipWrapperExpanded","trackDetailsWrapper","inbetweenArtistAndTitle","paddingLeft","paddingRight","getSimilarButtonWrapper","getSimilarButton","viewReleaseButton","imgWrapper","releaseInfos","TrackInfoComponent","chipGroupExpanded","setChipGroupExpanded","keywordsForTrack","setKeywordsForTrack","Wide","layoutType","setLayoutType","elWidth","setElWidth","_elWidth","Narrow","calcLayout","releasesForTrack","releaseId","getReleaseButtonClicked","tableRowInfoArray","displayKey","val","trackDetail","topHalfClassName","wrapperStyle","TableContainer","TableBody","TableRow","TableCell","colSpan","getSimilarButtonClicked","info","src","releaseImgFilePath","keywordWasRequested","netHostArray","fetchNetHosts","res","netHost","console","log","button","buttonContainerDiv","buttonDivDisabled","buttonDiv","paddingBottom","border","borderRadius","buttonDivAvailable","buttonDivActive","EmbedButtons","netHostAvailable","setNetHostAvailable","nameChoices","toolTipLabels","availableNetHostNames","setAvailableNetHostNames","selectedName","setSelectedName","setNetHostArray","_netHostArray","availableNetHostIds","_availableNetHostNames","n","calcAvailableNetHostNames","available","selectedNetHostId","disabled","data-name","buttonName","currentTarget","getAttribute","selectedNetHost","netHostWasSelectedWithId","buttonClicked","Icon","BandcampEmbed","embedWidth","setEmbedWidth","srcString","setSrcString","setTimeout","iframeTitle","trackLinkId","_srcString","albumId","iframeStyle","seamless","href","SoundCloudEmbed","iframeWidth","setIframeWidth","iframeHeight","setIframeHeight","visual","setVisual","scrolling","frameBorder","allow","YouTubeEmbed","videoId","embedWrapper","SpotifyEmbed","albumCode","AppleMusicEmbed","appleWrapperWidth","setAppleWrapperWidth","splitSrc","frameTitle","appleMusicWrapperStyle","background","sandbox","Alert","elevation","noTrackSelectedWrapper","textAlign","allWrapper","embed","trackDetailWrapper","returnButtonWrapper","TrackDetailComponent","embeddedInfoRenderArray","setEmbeddedInfoRenderArray","snackbarIsOpen","setSnackbarIsOpen","snackbarSeverity","snackbarMessage","setAvailableNetHostIds","setTrackDetail","setReleasesForTrack","setReleaseImgFilePath","showListenText","setShowListenText","handleSnackbarClose","fetchTrackDetail","_trackDetail","_keywordsForTrack","getKeywordNameForId","releases","getReleasesForTrackId","filePath","fetchTrack","catch","fetchAvailableEmbedHostIdsForTrack","dtos","trackOnNetHostArray","trackOnNetHost","fetchEmbedInfosForTrackAndHost","_embeddedInfoRenderArray","render","embeddedInfo","netHostName","videoCode","trackCode","getRenderForEmbeddedInfo","fetchEmbedInfos","displayed","showModalCloseButton","onClose","similarWasRequested","r","releaseWasRequested","Snackbar","open","autoHideDuration","severity","tracksOnReleaseText","linkImg","linksWrapper","linkWrapper","linkText","mainWrapper","doneButtonWrapper","ReleaseGroupsOnNetHostComponent","imgSrc","releaseGroupOnNetHostArray","releaseGroupOnNetHost","linkImgSrc","getImgSrcForNetHostWithId","getNetHostNameForId","releaseImgSmall","buyButton","loadingWaitWrapper","loadingText","TracksPageComponent","setTrackOverviews","setTrackUpdateCount","netHosts","setNetHosts","setSelectedNetHostId","setSimilarTrackIds","setSimilarDescription","trackIdBreadcrumbs","setSelectedTrackId","setSelectedUserOption","buyModalIsOpen","setBuyModalIsOpen","setFilterText","setKeywords","currentlySelectedRelease","setCurrentlySelectedRelease","setReleaseGroupOnNetHostArray","displayLoadingSpinner","setDisplayLoadingSpinner","setTotalDurationInSecs","detailAppearsInModal","setDetailAppearsInModal","detailModalIsOpen","setDetailModalIsOpen","performFetchTrackOverviews","results","entry","fetchTrackOverviews","handleBuyClicked","handleBuyOnClose","_totalDurationInSecs","modalStyles","displayDetail","trackDetailStyle","trackHeader","getIdOfRandomTrack","userOption","trackDetailComponent","noOfItems","fetchSimilarTrackIds","t","releaseGroupOnNetHostSortFunc","getReleaseGroupOnNetHostsForRelease","releaseCanBeBought","getTrackIdsForReleaseWithId","imgClassName","fetchTrackIdsForRelease","_keywords","trackBrowserComponent","CircularProgress","_filterText","tracksPageWrapperStyle","display","Modal","AboutCylobComponent","storeWrapper","AboutCylobIndustriesComponent","getImgSrcForNetHostWithName","linkDetails","displayName","link","details","AboutThisWebsiteComponent","AboutHistoryComponent","AboutEasterEggsComponent","wrapper","listWrapper","list","selectedBackground","infoTextWrapper","returnButton","AboutPageComponent","visibleSectionIndex","setVisibleSectionIndex","showAboutInModal","setShowAboutInModal","modalIsOpen","setModalIsOpen","handleModalClose","visibleSection","component","listItem","ListItem","handleButtonClicked","ListItemText","primary","Divider","appBar","boxShadow","borderBottom","logo","navTabWrapper","selectedTab","copyrightNotice","YellowTabs","withStyles","indicator","Tabs","SiteHeaderComponent","history","useHistory","location","useLocation","routeArray","navTabIndex","setNavTabIndex","a11yProps","pathname","showCopyright","showLogo","logoWidth","logoHeight","viewBox","x","y","preserveAspectRatio","in","stdDeviation","d","stroke","strokeWidth","fill","AppBar","newValue","Tab","App","path","Boolean","hostname","createBrowserHistory","ReactDOM","navigator","serviceWorker","ready","registration","unregister"],"mappings":"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","file":"static/js/main.900b46be.chunk.js","sourcesContent":["import React, {useState, useEffect } from 'react';\r\n\r\nimport Button from '@material-ui/core/Button';\r\nimport ButtonGroup from '@material-ui/core/ButtonGroup';\r\n\r\ninterface ExclusiveButtonGroupProps {\r\n optionNames: Array;\r\n optionIcons?: Array;\r\n useIcons: boolean;\r\n selectedIndex: number;\r\n buttonSize: \"small\" | \"medium\" | \"large\";\r\n optionWasSelected: (selectedIndex: number) => any\r\n}\r\n\r\nexport default function ExclusiveButtonGroup(props: ExclusiveButtonGroupProps) {\r\n\r\n function buttonWasClicked(index: number) {\r\n props.optionWasSelected(index);\r\n }\r\n let buttonGroup = null;\r\n if (props.useIcons && props.optionIcons != null) {\r\n buttonGroup = (\r\n {props.optionIcons.map((icon: any, index: number) => {\r\n const variant = index === props.selectedIndex ? \"contained\" : \"outlined\";\r\n return ()\r\n })}\r\n );\r\n } else {\r\n buttonGroup = (\r\n {props.optionNames.map((name: string, index: number) => {\r\n const variant = index === props.selectedIndex ? \"contained\" : \"outlined\";\r\n return ()\r\n })}\r\n );\r\n }\r\n return (
{buttonGroup}
)\r\n}","import { useState, useEffect } from 'react';\r\n\r\nfunction getWindowDimensions() {\r\n const { innerWidth: width, innerHeight: height } = window;\r\n return {\r\n width,\r\n height\r\n };\r\n}\r\n\r\nexport default function useWindowDimensions() {\r\n const [windowDimensions, setWindowDimensions] = useState(getWindowDimensions());\r\n\r\n useEffect(() => {\r\n function handleResize() {\r\n setWindowDimensions(getWindowDimensions());\r\n }\r\n\r\n window.addEventListener('resize', handleResize);\r\n return () => window.removeEventListener('resize', handleResize);\r\n }, []);\r\n\r\n return windowDimensions;\r\n}","import React, { useState, useEffect } from 'react';\r\nimport { makeStyles } from '@material-ui/core/styles';\r\n\r\nimport Button from '@material-ui/core/Button';\r\nimport \"font-awesome/css/font-awesome.css\";\r\n\r\nimport ExclusiveButtonGroup from '../generic/ExclusiveButtonGroup';\r\nimport { UserOption } from './TracksPageComponent';\r\n\r\nimport '../css/TrackHeader.css';\r\nimport '../css/flex.css';\r\nimport { outerWidth } from '../util/css.util';\r\n\r\nimport ListIcon from '@material-ui/icons/List';\r\nimport SearchIcon from '@material-ui/icons/Search';\r\nimport MoreIcon from '@material-ui/icons/More';\r\nimport HistoryIcon from '@material-ui/icons/History';\r\nimport ShuffleIcon from '@material-ui/icons/Shuffle';\r\nimport Tooltip from '@material-ui/core/Tooltip';\r\nimport useWindowDimensions from '../util/windowDimensions';\r\n\r\nconst useStyles = makeStyles({\r\n header: {\r\n width: '100%',\r\n // marginLeft: '20px'\r\n },\r\n innerWrapper: {\r\n // marginRight: '20px',\r\n // backgroundColor: 'green'\r\n },\r\n randomButton: {\r\n // marginRight: '20px'\r\n },\r\n // title: {\r\n // fontSize: '1.8em',\r\n // marginLeft: '50px'\r\n // },\r\n buttonsWrapper: {\r\n width: '470px',\r\n margin: '0px',\r\n // marginTop: '10px'\r\n },\r\n tracksText: {\r\n // marginRight: '20px',\r\n fontWeight: 'bold',\r\n fontSize: '1.0em',\r\n maxWidth: '100px'\r\n }\r\n\r\n});\r\n\r\ninterface TrackHeaderProps {\r\n selectedUserOption: UserOption;\r\n totalNoOfTracks: number;\r\n totalDurationInSecs: number;\r\n onRandomTrackRequested: () => any;\r\n onUserOptionSelected: (userOption: UserOption) => any;\r\n}\r\n\r\n\r\nexport default function TrackHeader(props: TrackHeaderProps) {\r\n const classes = useStyles();\r\n const { height, width } = useWindowDimensions();\r\n const [selectedTableIndex, setSelectedTableIndex] = useState(0);\r\n const [totalDurationString, setTotalDurationString] = useState('');\r\n const originalTableOptionNames = [\"all\", \"search\", \"related\", \"history\"];\r\n const detailOptionNames = [\"detail\", \"keywords\"];\r\n\r\n useEffect(() => {\r\n const index: number = originalTableOptionNames.findIndex((optionName: string) => optionName === props.selectedUserOption);\r\n if (index != -1) {\r\n setSelectedTableIndex(index);\r\n };\r\n }, [props.selectedUserOption]);\r\n\r\n useEffect(() => {\r\n setTotalDurationString(new Date(props.totalDurationInSecs * 1000).toISOString().substr(11, 8));\r\n }, [props.totalDurationInSecs]);\r\n\r\n function userOptionWasSelected(index: number) {\r\n props.onUserOptionSelected(originalTableOptionNames[index] as UserOption);\r\n }\r\n\r\n\r\n function detailOptionWasSelected(index: number) {\r\n\r\n }\r\n\r\n function handleRandomClicked() {\r\n props.onRandomTrackRequested();\r\n }\r\n\r\n // const el: any = document.getElementById(\"track-header-wrapper\");\r\n // const thisWidth = el != null ? outerWidth(el) : 9999;\r\n const thisWidth = width >= 768 ? width * 0.5 : width;\r\n const showTotals: boolean = thisWidth > 600 ? true : false;\r\n const buttonSize = thisWidth >= 480 ? \"medium\" : \"small\";\r\n const buttonsFlex = \"flex-row-space-between-center\";\r\n // thisWidth >= 480 ? \"flex-row-space-between-center\" : \"flex-column-start-center\";\r\n const buttonStyle = thisWidth >= 480 ? {paddingTop: '0px'} : {paddingTop: '10px'};\r\n const randomLegend = thisWidth >= 400 ? \"Random\" : \"Rnd\";\r\n const tableOptionNames = [\"all\", \"search\", \"related\", \"history\"];\r\n const tableOptionIcons = [\r\n , , , \r\n ];\r\n /*\r\nimport ListIcon from '@material-ui/icons/List';\r\nimport SearchIcon from '@material-ui/icons/Search';\r\nimport MoreIcon from '@material-ui/icons/More';\r\nimport HistoryIcon from '@material-ui/icons/History';\r\n */\r\n // thisWidth >= 400 ? : [\"all\", \"srch\", \"rel\", \"hist\"];\r\n return (\r\n
\r\n
\r\n {showTotals ? (
\r\n
{props.totalNoOfTracks} Tracks
\r\n
{totalDurationString}
\r\n
) : null}\r\n {/*
*/}\r\n
\r\n \r\n
\r\n
\r\n \r\n \r\n \r\n
\r\n {/*
*/}\r\n
\r\n
\r\n )\r\n \r\n}\r\n","import React from 'react';\r\nimport Chip from '@material-ui/core/Chip';\r\nimport { makeStyles } from '@material-ui/core/styles';\r\n\r\ninterface ChipGroupProps {\r\n chipNames: Array;\r\n canDelete: boolean;\r\n canClick: boolean;\r\n chipDeletedAtIndex?: (index: number) => any;\r\n chipNamesUpdated?: (chipNames: Array) => any;\r\n chipNameWasClicked?: (chipName: string) => any;\r\n}\r\n\r\nconst useStyles = makeStyles({\r\n chip: {\r\n marginRight: '5px',\r\n marginBottom: '5px'\r\n },\r\n});\r\n\r\nexport default function ChipGroupComponent(props: ChipGroupProps) {\r\n\r\n const classes: any = useStyles();\r\n\r\n function handleDelete(index: number) {\r\n removeChipAtIndex(index);\r\n }\r\n function removeChipAtIndex(index: number) {\r\n if (props.chipDeletedAtIndex != null) {\r\n props.chipDeletedAtIndex(index);\r\n const chipNames = [...props.chipNames]; // copy array\r\n chipNames.splice(index, 1);\r\n if (props.chipNamesUpdated != null) {\r\n props.chipNamesUpdated(chipNames);\r\n };\r\n };\r\n }\r\n\r\n function handleChipClicked(index: number) {\r\n if (props.chipNameWasClicked != null) {\r\n props.chipNameWasClicked(props.chipNames[index]);\r\n };\r\n }\r\n\r\n return (
\r\n {props.chipNames.map((chipName, index) => {\r\n\r\n return (\r\n handleChipClicked(index) : undefined}\r\n onDelete={props.canDelete ? () => handleDelete(index) : undefined} />\r\n );\r\n })}\r\n
);\r\n \r\n}\r\n","function getApiBaseAddr() {\r\n //return \"https://localhost:44320/api/\";\r\n // return \"http://dorning44-001-site1.htempurl.com/api/\";\r\n // return \"https://cylobindustries.com/api/\";\r\n return process.env.REACT_APP_API_ADDR;\r\n}\r\n\r\n/*\r\n method: 'POST', 'PUT', 'DELETE'\r\n endpoint: 'track', 'artist', etc....\r\n*/\r\nasync function sendRequest(method, endpoint, params = {}, token) {\r\n const url = getApiBaseAddr() + endpoint;\r\n const headers = {\r\n 'Content-Type': 'application/json'\r\n };\r\n if (token != null) {\r\n headers['Authorization'] = `Bearer ${token}`\r\n };\r\n const fetchParams = {\r\n method,\r\n mode: 'cors',\r\n cache: 'no-cache',\r\n credentials: 'same-origin',\r\n headers,\r\n redirect: 'follow',\r\n referrerPolicy: 'no-referrer'\r\n };\r\n if (method !== 'GET') {\r\n const body = JSON.stringify(params);\r\n fetchParams.body = body;\r\n };\r\n const response = await fetch(url, fetchParams);\r\n //console.log(\"RESPONSE IS...\", response)\r\n return response;\r\n}\r\n\r\nexport { getApiBaseAddr, sendRequest }","export class Base {\r\n id: number = -1;\r\n\r\n static createFromDto(object: any): Base {\r\n const instance = new Base();\r\n instance.id = object.id;\r\n return instance;\r\n }\r\n\r\n public toDto(): Object {\r\n return {\r\n id: this.id\r\n }\r\n }\r\n\r\n}\r\n","import { Base } from './base.dto';\r\n\r\nexport class Keyword extends Base {\r\n name: string = '';\r\n}","import { Base } from './base.dto';\r\n\r\nexport class NetHost extends Base {\r\n name: string = '';\r\n baseAddr: string = '';\r\n iconFileName: string = '';\r\n\r\n static createFromDto(object: any): NetHost {\r\n const instance = new NetHost();\r\n Object.assign(instance, super.createFromDto(object));\r\n instance.name = object.name;\r\n instance.baseAddr = object.baseAddr;\r\n instance.iconFileName = object.iconFileName ?? '';\r\n return instance;\r\n }\r\n}\r\n","\r\nfunction stringIsEmptyOrNull(str: string) {\r\n if (str == null) {\r\n return true;\r\n }\r\n str = str + '';\r\n return (str.length === 0 || str.match(/^ *$/) != null);\r\n}\r\n\r\n// https://stackoverflow.com/questions/2998784/how-to-output-numbers-with-leading-zeros-in-javascript\r\nfunction getPaddedString(num: number, noOfPlaces: number) {\r\n let s = num + \"\";\r\n while (s.length < noOfPlaces) {\r\n s = \"0\" + s;\r\n }\r\n return s;\r\n}\r\n\r\nfunction getDisplayDuration(durationSecs: number, showHours: boolean = true) {\r\n const hours = Math.floor(durationSecs / 3600);\r\n const h = getPaddedString(hours, 2);\r\n let minutes = Math.floor((durationSecs % 3600) / 60);\r\n if (!showHours) {\r\n minutes += (hours * 60);\r\n }\r\n const m = getPaddedString(minutes, 2);\r\n const s = getPaddedString(Math.floor(durationSecs % 3600) % 60, 2);\r\n if (showHours) {\r\n return h + \":\" + m + \":\" + s;\r\n } else {\r\n return m + \":\" + s;\r\n }\r\n}\r\n\r\nfunction getDisplayTitle(titleMain: string, titleSecondary: string) {\r\n let title = titleMain;\r\n if (!stringIsEmptyOrNull(titleSecondary)) {\r\n title += \" (\" + titleSecondary + \")\";\r\n }\r\n return title;\r\n}\r\n/*\r\nreturn TRUE if the elements in str are in otherStr, OR if str is empty/null\r\nexample: otherStr is \"sally robinson\"\r\nstr contains \"sa ins\". in this case true is returned.\r\nallows for search using partial matches based on substrings separated by spaces.\r\n*/\r\nfunction stringIsInOtherString(str: string, otherStr: string) {\r\n if (stringIsEmptyOrNull(str)) {\r\n return true;\r\n }\r\n str = str.toLowerCase();\r\n otherStr = otherStr.toLowerCase();\r\n let subStrings = str.split(\" \");\r\n subStrings = subStrings.filter(s => !stringIsEmptyOrNull(s));\r\n let match = true;\r\n subStrings.forEach((s) => {\r\n match = match && otherStr.includes(s);\r\n })\r\n return match;\r\n}\r\n\r\n// take some kind of param name and return something suitbable for an html id.\r\n// https://stackoverflow.com/questions/1983648/replace-spaces-with-dashes-and-make-all-letters-lower-case\r\nfunction replaceSpacesInString(str: string, replaceWith: string = '-') {\r\n return str.replace(/\\s+/g, replaceWith);\r\n}\r\n\r\nfunction bindNameArray(nameArray: Array, bindTo: any) {\r\n nameArray.forEach(methodName => {\r\n bindTo[methodName] = bindTo[methodName].bind(bindTo);\r\n })\r\n}\r\n\r\nexport { stringIsEmptyOrNull, getPaddedString, getDisplayDuration, getDisplayTitle, stringIsInOtherString, replaceSpacesInString, bindNameArray }","import { Base } from './base.dto';\r\nimport { getDisplayDuration, getDisplayTitle } from '../util/utilities';\r\n\r\nexport class TrackOverview extends Base {\r\n id: number = -1;\r\n trackId: number = -1;\r\n count: number = -1;\r\n artistName: string = '';\r\n bpm: number = 0;\r\n isEasterEgg: boolean = false;\r\n public _titleMain: string = '';\r\n public get titleMain(): string {\r\n return this._titleMain;\r\n }\r\n public set titleMain(newVal: string) {\r\n this._titleMain = newVal;\r\n this._updateDisplayTitle();\r\n }\r\n private _titleSecondary: string = '';\r\n public get titleSecondary(): string {\r\n return this._titleSecondary;\r\n }\r\n public set titleSecondary(newVal: string) {\r\n this._titleSecondary = newVal;\r\n this._updateDisplayTitle();\r\n }\r\n // combined main and secondary in brackets\r\n private _displayTitle: string = '';\r\n public get displayTitle(): string {\r\n \r\n return this._displayTitle;\r\n }\r\n keywordIds = new Array();\r\n visible: boolean = false;\r\n private _durationSecs: number = 0;\r\n public get durationSecs(): number {\r\n return this._durationSecs;\r\n }\r\n public set durationSecs(newVal: number) {\r\n this._durationSecs = newVal;\r\n this._updateDisplayDuration();\r\n }\r\n private _displayDuration: string = '00:00';\r\n public get displayDuration(): string {\r\n return this._displayDuration;\r\n }\r\n\r\n private _updateDisplayTitle() {\r\n this._displayTitle = getDisplayTitle(this._titleMain, this._titleSecondary);\r\n \r\n }\r\n private _updateDisplayDuration() {\r\n this._displayDuration = getDisplayDuration(this.durationSecs);\r\n }\r\n\r\n static createFromDto(dto: any): TrackOverview {\r\n const instance = new TrackOverview();\r\n Object.assign(instance, super.createFromDto(dto));\r\n instance.trackId = dto.trackId;\r\n instance.artistName = dto.artistName;\r\n instance.titleMain = dto.titleMain;\r\n instance.titleSecondary = dto.titleSecondary;\r\n instance.durationSecs = dto.durationSecs;\r\n instance.keywordIds = dto.keywordIds;\r\n instance.visible = dto.visible;\r\n instance.bpm = dto.bpm;\r\n \r\n return instance;\r\n }\r\n\r\n public getSortResult(other: TrackOverview, propertyName: string): number {\r\n let thisProperty: string = '', otherProperty: string = '';\r\n switch (propertyName) {\r\n case \"title\":\r\n thisProperty = this.displayTitle;\r\n otherProperty = other.displayTitle;\r\n break;\r\n case \"artistName\":\r\n thisProperty = this.artistName;\r\n otherProperty = other.artistName;\r\n break;\r\n case \"duration\":\r\n thisProperty = this.displayDuration;\r\n otherProperty = other.displayDuration;\r\n break;\r\n };\r\n let result = 0;\r\n if (thisProperty > otherProperty) {\r\n result = -1;\r\n } else if (thisProperty < otherProperty) {\r\n result = 1;\r\n };\r\n \r\n return result;\r\n }\r\n\r\n}","import { Base } from './base.dto';\r\nimport { TrackOverview } from './trackoverview.dto';\r\n\r\nexport class TrackDetail extends Base {\r\n artistId: number = -1;\r\n trackOverview = new TrackOverview();\r\n remixOfTrackId: number = -1;\r\n remixArtistId: number = -1;\r\n bpm: number = 0;\r\n artistIdSecondary: number = -1;\r\n\r\n static createFromDto(dto: any): TrackDetail {\r\n const instance = new TrackDetail();\r\n Object.assign(instance, super.createFromDto(dto));\r\n instance.artistId = dto.artistId;\r\n instance.trackOverview = TrackOverview.createFromDto(dto.trackOverview);\r\n instance.remixOfTrackId = dto.remixOfTrackId;\r\n instance.remixArtistId = dto.remixArtistId;\r\n instance.bpm = dto.bpm;\r\n instance.artistIdSecondary = dto.artistIdSecondary;\r\n return instance;\r\n }\r\n}","import { Base } from './base.dto';\r\n\r\n// TODO: releaseDate not yet implemented\r\nexport class Release extends Base {\r\n title: string = '';\r\n versionDescription: string = '';\r\n releaseGroupId: number = -1;\r\n catNo: string = '';\r\n // in backend is DateTime instance\r\n releaseDate: any = undefined;\r\n labelId: number = -1;\r\n\r\n public get displayDescription(): string {\r\n return this.title + ' (' + this.versionDescription + ')';\r\n }\r\n\r\n static createFromDto(object: any): Release {\r\n const instance = new Release();\r\n Object.assign(instance, super.createFromDto(object));\r\n instance.title = object.title;\r\n instance.versionDescription = object.versionDescription;\r\n instance.releaseGroupId = object.releaseGroupId;\r\n instance.catNo = object.catNo;\r\n instance.releaseDate = object.releaseDate;\r\n instance.labelId = object.labelId;\r\n return instance;\r\n }\r\n\r\n public toDto(): Object {\r\n const dto: any = super.toDto();\r\n dto.title = this.title;\r\n dto.versionDescription = this.versionDescription;\r\n dto.releaseGroupId = this.releaseGroupId;\r\n dto.catNo = this.catNo;\r\n dto.releaseDate = this.releaseDate;\r\n dto.labelId = this.labelId;\r\n return dto;\r\n }\r\n}","import { Base } from './base.dto';\r\n\r\nexport class TrackOnNetHost extends Base {\r\n netHostId: number = -1;\r\n trackId: number = -1;\r\n embeddedInfoJson: string = '{}';\r\n static createFromDto(dto: any): TrackOnNetHost {\r\n const instance = new TrackOnNetHost();\r\n Object.assign(instance, super.createFromDto(dto));\r\n instance.netHostId = dto.netHostId;\r\n instance.trackId = dto.trackId;\r\n instance.embeddedInfoJson = dto.embeddedInfoJson;\r\n return instance;\r\n }\r\n}","import { Base } from './base.dto';\r\n\r\nexport class ReleaseGroupOnNetHost extends Base {\r\n releaseGroupId: number = -1;\r\n netHostId: number = -1;\r\n linkAddr: string = '';\r\n\r\n static createFromDto(dto: any): ReleaseGroupOnNetHost {\r\n const instance = new ReleaseGroupOnNetHost();\r\n Object.assign(instance, super.createFromDto(dto));\r\n instance.releaseGroupId = dto.releaseGroupId;\r\n instance.netHostId = dto.netHostId;\r\n instance.linkAddr = dto.linkAddr;\r\n return instance;\r\n }\r\n\r\n public toDto(): Object {\r\n const dto: any = super.toDto();\r\n dto.releaseGroupId = this.releaseGroupId;\r\n dto.netHostId = this.netHostId;\r\n dto.linkAddr = this.linkAddr;\r\n return dto;\r\n }\r\n\r\n}","import { \r\n getApiBaseAddr, \r\n // sendRequest \r\n} from '../util/util_api.js';\r\n\r\nimport { Keyword } from '../dtos/dto';\r\n\r\nlet keywords = new Array();\r\n\r\nfunction fetchKeywords(onSuccessCallbackFunc: (keywords: Array) => any, onErrorCallbackFunc = (err: any) => {}) {\r\n if (keywords.length > 0) {\r\n onSuccessCallbackFunc(keywords);\r\n return;\r\n };\r\n fetch (getApiBaseAddr() + 'keyword')\r\n .then(result => result.json())\r\n .then(result => {\r\n keywords = new Array();\r\n const keywordObjects = result.objects;\r\n keywordObjects.forEach((keywordObject: any) => {\r\n const keyword = new Keyword();\r\n keyword.id = keywordObject.id;\r\n keyword.name = keywordObject.name;\r\n keywords.push(keyword);\r\n })\r\n onSuccessCallbackFunc(keywords);\r\n },\r\n error => {\r\n onErrorCallbackFunc(error);\r\n });\r\n\r\n}\r\n\r\nfunction getKeywordNameForId(id: number): string | null {\r\n const indexOfKeyword = keywords.findIndex(keyword => keyword.id === id);\r\n if (indexOfKeyword !== -1) {\r\n return keywords[indexOfKeyword].name;\r\n };\r\n return null;\r\n}\r\n\r\nfunction getKeywordIdForName(name: string): number {\r\n const compareName = name.toLowerCase();\r\n const indexOfKeyword = keywords.findIndex(keyword => keyword.name.toLowerCase() === compareName);\r\n if (indexOfKeyword !== -1) {\r\n return keywords[indexOfKeyword].id;\r\n };\r\n return -1;\r\n}\r\n\r\nexport { fetchKeywords, getKeywordNameForId, getKeywordIdForName }","import React, { useState, useEffect } from 'react';\r\nimport { makeStyles } from '@material-ui/core/styles';\r\nimport TextField from '@material-ui/core/TextField';\r\nimport IconButton from '@material-ui/core/IconButton';\r\nimport ClearIcon from '@material-ui/icons/Clear';\r\nimport AddIcon from '@material-ui/icons/Add';\r\nimport Autocomplete from '@material-ui/lab/Autocomplete';\r\nimport InputLabel from '@material-ui/core/InputLabel';\r\nimport FormHelperText from '@material-ui/core/FormHelperText';\r\nimport FormControl from '@material-ui/core/FormControl';\r\nimport Select from '@material-ui/core/Select';\r\nimport NativeSelect from '@material-ui/core/NativeSelect';\r\n\r\nimport ChipGroup from '../generic/ChipGroup';\r\nimport { fetchKeywords } from '../api/api_keyword';\r\nimport { Keyword } from '../dtos/dto';\r\nimport { stringIsEmptyOrNull } from '../util/utilities';\r\n\r\nimport '../css/flex.css';\r\n\r\nconst useStyles = makeStyles({\r\n textAndKeywordSearchWrapper: {\r\n maxWidth: '600px'\r\n },\r\n searchTextField: {\r\n maxWidth: '250px'\r\n },\r\n searchForKeyword: {\r\n marginTop: '3px'\r\n }\r\n})\r\n\r\ninterface TrackFilterProps {\r\n // filterParams: FilterParams;\r\n filterText: string;\r\n keywords: Array;\r\n filterTextChanged: (filterText: string) => any;\r\n keywordsChanged: (keywords: Array) => any;\r\n // filterParamsChanged: (filterParams: FilterParams) => any;\r\n compact: boolean;\r\n}\r\n\r\nexport default function TrackFilterParamsComponent(props: TrackFilterProps) {\r\n\r\n const classes = useStyles();\r\n\r\n const [keywordStringsForTrack, setKeywordStringsForTrack] = useState>(props.keywords);\r\n const [allKeywordStrings, setAllKeywordStrings] = useState>([]);\r\n const [currentlyEnteredNewKeyword, setCurrentlyEnteredNewKeyword] = useState('');\r\n\r\n useEffect(() => {\r\n fetchKeywords((keywords: Array) => {\r\n setAllKeywordStrings(keywords.map((keyword: Keyword) => keyword.name).sort());\r\n })\r\n }, []);\r\n\r\n useEffect(() => {\r\n props.keywordsChanged(keywordStringsForTrack);\r\n }, [keywordStringsForTrack]);\r\n\r\n useEffect(() => {\r\n setKeywordStringsForTrack(props.keywords);\r\n }, [props.keywords])\r\n\r\n function searchInTitleTextChanged(event: any) {\r\n props.filterTextChanged(event.target.value);\r\n }\r\n function clearButtonClicked() {\r\n // setFilterText('');\r\n props.filterTextChanged('');\r\n }\r\n\r\n function handleKeywordsChanged(keywords: Array) {\r\n props.keywordsChanged(keywords);\r\n }\r\n\r\n function keywordTextFieldChanged(event: any) {\r\n // console.log('keywordTextFieldChanged ', event.target.value);\r\n // setCurrentlyEnteredNewKeyword(event.target.value);\r\n // if (event.key === 'Enter') {\r\n // console.log('enter prezxxed')\r\n // }\r\n }\r\n\r\n function onKeywordTextFieldKeyPress(e: any) {\r\n // console.log('keyword text field key press', e.target.value, e.Key);\r\n // // // prevent form being submitted when return is pressed in the text field\r\n // // if (e.key === 'Enter') {\r\n // // //console.log('onKeywordTextFieldKeyPress, enter pressed')\r\n // // addNewKeyword();\r\n // // }\r\n }\r\n\r\n function onKeywordAutocompleteChange(event: any, value: string, reason: string) {\r\n // console.log('onKeywordAutocompleteChange', event.target.value, value, reason);\r\n if (reason === 'reset') {\r\n setCurrentlyEnteredNewKeyword(value);\r\n }\r\n }\r\n\r\n function onKeywordMenuChange(event: any) {\r\n if (event.target.value != null) {\r\n setCurrentlyEnteredNewKeyword(event.target.value);\r\n };\r\n }\r\n\r\n function addKeywordButtonClicked() {\r\n addNewKeyword();\r\n }\r\n\r\n function addNewKeyword() {\r\n if (\r\n !stringIsEmptyOrNull(currentlyEnteredNewKeyword) &&\r\n keywordStringsForTrack.indexOf(currentlyEnteredNewKeyword) === -1) {\r\n const _keywordStringsForTrack = [...keywordStringsForTrack];\r\n _keywordStringsForTrack.push(currentlyEnteredNewKeyword);\r\n setKeywordStringsForTrack(_keywordStringsForTrack);\r\n };\r\n }\r\n\r\n function handleRemoveKeywordAtIndex(index: number) {\r\n const _keywordStringsForTrack = [...keywordStringsForTrack];\r\n _keywordStringsForTrack.splice(index, 1);\r\n setKeywordStringsForTrack(_keywordStringsForTrack);\r\n }\r\n\r\n let keywordMenu: any = null;\r\n if (props.compact) {\r\n keywordMenu = (\r\n Keyword\r\n \r\n \r\n {allKeywordStrings.map(k => )}\r\n \r\n );\r\n } else {\r\n keywordMenu = ( }\r\n />);\r\n };\r\n\r\n return (
\r\n
\r\n {!props.compact ? (
\r\n \r\n \r\n \r\n \r\n
) : null}\r\n
\r\n {keywordMenu}\r\n \r\n \r\n \r\n
\r\n
\r\n\r\n
\r\n \r\n
\r\n
);\r\n}\r\n","import { TrackOverview } from '../dtos/dto';\r\nconst randomWords = require('random-words');\r\n\r\n// https://stackoverflow.com/questions/2332811/capitalize-words-in-string\r\nconst capitalize = (str: string, lower = false) =>\r\n (lower ? str.toLowerCase() : str).replace(/(?:^|\\s|[\"'([{])+\\S/g, match => match.toUpperCase());\r\n\r\nexport function getReleaseImageSrcForCatNo(catNo: string): string {\r\n // remove spaces\r\n const fileNameBasis = catNo.toLowerCase().replace(/\\s+/g, '');\r\n const filePath: string = process.env.PUBLIC_URL + 'images/releases/' + fileNameBasis + '.jpg';\r\n return filePath;\r\n}\r\n\r\nexport function getRandomTrackOverview(trackId: number): TrackOverview {\r\n const trackOverview = new TrackOverview();\r\n trackOverview.trackId = trackId;\r\n trackOverview.artistName = \"Cylob\";\r\n const rndWords = randomWords(5);\r\n let titleMain = '';\r\n let noOfWords = 2;\r\n if (Math.random() > 0.5) {\r\n noOfWords = 3;\r\n }\r\n for (let i = 0; i < noOfWords; i++) {\r\n titleMain += rndWords[i] + ' ';\r\n };\r\n trackOverview.titleMain = capitalize(titleMain.trim());\r\n if (Math.random() > 0.5) {\r\n trackOverview.titleSecondary = capitalize(rndWords[3] + ' ' + rndWords[4]);\r\n }\r\n trackOverview.bpm = 70 + Math.floor(Math.random() * 80);\r\n trackOverview.durationSecs = 120 + Math.floor(Math.random() * 120);\r\n trackOverview.visible = true;\r\n return trackOverview;\r\n}\r\n\r\nexport function sortTrackOverviews(trackOverviewArray: Array, sortBy: string, sortDirection: string): Array {\r\n const sortedResults = trackOverviewArray.sort((a: TrackOverview, b: TrackOverview) => {\r\n let thisProperty: string | number = '', otherProperty: string | number = '';\r\n switch (sortBy) {\r\n case \"displayTitle\":\r\n thisProperty = a.displayTitle.toLowerCase();\r\n otherProperty = b.displayTitle.toLowerCase();\r\n break;\r\n case \"artistName\":\r\n thisProperty = a.artistName.toLowerCase();\r\n otherProperty = b.artistName.toLowerCase();\r\n break;\r\n case \"displayDuration\":\r\n thisProperty = a.displayDuration;\r\n otherProperty = b.displayDuration;\r\n break;\r\n case \"bpm\":\r\n thisProperty = a.bpm;\r\n otherProperty = b.bpm;\r\n break;\r\n };\r\n let result = 0;\r\n if (thisProperty > otherProperty) {\r\n result = -1;\r\n } else if (thisProperty < otherProperty) {\r\n result = 1;\r\n };\r\n\r\n //let result = a.getSortResult(b, sortBy);\r\n result *= sortDirection === \"ASC\" ? 1 : -1;\r\n return result;\r\n });\r\n return sortedResults;\r\n}","import React, { useState, useEffect } from 'react';\r\nimport { makeStyles } from '@material-ui/core/styles';\r\nimport { Column, Table } from 'react-virtualized';\r\nimport { defaultRowRenderer } from \"react-virtualized/dist/es/Table\";\r\nimport CircularProgress from '@material-ui/core/CircularProgress';\r\nimport { Keyword, TrackOverview } from '../dtos/dto';\r\n\r\nimport { stringIsEmptyOrNull, stringIsInOtherString, bindNameArray } from '../util/utilities';\r\nimport { fetchKeywords, getKeywordIdForName } from '../api/api_keyword';\r\nimport { sortTrackOverviews } from '../util/track.util';\r\n// import useWindowDimensions from '../util/windowDimensions';\r\n\r\nimport 'react-virtualized/styles.css'; // only needs to be imported once\r\nimport '../css/TrackTable.css';\r\nimport '../css/generic.css';\r\nimport '../css/flex.css';\r\n\r\n// const useStyles = makeStyles({\r\n// loadingWaitWrapper: {\r\n// width: '600px',\r\n// height: '500px'\r\n// },\r\n// loadingText: {\r\n// marginLeft: '50px'\r\n// }\r\n\r\n// });\r\n\r\ninterface TableDisplayParams {\r\n width: number;\r\n height: number;\r\n showArtist: boolean;\r\n showTime: boolean;\r\n showBpm: boolean;\r\n artistWidth: number;\r\n titleWidth: number;\r\n timeWidth: number;\r\n bpmWidth: number;\r\n}\r\n\r\ninterface TrackTableProps {\r\n trackOverviews: Array;\r\n // filterParams: FilterParams;\r\n filterText: string;\r\n keywords: Array;\r\n trackUpdateCount: number; // increase to force filter to be reapplied\r\n selectedTrackId: number | null;\r\n uiChangeCount: number; // increase to force resize of table after mode switched\r\n tableWidth: number;\r\n tableHeight: number;\r\n trackSelected: (trackId: number) => any;\r\n}\r\ntype SortDirection = \"ASC\" | \"DESC\" | undefined;\r\n\r\nexport default function TrackTable(props: TrackTableProps) {\r\n // const classes = useStyles();\r\n // const { height, width } = useWindowDimensions();\r\n let tableRef: any;\r\n\r\n const [keywordIds, setKeywordIds] = useState(new Array());\r\n const [filteredResults, setFilteredResults] = useState(new Array());\r\n const [sortedResults, setSortedResults] = useState(new Array());\r\n const [sortBy, setSortBy] = useState(\"displayTitle\");\r\n const defaultSortDirection: SortDirection = \"DESC\";\r\n const [sortDirection, setSortDirection] = useState(defaultSortDirection); \r\n //const [lastSelectedRowId, setLastSelectedRowId] = useState(-1); \r\n const [updateTableCount, setUpdateTableCount] = useState(0);\r\n const [scrollToIndex, setScrollToIndex] = useState(0);\r\n\r\n const defaultTrackIdToTableRowIndexDict: {[trackId: number]: number} = { };\r\n const [trackIdToTableRowIndexDict, setTrackIdToTableRowIndexDict] = useState(defaultTrackIdToTableRowIndexDict);\r\n const [tableDisplayParams, setTableDisplayParams] = useState({width: 0, height: 0, showArtist: false, showTime: false, showBpm: false, artistWidth: 0, titleWidth: 0, timeWidth: 0, bpmWidth: 0});\r\n const [showHeader, setShowHeader] = useState(true);\r\n\r\n useEffect(() => {\r\n // recalculate tableDisplayParams\r\n const p = {...tableDisplayParams};\r\n p.width = props.tableWidth;\r\n //width * (width >= 768 ? 0.5 : 1);\r\n p.height = props.tableHeight;\r\n //height - 100;\r\n p.showArtist = p.width > 450;\r\n p.showTime = p.width > 540;\r\n p.showBpm = p.width > 600;\r\n // assign the widths as previously (when table was fixed width),\r\n // calculate the total,\r\n // then use these to calculate fractions of the actual table width\r\n p.artistWidth = p.showArtist ? 140 : 0;\r\n p.titleWidth = 330;\r\n p.timeWidth = p.showTime ? 90 : 0;\r\n p.bpmWidth = p.showBpm ? 80 : 0;\r\n const totalWidth = p.artistWidth + p.titleWidth;\r\n p.artistWidth = (p.artistWidth / totalWidth) * p.width;\r\n p.titleWidth = (p.titleWidth / totalWidth) * p.width;\r\n // keep fixed time and bpm widths\r\n setTableDisplayParams(p);\r\n\r\n if (!p.showArtist && !p.showTime && !p.showBpm) {\r\n setShowHeader(false);\r\n } else {\r\n setShowHeader(true);\r\n }\r\n\r\n // const trackBrowserElement = document.getElementById('track-browser');\r\n // if (trackBrowserElement != null) {\r\n // const boundingRect = trackBrowserElement.getBoundingClientRect();\r\n // const top: number = boundingRect.top;\r\n // const tableHeight = height - top;\r\n // p.height = tableHeight - 30;\r\n // };\r\n // const trackBrowserOptionalUI = document.getElementById('track-browser-optional-ui');\r\n // if (trackBrowserOptionalUI != null) {\r\n // const boundingRect = trackBrowserOptionalUI.getBoundingClientRect();\r\n // p.height -= boundingRect.height;\r\n // }\r\n }, [props.tableWidth, props.tableHeight, props.uiChangeCount]);\r\n\r\n useEffect(() => {\r\n filterResults();\r\n \r\n // although nothing happens in response, if this isn't called then keywords don't appear in track detail.. hmm...\r\n fetchKeywords((keywords: any) => {\r\n //console.log('fetched keywords, they are ', keywords);\r\n })\r\n }, []);\r\n\r\n useEffect(() => {\r\n filterResults();\r\n }, [props.filterText])\r\n\r\n useEffect(() => {\r\n // console.log('useEffect props.selectedTrackId: ', props.selectedTrackId, trackIdToTableRowIndexDict, trackIdToTableRowIndexDict[props.selectedTrackId ?? 0]);\r\n setScrollToIndex(trackIdToTableRowIndexDict[props.selectedTrackId ?? 0]);\r\n //setLastSelectedRowId(props.selectedTrackId ?? -1);\r\n }, [props.selectedTrackId])\r\n\r\n useEffect(() => {\r\n // console.log('keyword ids is', keywordIds)\r\n filterResults();\r\n //setScrollToIndex(trackIdToTableRowIndexDict[100]);\r\n // setSortBy('title');\r\n // setSortDirection('DESC');\r\n // sortResults();\r\n \r\n }, [props.trackOverviews, props.trackUpdateCount, keywordIds]);\r\n\r\n useEffect(() => {\r\n // console.log('filter params changed: ', props.filterParams);\r\n const _keywordIds = new Array();\r\n props.keywords.forEach((keyword: string) => {\r\n const keywordId: number = getKeywordIdForName(keyword);\r\n // console.log('keyword id is ', keywordId);\r\n if (keywordId !== -1) {\r\n _keywordIds.push(keywordId);\r\n };\r\n // console.log('track table keywords.. ', props.keywords, _keywordIds);\r\n });\r\n setKeywordIds(_keywordIds);\r\n }, [props.keywords]);\r\n\r\n useEffect(() => {\r\n sortResults();\r\n // tableRef?.forceUpdateGrid();\r\n }, [filteredResults, sortBy, sortDirection]);\r\n\r\n useEffect(() => {\r\n tableRef?.forceUpdateGrid();\r\n // console.log('just tried to force update grid, tableRef is ', tableRef);\r\n }, [props.trackUpdateCount, updateTableCount]);\r\n\r\n // @param: an array with the keyword ids for a track.\r\n // returns true if these match the ids to search for or false if not.\r\n // a match happens if all of this.state.keywordIds appear in the keywordIds argument array\r\n\r\n const keywordsDoMatch = (trackKeywordIds: Array): boolean => {\r\n // if any of the entered keywords do not exist in the database, a match cannot be valid.\r\n if (keywordIds.indexOf(-1) !== -1) {\r\n return false;\r\n }\r\n for (let i = 0; i < keywordIds.length; i++) {\r\n const thisId = keywordIds[i];\r\n if (trackKeywordIds.indexOf(thisId) === -1) {\r\n return false;\r\n };\r\n };\r\n return true;\r\n }\r\n\r\n const filterResults = () => {\r\n\r\n const _filteredResults: Array = props.trackOverviews.filter((result: TrackOverview) => {\r\n const titleSearchTrackFound = stringIsInOtherString(props.filterText, result.displayTitle);\r\n const keywordsMatch = keywordsDoMatch(result.keywordIds);\r\n return titleSearchTrackFound && keywordsMatch;\r\n });\r\n setFilteredResults(_filteredResults);\r\n }\r\n\r\n const sortResults = () => {\r\n\r\n const _sortedResults = sortTrackOverviews(filteredResults, sortBy, sortDirection as string);\r\n\r\n let _trackIdToTableRowIndexDict: {[trackId: number]: number} = { };\r\n for (let i = 0; i < _sortedResults.length; i++) {\r\n _trackIdToTableRowIndexDict[_sortedResults[i].trackId] = i;\r\n };\r\n setTrackIdToTableRowIndexDict(_trackIdToTableRowIndexDict);\r\n\r\n setSortedResults(_sortedResults);\r\n setUpdateTableCount(updateTableCount + 1);\r\n\r\n };\r\n\r\n const rowClicked = (event: any) => {\r\n const trackId = event.rowData.trackId;\r\n props.trackSelected(trackId);\r\n //setLastSelectedRowId(trackId);\r\n };\r\n\r\n const sort = (params: any) => {\r\n \r\n setSortBy(params.sortBy);\r\n setSortDirection(params.sortDirection);\r\n };\r\n\r\n const rowRenderer = (args: any) => {\r\n if (args.rowData.visible === false) {\r\n args.className += \" not-visible\";\r\n } else if (args.rowData.trackId === props.selectedTrackId) {\r\n args.className += \" selected-row\";\r\n } else if (args.rowData.isEasterEgg === true) {\r\n args.className += \" easter-egg\";\r\n };\r\n return defaultRowRenderer(args);\r\n }\r\n\r\n const rowGetter = (indexObject: {index: number}): any => {\r\n const index = indexObject.index;\r\n return sortedResults[index];\r\n };\r\n\r\n // const displayTable: boolean = props.trackOverviews.length > 0;\r\n // if (displayTable) {\r\n return (\r\n
\r\n tableRef = ref}\r\n width={tableDisplayParams.width} height={tableDisplayParams.height} headerHeight={showHeader ? 50 : 0} rowHeight={40} \r\n rowCount={sortedResults.length} \r\n rowGetter={rowGetter}\r\n onRowClick={rowClicked}\r\n sort={sort} sortBy={sortBy} \r\n sortDirection={sortDirection}\r\n rowRenderer={rowRenderer}\r\n scrollToIndex={scrollToIndex}>\r\n {tableDisplayParams.showArtist ? : null}\r\n \r\n {tableDisplayParams.showTime ? : null}\r\n {tableDisplayParams.showBpm ? : null}\r\n \r\n
\r\n );\r\n // } else {\r\n // return (
\r\n //
\r\n // \r\n //
Tracks are loading, please wait...
\r\n //
\r\n //
);\r\n // }\r\n \r\n}\r\n\r\n","/**\r\n * Returns the element height including margins\r\n * @param element - element\r\n * @returns {number}\r\n */\r\nexport function outerHeight(element: HTMLElement) {\r\n const height: number = element.offsetHeight;\r\n const style: any = window.getComputedStyle(element);\r\n return ['top', 'bottom']\r\n .map(side => parseInt(style[`margin-${side}`]))\r\n .reduce((total, side) => total + side, height);\r\n}\r\n\r\nexport function outerWidth(element: HTMLElement) {\r\n const width: number = element.offsetWidth;\r\n const style: any = window.getComputedStyle(element);\r\n return ['right', 'left']\r\n .map(side => parseInt(style[`margin-${side}`]))\r\n .reduce((total, side) => total + side, width);\r\n}\r\n\r\nexport function respondToParentWidth(wrapperId: string, onCalcFunc: (width: number) => any) {\r\n const el: HTMLElement | null = document.getElementById(wrapperId);\r\n if (el == null) return;\r\n const parentElement: HTMLElement | null = el.parentElement;\r\n if (parentElement == null) return;\r\n const elWidth = outerWidth(parentElement);\r\n onCalcFunc(elWidth);\r\n}\r\n\r\nexport function getModalStyles(width: number, height: number): any {\r\n let modalWidth = width - 40;\r\n if (modalWidth > 600) modalWidth = 600;\r\n let modalHeight = height - 100;\r\n if (modalHeight > 800) modalHeight = 800;\r\n const modalStyles: any = {\r\n position: 'absolute',\r\n width: modalWidth + 'px',\r\n height: modalHeight + 'px',\r\n padding: '15px',\r\n top: '50%',\r\n left: '50%',\r\n transform: 'translate(-50%, -50%)',\r\n backgroundColor: 'white',\r\n overflowY: 'auto'\r\n };\r\n return modalStyles;\r\n}","import React, { useState, useEffect } from 'react';\r\n\r\nimport Button from '@material-ui/core/Button';\r\nimport { makeStyles } from '@material-ui/core/styles';\r\n\r\nimport TrackFilterParams from './TrackFilterParams';\r\nimport TrackTable from './TrackTable';\r\nimport '../css/TrackBrowser.css';\r\nimport '../css/generic.css';\r\nimport '../css/flex.css';\r\n\r\nimport { TrackOverview } from '../dtos/dto';\r\nimport { UserOption } from './TracksPageComponent';\r\nimport { getRandomTrackOverview } from '../util/track.util';\r\nimport { FilterParams } from './TracksPageComponent';\r\nimport useWindowDimensions from '../util/windowDimensions';\r\nimport { outerHeight, outerWidth } from '../util/css.util';\r\n\r\nconst useStyles = makeStyles({\r\n explainText: {\r\n margin: '5px 20px',\r\n }\r\n});\r\n\r\ninterface TrackBrowserProps {\r\n trackOverviews: Array;\r\n trackUpdateCount: number;\r\n selectedTrackId: number;\r\n selectedUserOption: UserOption;\r\n // first number in array is id of the track itself, the others are the ids of the tracks similar to that one\r\n similarTrackIds: Array;\r\n similarDescription: any;\r\n trackSelected: (trackId: number) => any;\r\n\r\n // filterParams: FilterParams;\r\n // filterParamsChanged: (filterParams: FilterParams) => any;\r\n\r\n // mechanism to add keyword to search params\r\n // TODO: something more elegant..\r\n // addKeywordCount: number;\r\n // keywordToAdd: string;\r\n\r\n filterText: string;\r\n keywords: Array;\r\n\r\n filterTextChanged: (filterText: string) => any;\r\n keywordsChanged: (keywords: Array) => any;\r\n}\r\n\r\nexport default function TrackBrowserComponent(props: TrackBrowserProps) {\r\n\r\n const classes = useStyles();\r\n const { height, width } = useWindowDimensions();\r\n const [trackOverviewHistory, setTrackOverviewHistory] = useState(new Array());\r\n const [similarTracks, setSimilarTracks] = useState(new Array());\r\n const [trackTableUiChangeCount, setTrackTableUiChangeCount] = useState(0);\r\n const [tableWidth, setTableWidth] = useState(0);\r\n const [tableHeight, setTableHeight] = useState(0);\r\n const [searchIsCompact, setSearchIsCompact] = useState(false);\r\n\r\n useEffect(() => {\r\n calcTableDimensions();\r\n }, [height, width, trackTableUiChangeCount]);\r\n\r\n useEffect(() => {\r\n\r\n let historyIdArray: Array = getHistoryIdArray();\r\n setTrackOverviewHistory(convertHistoryTrackIdsToTrackOverviewArray(historyIdArray));\r\n \r\n }, [props.trackOverviews]);\r\n\r\n\r\n useEffect(() => {\r\n const _similarTracks = new Array();\r\n props.similarTrackIds.forEach((trackId: number) => {\r\n const findFunc = (trackOverview: TrackOverview) => {\r\n return trackOverview.trackId === trackId;\r\n };\r\n let trackOverview: TrackOverview | undefined = props.trackOverviews.find(findFunc);\r\n if (trackOverview != null) {\r\n _similarTracks.push(trackOverview);\r\n } else {\r\n // it's an easter egg\r\n trackOverview = getRandomTrackOverview(trackId);\r\n trackOverview.isEasterEgg = true;\r\n _similarTracks.push(trackOverview);\r\n };\r\n setSimilarTracks(_similarTracks);\r\n });\r\n }, [props.similarTrackIds]);\r\n\r\n useEffect(() => {\r\n addTrackToHistory(props.selectedTrackId);\r\n }, [props.selectedTrackId])\r\n\r\n useEffect(() => {\r\n setTrackTableUiChangeCount(trackTableUiChangeCount + 1);\r\n }, [props.selectedUserOption]);\r\n\r\n function trackSelected(trackId: number) {\r\n props.trackSelected(trackId);\r\n }\r\n\r\n function getHistoryIdArray(): Array {\r\n // get existing list of ids from localstorage\r\n let historyIds: any = window.localStorage.getItem('trackBrowserHistoryIds');\r\n let historyIdArray: Array | null = JSON.parse(historyIds);\r\n if (historyIdArray == null) {\r\n historyIdArray = new Array();\r\n };\r\n return historyIdArray;\r\n }\r\n\r\n function addTrackToHistory(trackId: number) {\r\n if (trackId < 0) return;\r\n // if we are browsing history, don't add things on to the end of it\r\n if (props.selectedUserOption === 'history') return;\r\n\r\n let historyIdArray: Array = getHistoryIdArray();\r\n if (historyIdArray.indexOf(trackId) === -1) {\r\n historyIdArray.push(trackId);\r\n };\r\n window.localStorage.setItem('trackBrowserHistoryIds', JSON.stringify(historyIdArray));\r\n setTrackOverviewHistory(convertHistoryTrackIdsToTrackOverviewArray(historyIdArray));\r\n }\r\n\r\n function convertHistoryTrackIdsToTrackOverviewArray(trackIds: Array): Array {\r\n const trackOverviewArray = new Array();\r\n trackIds.forEach((trackId: number) => {\r\n const findFunc = (trackOverview: TrackOverview) => {\r\n return trackOverview.trackId === trackId;\r\n };\r\n let trackOverview: TrackOverview | undefined = props.trackOverviews.find(findFunc);\r\n if (trackOverview == null) {\r\n // it's an easter egg\r\n trackOverview = getRandomTrackOverview(trackId);\r\n trackOverview.isEasterEgg = true;\r\n };\r\n trackOverviewArray.push(trackOverview);\r\n });\r\n return trackOverviewArray;\r\n }\r\n\r\n function handleClearHistory() {\r\n setTrackOverviewHistory(new Array());\r\n window.localStorage.setItem('trackBrowserHistoryIds', JSON.stringify([]));\r\n }\r\n\r\n function handleFilterTextChanged(filterText: string) {\r\n props.filterTextChanged(filterText);\r\n }\r\n\r\n function handleKeywordsChanged(keywords: Array) {\r\n props.keywordsChanged(keywords);\r\n }\r\n\r\n function calcTableDimensions() {\r\n let _tableHeight = height - 95;\r\n let _tableWidth = width * (width >= 768 ? 0.48 : 1);\r\n _tableWidth -= (width >= 768 ? 0 : 40);\r\n // _tableWidth += (width >= 768 ? 20 : 0);\r\n const trackBrowserElement = document.getElementById('track-browser');\r\n if (trackBrowserElement != null) {\r\n const boundingRect = trackBrowserElement.getBoundingClientRect();\r\n const top: number = boundingRect.top;\r\n _tableHeight = height - top;\r\n _tableHeight = _tableHeight - 30;\r\n };\r\n const trackBrowserOptionalUI = document.getElementById('track-browser-optional-ui');\r\n if (trackBrowserOptionalUI != null) {\r\n //const boundingRect = trackBrowserOptionalUI.getBoundingClientRect();\r\n _tableHeight -= outerHeight(trackBrowserOptionalUI);\r\n //console.log('height comparison: ', trackBrowserOptionalUI.getBoundingClientRect().height, outerHeight(trackBrowserOptionalUI))\r\n //boundingRect.height;\r\n };\r\n setTableWidth(_tableWidth);\r\n setTableHeight(_tableHeight);\r\n setSearchIsCompact(width < 480);\r\n }\r\n\r\n // filterParams is used by the filter params component but also by the table in order to filter things\r\n // if there's no filtering ('all') then make the filter params blank\r\n let thisFilterText = '';\r\n let thisKeywords = new Array();\r\n // let thisFilterParams: FilterParams = {filterText: '', keywords: []};\r\n let optionalUi: any = (
);\r\n let trackOverviews: Array = props.trackOverviews;\r\n\r\n switch (props.selectedUserOption) {\r\n case \"all\":\r\n break;\r\n case \"search\":\r\n thisFilterText = props.filterText;\r\n thisKeywords = props.keywords;\r\n optionalUi = (\r\n \r\n );\r\n break;\r\n case \"related\":\r\n trackOverviews = similarTracks;\r\n if (similarTracks.length > 0) {\r\n optionalUi = (
\r\n {props.similarDescription}\r\n
);\r\n } else {\r\n optionalUi = (
\r\n
Select a track under All or Search and then select Get Similar or View a release.
\r\n
The related tracks will be listed here.
\r\n
);\r\n };\r\n break;\r\n case \"history\":\r\n optionalUi = (
\r\n \r\n
);\r\n trackOverviews = trackOverviewHistory;\r\n break;\r\n }\r\n\r\n return (\r\n
\r\n
{optionalUi}
\r\n \r\n
\r\n );\r\n\r\n}\r\n","import React, { useState } from 'react';\r\nimport { TrackOverview, TrackDetail, TrackOnNetHost, Release } from '../dtos/dto';\r\n\r\ninterface ReleaseNameDisplayProps {\r\n release: Release;\r\n includeVersionDescription?: boolean;\r\n}\r\n\r\nexport default function ReleaseNameDisplayComponent(props: ReleaseNameDisplayProps) {\r\n return (
\r\n {props.release.title}\r\n {props.includeVersionDescription ? ({\" (\" + props.release.versionDescription + \")\"}) : ()}\r\n
)\r\n}","import React, { useState, useEffect } from 'react';\r\n\r\nimport { makeStyles } from '@material-ui/core/styles';\r\nimport Chip from '@material-ui/core/Chip';\r\nimport Paper from '@material-ui/core/Paper';\r\n\r\nimport Table from '@material-ui/core/Table';\r\nimport TableBody from '@material-ui/core/TableBody';\r\nimport TableCell from '@material-ui/core/TableCell';\r\nimport TableContainer from '@material-ui/core/TableContainer';\r\nimport TableRow from '@material-ui/core/TableRow';\r\nimport Button from '@material-ui/core/Button';\r\nimport Collapse from '@material-ui/core/Collapse';\r\nimport KeyboardArrowDownIcon from '@material-ui/icons/KeyboardArrowDown';\r\nimport KeyboardArrowUpIcon from '@material-ui/icons/KeyboardArrowUp';\r\nimport IconButton from '@material-ui/core/IconButton';\r\n\r\nimport ReleaseNameDisplayComponent from './ReleaseNameDisplay';\r\nimport { TrackOverview, TrackDetail, TrackOnNetHost, Release } from '../dtos/dto';\r\nimport ChipGroup from '../generic/ChipGroup';\r\nimport { outerWidth } from '../util/css.util';\r\nimport useWindowDimensions from '../util/windowDimensions';\r\n\r\nimport '../css/generic.css';\r\nimport '../css/flex.css';\r\n\r\n\r\nconst useStyles = makeStyles({\r\n paper: {\r\n padding: '10px 15px',\r\n // backgroundColor: '#f9f9f9',\r\n margin: '10px'\r\n },\r\n chip: {\r\n marginRight: '5px'\r\n },\r\n icon: {\r\n color: '#aaa',\r\n marginRight: '10px'\r\n },\r\n propertyText: {\r\n marginRight: '20px',\r\n fontWeight: 'bold'\r\n },\r\n section: {\r\n width: '100%'\r\n },\r\n // divider: {\r\n // margin: '10px 10px',\r\n // height: '1px',\r\n // width: 'calc(100% - 20px)',\r\n // // backgroundColor: '#ccc'\r\n // },\r\n cellKey: {\r\n minWidth: '80px'\r\n },\r\n cellKeyText: {\r\n minWidth: '80px'\r\n },\r\n cellValue: {\r\n //width: '500px'\r\n },\r\n tableContainer: {\r\n // maxWidth: '500px'\r\n }, \r\n releaseImg: {\r\n width: '150px',\r\n marginLeft: '10px'\r\n },\r\n chipWrapper: {\r\n //padding: '10px',\r\n width: 'calc(100% - 20px)',\r\n },\r\n chipWrapperClosed: {\r\n maxHeight: '37px',\r\n overflow: 'hidden'\r\n },\r\n chipWrapperExpanded: {\r\n\r\n },\r\n displayTitle: {\r\n fontSize: '1.4em'\r\n },\r\n trackDetailsWrapper: {\r\n maxWidth: '850px',\r\n // marginTop: '50px'\r\n },\r\n inbetweenArtistAndTitle: {\r\n paddingLeft: '5px',\r\n paddingRight: '5px'\r\n },\r\n getSimilarButtonWrapper: {\r\n //marginLeft: '10px'\r\n // maxHeight: '40px'\r\n },\r\n getSimilarButton: {\r\n maxHeight: '36px',\r\n minWidth: '110px',\r\n marginLeft: '10px'\r\n },\r\n viewReleaseButton: {\r\n maxHeight: '36px',\r\n minWidth: '54px',\r\n marginLeft: '10px'\r\n },\r\n imgWrapper: {\r\n padding: '5px',\r\n marginLeft: '10px',\r\n marginRight: '10px'\r\n },\r\n releaseInfos: {\r\n marginBottom: '5px'\r\n }\r\n\r\n});\r\n\r\nenum LayoutType {\r\n None = -1,\r\n Wide = 0,\r\n Narrow = 1\r\n}\r\n\r\ninterface TrackInfoProps {\r\n trackDetail: TrackDetail;\r\n releaseImgFilePath: string;\r\n releasesForTrack: Array;\r\n keywordsForTrack: Array;\r\n getSimilarButtonClicked: () => any;\r\n getReleaseButtonClicked: (releaseId: number) => any;\r\n keywordWasRequested: (keyword: string) => any;\r\n}\r\n\r\ninterface TableRowInfo {\r\n key: string;\r\n displayKey: string;\r\n val: any;\r\n}\r\nexport default function TrackInfoComponent(props: TrackInfoProps) {\r\n const classes = useStyles();\r\n const { height, width } = useWindowDimensions();\r\n const [chipGroupExpanded, setChipGroupExpanded] = useState(false);\r\n const [keywordsForTrack, setKeywordsForTrack] = useState>([]);\r\n const [layoutType, setLayoutType] = useState(LayoutType.Wide);\r\n const [elWidth, setElWidth] = useState(800);\r\n\r\n useEffect(() => {\r\n setKeywordsForTrack(props.keywordsForTrack.sort());\r\n }, [props.keywordsForTrack]);\r\n\r\n useEffect(() => {\r\n calcLayout();\r\n }, [width]);\r\n\r\n function handleGetSimilarClicked() {\r\n props.getSimilarButtonClicked();\r\n }\r\n function handleGetReleaseClicked(releaseId: number) {\r\n props.getReleaseButtonClicked(releaseId);\r\n }\r\n function handleChipNameClicked(chipName: string) {\r\n \r\n props.keywordWasRequested(chipName);\r\n }\r\n\r\n const releaseInfos = (
\r\n {props.releasesForTrack.map((release: Release, index: number) => {\r\n return (
\r\n \r\n \r\n
);\r\n })}\r\n
);\r\n\r\n function handleChipGroupButtonClicked() {\r\n setChipGroupExpanded(!chipGroupExpanded);\r\n }\r\n \r\n const tableRowInfoArray: Array = [\r\n {key: 'displayDuration', displayKey: 'Duration', val: props.trackDetail.trackOverview.displayDuration},\r\n {key: 'bpm', displayKey: 'BPM', val: props.trackDetail.bpm},\r\n // {key: 'releases', displayKey: 'Appears on', val: (
{releaseInfos}
)}\r\n ];\r\n if (props.releasesForTrack.length > 0) {\r\n tableRowInfoArray.push({key: 'releases', displayKey: 'Appears on', val: (
{releaseInfos}
)});\r\n };\r\n\r\n function calcLayout() {\r\n const el: HTMLElement | null = document.getElementById('track-info-wrapper');\r\n if (el == null) return;\r\n const _elWidth = outerWidth(el);\r\n setLayoutType(_elWidth >= 600 ? LayoutType.Wide : LayoutType.Narrow);\r\n setElWidth(_elWidth);\r\n }\r\n\r\n let topHalfClassName = '';\r\n let wrapperStyle = { };\r\n switch (layoutType) {\r\n case LayoutType.Narrow:\r\n topHalfClassName = 'flex-column-reverse-start-center';\r\n wrapperStyle = { marginTop: '10px' };\r\n break;\r\n case LayoutType.Wide:\r\n topHalfClassName = 'flex-row-start-center';\r\n wrapperStyle = { marginTop: '60px' };\r\n break;\r\n }\r\n\r\nreturn (\r\n
\r\n\r\n
\r\n
\r\n \r\n \r\n \r\n \r\n \r\n
480 ? \"flex-row-space-between-center\" : \"flex-column-start-center\"}>\r\n
\r\n {props.trackDetail.trackOverview.displayTitle}\r\n by \r\n {props.trackDetail.trackOverview.artistName}\r\n
\r\n
\r\n \r\n
\r\n
\r\n
\r\n
\r\n {tableRowInfoArray.map((info: TableRowInfo) => {\r\n return (\r\n \r\n {info.displayKey}\r\n \r\n {info.val}\r\n )\r\n })}\r\n\r\n
\r\n
\r\n
\r\n
\r\n
\r\n \r\n
\r\n
{/* end of table + image row */}\r\n \r\n \r\n \r\n \r\n \r\n {keywordsForTrack.length} Keywords\r\n \r\n {chipGroupExpanded ? : }\r\n \r\n \r\n \r\n
\r\n \r\n
\r\n
\r\n
\r\n
\r\n
\r\n
\r\n\r\n
\r\n);\r\n\r\n}\r\n\r\n\r\n","import { getApiBaseAddr, sendRequest } from '../util/util_api.js';\r\nimport { NetHost, TrackOnNetHost } from '../dtos/dto';\r\n\r\n// store the array after the first fetch since it is unlikely to be updated afterwards\r\nlet netHostArray = new Array();\r\n\r\n// if they have already been fetched, just return the array:\r\n// net hosts are unlikely to change after the initial pickup\r\n// if one is added, just refresh the app!\r\nfunction fetchNetHosts(onSuccessCallbackFunc: (netHosts: Array) => any, onErrorCallbackFunc: (err: any) => any = () => {}) {\r\n\r\n fetch(getApiBaseAddr() + 'nethost')\r\n .then(res => res.json())\r\n .then((result: any) => {\r\n netHostArray = new Array();\r\n result.forEach((dto: any) => {\r\n const netHost = NetHost.createFromDto(dto);\r\n netHostArray.push(netHost);\r\n });\r\n onSuccessCallbackFunc(netHostArray);\r\n },\r\n (err) => {\r\n console.log('there was an error fetching net hosts, it is ', err);\r\n onErrorCallbackFunc(err);\r\n });\r\n}\r\n\r\nfunction addEmbedCode(token: any, params: any, onSuccessCallbackFunc: any, onErrorCallbackFunc = (err: any) => {}) {\r\n sendRequest('POST', 'embedded-track', params, token)\r\n .then(result => result.json())\r\n .then(result => {\r\n\r\n onSuccessCallbackFunc(result);\r\n })\r\n .catch((err: any) => {\r\n onErrorCallbackFunc(err);\r\n });\r\n}\r\n\r\nfunction deleteEmbed(token: any, params: any, onSuccessCallbackFunc: any, onErrorCallbackFunc = (err: any) => {}) {\r\n sendRequest('POST', 'embedded-track/delete', params, token)\r\n .then(result => result.json())\r\n .then(result => {\r\n \r\n onSuccessCallbackFunc(result);\r\n })\r\n .catch(err => {\r\n onErrorCallbackFunc(err);\r\n });\r\n}\r\n\r\nfunction fetchEmbedInfosForTrack(trackId: number, onSuccessCallbackFunc: (result: Array) => any, onErrorCallbackFunc = (err: any) => {}) {\r\n fetch(getApiBaseAddr() + 'embedded-track/l4t/' + trackId)\r\n .then(result=> result.json())\r\n .then((result) => {\r\n const dtos = result.objects;\r\n const trackOnNetHostArray = new Array();\r\n dtos.forEach((dto: any) => {\r\n const trackOnNetHost = TrackOnNetHost.createFromDto(dto);\r\n trackOnNetHostArray.push(trackOnNetHost);\r\n });\r\n \r\n onSuccessCallbackFunc(trackOnNetHostArray);\r\n },\r\n (error) => {\r\n console.log('there was an error fetching embed infos, it is ', error);\r\n onErrorCallbackFunc(error);\r\n });\r\n}\r\n\r\nfunction fetchEmbedInfosForTrackAndHost(trackId: number, netHostId: number, onSuccessCallbackFunc: (result: Array) => any, onErrorCallbackFunc = (err: any) => {}) {\r\n fetch(getApiBaseAddr() + 'embedded-track/links?netHostId=' + netHostId + \"&trackId=\" + trackId)\r\n .then(result=> result.json())\r\n .then(result => {\r\n const dtos = result.objects;\r\n const trackOnNetHostArray = new Array();\r\n dtos.forEach((dto: any) => {\r\n const trackOnNetHost = TrackOnNetHost.createFromDto(dto);\r\n trackOnNetHostArray.push(trackOnNetHost);\r\n });\r\n onSuccessCallbackFunc(trackOnNetHostArray);\r\n })\r\n .catch(err => {\r\n onErrorCallbackFunc(err);\r\n });\r\n}\r\n\r\nfunction fetchAvailableEmbedHostIdsForTrack(trackId: number, onSuccessCallbackFunc = (result: Array) => {}, onErrorCallbackFunc = (err: any) => {}) {\r\n \r\n fetch(getApiBaseAddr() + 'embedded-track/anh4t/' + trackId)\r\n .then(result => result.json())\r\n .then(result => {\r\n \r\n onSuccessCallbackFunc(result.objects);\r\n })\r\n .catch(err => {\r\n onErrorCallbackFunc(err);\r\n });\r\n\r\n}\r\n\r\nexport { fetchNetHosts, addEmbedCode, deleteEmbed, fetchEmbedInfosForTrack, fetchEmbedInfosForTrackAndHost, fetchAvailableEmbedHostIdsForTrack }","import React, { useState, useEffect } from 'react';\r\n\r\nimport Tooltip from '@material-ui/core/Tooltip';\r\nimport Button from '@material-ui/core/Button';\r\nimport IconButton from '@material-ui/core/IconButton';\r\nimport Icon from '@material-ui/core/Icon';\r\nimport { makeStyles } from '@material-ui/core/styles';\r\n\r\nimport { NetHost } from '../dtos/dto';\r\nimport { fetchNetHosts } from '../api/api_nethost';\r\n\r\nimport '../css/flex.css';\r\nimport '../css/generic.css';\r\n\r\nimport \"font-awesome/css/font-awesome.css\";\r\n\r\nconst useStyles = makeStyles({\r\n button: {\r\n // marginLeft: '5px',\r\n // marginRight: '5px'\r\n\r\n },\r\n buttonGroup: {\r\n // margin: '10px 15px'\r\n marginBottom: '10px',\r\n width: '100%',\r\n // backgroundColor: 'yellow'\r\n },\r\n buttonContainerDiv: {\r\n width: '20%',\r\n // backgroundColor: 'orange',\r\n },\r\n buttonDivDisabled: {\r\n color: '#eee',\r\n // backgroundColor: 'red'\r\n },\r\n buttonDiv: {\r\n margin: '3px',\r\n paddingLeft: '10px',\r\n paddingRight: '10px',\r\n width: 'calc(90% - 20px)',\r\n paddingTop: '5px',\r\n paddingBottom: '5px',\r\n // color: 'black',\r\n border: '1px solid #bbb',\r\n borderRadius: '3px',\r\n \r\n '&:active': {\r\n backgroundColor: '#eaeaea'\r\n }\r\n },\r\n buttonDivAvailable: {\r\n color: '#777'\r\n },\r\n buttonDivActive: {\r\n color: 'red',\r\n backgroundColor: '#eaeaea'\r\n }\r\n});\r\n\r\ninterface EmbedButtonsProps {\r\n availableNetHostIds: Array;\r\n selectedNetHostId: number;\r\n netHostWasSelectedWithId: (netHostId: number) => any;\r\n}\r\n\r\nfunction EmbedButtons(props: EmbedButtonsProps) {\r\n const netHostAvailableDefault: {[key: string]: boolean } = { };\r\n const [netHostAvailable, setNetHostAvailable] = useState(netHostAvailableDefault);\r\n const nameChoices = ['youtube', 'soundcloud', 'bandcamp', 'spotify', 'apple'];\r\n const toolTipLabels = ['YouTube Embedded Player', 'SoundCloud Embedded Player', 'Bandcamp Embedded Player', 'Spotify Embedded Player', 'Apple Music Embedded Player'];\r\n const [availableNetHostNames, setAvailableNetHostNames] = useState(new Array());\r\n const [selectedName, setSelectedName] = useState('');\r\n const [netHostArray, setNetHostArray] = useState(new Array());\r\n\r\n \r\n useEffect(() => {\r\n \r\n fetchNetHosts((_netHostArray: Array) => {\r\n \r\n setNetHostArray(_netHostArray);\r\n });\r\n }, []);\r\n\r\n useEffect(() => {\r\n if ((netHostArray.length > 0) && (props.availableNetHostIds.length > 0)) {\r\n calcAvailableNetHostNames();\r\n };\r\n }, [netHostArray, props.availableNetHostIds] );\r\n\r\n useEffect(() => {\r\n ;\r\n const available: {[key: string]: boolean } = { };\r\n nameChoices.forEach(name => {\r\n available[name] = availableNetHostNames.includes(name);\r\n });\r\n setNetHostAvailable(available);\r\n \r\n }, [availableNetHostNames]);\r\n\r\n useEffect(() => {\r\n if (netHostArray.length > 0) {\r\n const netHost: NetHost | undefined = netHostArray.find((n: NetHost) => n.id === props.selectedNetHostId);\r\n if (netHost != null) {\r\n setSelectedName(netHost.name.toLowerCase());\r\n } else {\r\n setSelectedName('');\r\n }\r\n };\r\n }, [netHostArray, props.selectedNetHostId])\r\n\r\n function calcAvailableNetHostNames() {\r\n if (props.availableNetHostIds == null) return;\r\n const _availableNetHostNames = new Array();\r\n props.availableNetHostIds.forEach((netHostId: number) => {\r\n const netHost: NetHost | undefined = netHostArray.find((n: NetHost) => n.id === netHostId);\r\n if (netHost != null) {\r\n _availableNetHostNames.push(netHost?.name.toLowerCase());\r\n };\r\n });\r\n setAvailableNetHostNames(_availableNetHostNames);\r\n }\r\n\r\n function buttonClicked(event: any) {\r\n const buttonName = event.currentTarget.getAttribute('data-name');\r\n const selectedNetHost: NetHost | undefined = netHostArray.find((netHost: NetHost) => {\r\n return netHost.name.toLowerCase() === buttonName;\r\n });\r\n if (selectedNetHost != null) {\r\n const id = selectedNetHost?.id;\r\n if (id !== null) {\r\n props.netHostWasSelectedWithId(id ?? 0);\r\n };\r\n };\r\n }\r\n const classes = useStyles();\r\n\r\n return (\r\n
\r\n\r\n {nameChoices.map((name: string, index: number) => {\r\n let disabled = !(netHostAvailable[name] === true);\r\n let className = classes.buttonDiv + ' flex-row-center-center';\r\n if (disabled) {\r\n className += (' ' + classes.buttonDivDisabled);\r\n } else {\r\n className += (' ' + classes.buttonDivAvailable);\r\n if (selectedName === name) className += (' ' + classes.buttonDivActive);\r\n }\r\n const buttonDiv = (
!disabled ? buttonClicked(e) : null} >\r\n \r\n
);\r\n \r\n if (!disabled) {\r\n return (
\r\n \r\n {buttonDiv}\r\n \r\n
);\r\n } else {\r\n return (
\r\n {buttonDiv}\r\n
);\r\n }\r\n })}\r\n
\r\n );\r\n}\r\n\r\nexport default EmbedButtons;\r\n","import React, { useState, useEffect } from 'react';\r\nimport { respondToParentWidth } from '../util/css.util';\r\nimport useWindowDimensions from '../util/windowDimensions';\r\n\r\ninterface BandcampEmbedProps {\r\n albumId: string;\r\n trackLinkId: string;\r\n href: string;\r\n title: string;\r\n}\r\nexport default function BandcampEmbed(props: BandcampEmbedProps) {\r\n\r\n const { height, width } = useWindowDimensions();\r\n const [embedWidth, setEmbedWidth] = useState(300);\r\n const [srcString, setSrcString] = useState('');\r\n\r\n useEffect(() => {\r\n setTimeout(() => {\r\n calcLayout();\r\n }, 400)\r\n \r\n }, [])\r\n\r\n useEffect(() => {\r\n calcLayout();\r\n }, [width]);\r\n\r\n //const srcString: string = 'https://bandcamp.com/EmbeddedPlayer/album=' + props.albumId + '/size=large/bgcol=ffffff/linkcol=0687f5/tracklist=false/artwork=small/track=' + props.trackLinkId + '/transparent=true/';\r\n const iframeTitle: string = 'bandcamp-embed_' + props.title + '_' + props.trackLinkId;\r\n \r\n function calcLayout() {\r\n respondToParentWidth('bandcamp-embed-wrapper', (width: number) => {\r\n setEmbedWidth(width - 20);\r\n const _srcString = 'https://bandcamp.com/EmbeddedPlayer/album=' + props.albumId + '/size=large/bgcol=ffffff/linkcol=0687f5/tracklist=false' + \r\n (width >= 400 ? '/artwork=small' : '')\r\n + '/track=' + props.trackLinkId + '/transparent=true/';\r\n setSrcString(_srcString);\r\n });\r\n }\r\n\r\n // todo: use usestyle\r\n const iframeStyle = {\r\n border: '0',\r\n width: embedWidth >= 400 ? embedWidth : '260px',\r\n height: embedWidth >= 400 ? '140px' : '400px'\r\n };\r\n return (
\r\n \r\n
);\r\n \r\n}","import React, { useState, useEffect } from 'react';\r\nimport { respondToParentWidth } from '../util/css.util';\r\nimport useWindowDimensions from '../util/windowDimensions';\r\n\r\ninterface SoundCloudEmbedProps {\r\n trackId: string;\r\n}\r\n\r\nexport default function SoundCloudEmbed(props: SoundCloudEmbedProps) {\r\n\r\n const { height, width } = useWindowDimensions();\r\n const [iframeWidth, setIframeWidth] = useState(300);\r\n const [iframeHeight, setIframeHeight] = useState(140);\r\n const [visual, setVisual] = useState('false');\r\n\r\n useEffect(() => {\r\n setTimeout(() => {\r\n calcLayout();\r\n }, 400)\r\n \r\n }, [])\r\n\r\n useEffect(() => {\r\n calcLayout();\r\n }, [width]);\r\n\r\n function calcLayout() {\r\n respondToParentWidth('soundcloud-embed-wrapper', (width: number) => {\r\n setIframeWidth(width - 20);\r\n setIframeHeight(width > 400 ? 140 : 300);\r\n setVisual(width > 400 ? 'false' : 'true')\r\n });\r\n }\r\n\r\n const iframeTitle: string = 'soundcloud-embed_' + props.trackId;\r\n const srcString: string = 'https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/' + props.trackId + '&color=%23ff5500&auto_play=false&hide_related=true&show_comments=false&show_user=true&show_reposts=false&show_teaser=false&visual=' + visual;\r\n\r\n return (
\r\n \r\n
);\r\n}\r\n","import React, { useState, useEffect } from 'react';\r\nimport '../css/flex.css';\r\nimport { respondToParentWidth } from '../util/css.util';\r\nimport useWindowDimensions from '../util/windowDimensions';\r\n\r\ninterface YouTubeEmbedProps {\r\n videoId: string;\r\n}\r\n\r\nexport default function YouTubeEmbed(props: YouTubeEmbedProps) {\r\n\r\n const { height, width } = useWindowDimensions();\r\n const [iframeWidth, setIframeWidth] = useState(300);\r\n\r\n useEffect(() => {\r\n setTimeout(() => {\r\n calcLayout();\r\n }, 400)\r\n \r\n }, [])\r\n\r\n useEffect(() => {\r\n calcLayout();\r\n }, [width]);\r\n\r\n function calcLayout() {\r\n respondToParentWidth('youtube-embed-wrapper', (width: number) => {\r\n setIframeWidth(width * 0.9);\r\n });\r\n }\r\n\r\n const iframeTitle: string = 'youtube-embed_' + props.videoId;\r\n const srcString: string = 'https://www.youtube.com/embed/' + props.videoId + '?autoplay=0';\r\n\r\n return (
\r\n \r\n\r\n
);\r\n}\r\n\r\n","import React, { useState, useEffect } from 'react';\r\nimport { makeStyles } from '@material-ui/core/styles';\r\nimport '../css/flex.css';\r\nimport { respondToParentWidth } from '../util/css.util';\r\nimport useWindowDimensions from '../util/windowDimensions';\r\n\r\nconst useStyles = makeStyles({\r\n embedWrapper: {\r\n // width: '600px',\r\n height: '140px',\r\n backgroundColor: '#F8F8FA',\r\n borderRadius: '4px'\r\n }\r\n\r\n});\r\n\r\ninterface SpotifyEmbedProps {\r\n albumCode: string;\r\n}\r\n\r\nexport default function SpotifyEmbed(props: SpotifyEmbedProps) {\r\n\r\n const classes = useStyles();\r\n const { height, width } = useWindowDimensions();\r\n const [iframeWidth, setIframeWidth] = useState(300);\r\n\r\n useEffect(() => {\r\n setTimeout(() => {\r\n calcLayout();\r\n }, 400)\r\n \r\n }, [])\r\n\r\n useEffect(() => {\r\n calcLayout();\r\n }, [width]);\r\n\r\n function calcLayout() {\r\n respondToParentWidth('spotify-embed-wrapper', (width: number) => {\r\n setIframeWidth(width * 0.9);\r\n });\r\n }\r\n \r\n const iframeTitle: string = 'spotify-embed_' + props.albumCode;\r\n const srcString: string = 'https://open.spotify.com/embed/track/' + props.albumCode;\r\n\r\n return (
\r\n \r\n
);\r\n\r\n}\r\n","import React, { useState, useEffect } from 'react';\r\nimport { respondToParentWidth } from '../util/css.util';\r\nimport useWindowDimensions from '../util/windowDimensions';\r\n\r\ninterface AppleMusicEmbedProps {\r\n srcString: string;\r\n}\r\n\r\nexport default function AppleMusicEmbed(props: AppleMusicEmbedProps) {\r\n\r\n const { height, width } = useWindowDimensions();\r\n const [appleWrapperWidth, setAppleWrapperWidth] = useState(300);\r\n\r\n useEffect(() => {\r\n setTimeout(() => {\r\n calcLayout();\r\n }, 400)\r\n \r\n }, [])\r\n\r\n useEffect(() => {\r\n calcLayout();\r\n }, [width])\r\n\r\n // get a unique frame title without using the whole src string if possible\r\n const splitSrc = props.srcString.split('/album/');\r\n const frameTitle = splitSrc[1] || splitSrc[0];\r\n\r\n\r\n function calcLayout() {\r\n\r\n respondToParentWidth('apple-music-embed-wrapper', (width: number) => {\r\n setAppleWrapperWidth(width * 0.9);\r\n });\r\n }\r\n\r\n\r\n // todo: use usestyle\r\n const itunesStyle = {\r\n width: '100%',\r\n maxWidth: '660px',\r\n overflow: 'hidden',\r\n background: 'transparent'\r\n };\r\n\r\n const appleMusicWrapperStyle = {\r\n width: appleWrapperWidth\r\n }\r\n\r\n\r\n return (
\r\n \r\n
)\r\n}","import React, { useState, useEffect } from 'react';\r\n\r\nimport Snackbar from '@material-ui/core/Snackbar';\r\nimport MuiAlert from '@material-ui/lab/Alert';\r\n\r\nimport Table from '@material-ui/core/Table';\r\nimport TableBody from '@material-ui/core/TableBody';\r\nimport TableCell from '@material-ui/core/TableCell';\r\nimport TableContainer from '@material-ui/core/TableContainer';\r\nimport TableRow from '@material-ui/core/TableRow';\r\nimport Button from '@material-ui/core/Button';\r\nimport { makeStyles } from '@material-ui/core/styles';\r\n\r\nimport TrackInfoComponent from './TrackInfo';\r\n\r\nimport EmbedButtons from '../embed/EmbedButtons';\r\n\r\nimport { getTrackEmbedParams, getRenderForEmbeddedInfo } from '../util/util_embed.js';\r\nimport { fetchEmbedInfosForTrackAndHost, fetchAvailableEmbedHostIdsForTrack } from '../api/api_nethost';\r\n\r\nimport { TrackOverview, TrackDetail, TrackOnNetHost, Release } from '../dtos/dto';\r\nimport { fetchTrackDetail, getReleasesForTrackId } from '../api/api_track';\r\nimport { getKeywordNameForId } from '../api/api_keyword';\r\nimport { getReleaseImageSrcForCatNo } from '../util/track.util';\r\nimport { respondToParentWidth } from '../util/css.util';\r\nimport useWindowDimensions from '../util/windowDimensions';\r\n\r\nimport '../css/generic.css';\r\nimport '../css/modal.css';\r\n\r\n// after demo at https://material-ui.com/components/snackbars/\r\nfunction Alert(props: any) {\r\n return \r\n}\r\n\r\nconst useStyles = makeStyles({\r\n chipWrapper: {\r\n padding: '10px',\r\n width: 'calc(100% - 20px)'\r\n },\r\n chip: {\r\n marginRight: '5px',\r\n marginBottom: '5px'\r\n },\r\n getSimilarButtonWrapper: {\r\n marginTop: '5px',\r\n marginBottom: '5px'\r\n },\r\n noTrackSelectedWrapper: {\r\n marginTop: '80px',\r\n textAlign: 'left',\r\n // backgroundColor: 'yellow',\r\n width: '400px',\r\n height: '300px'\r\n },\r\n allWrapper: {\r\n // backgroundColor: 'blue'\r\n },\r\n embed: {\r\n marginTop: '20px'\r\n },\r\n trackDetailWrapper: {\r\n marginRight: '20px'\r\n // height: '100%',\r\n // overflowY: 'scroll'\r\n },\r\n returnButtonWrapper: {\r\n marginTop: '10px',\r\n marginLeft: '10px'\r\n },\r\n cellKey: {\r\n width: '60px'\r\n },\r\n});\r\n\r\ninterface TrackDetailComponentProps {\r\n trackId: number;\r\n selectedNetHostId: number;\r\n netHostWasSelectedWithId: (netHostId: number) => any;\r\n similarWasRequested: () => any;\r\n releaseWasRequested: (release: Release) => any;\r\n keywordWasRequested: (keyword: string) => any;\r\n showModalCloseButton: boolean;\r\n onClose: () => any;\r\n}\r\nexport default function TrackDetailComponent(props: TrackDetailComponentProps) {\r\n\r\n const classes = useStyles();\r\n const { height, width } = useWindowDimensions();\r\n\r\n const [modalType, setModalType] = useState('');\r\n const [modalIsOpen, setModalIsOpen] = useState(false);\r\n // allow for multiple embeds for a web host\r\n const [embeddedInfoRenderArray, setEmbeddedInfoRenderArray] = useState(new Array());\r\n const [snackbarIsOpen, setSnackbarIsOpen] = useState(false);\r\n const [snackbarSeverity, setSnackbarSeverity] = useState('info');\r\n const [snackbarMessage, setSnackbarMessage] = useState('');\r\n\r\n const [keywordsForTrack, setKeywordsForTrack] = useState(new Array());\r\n const [availableNetHostIds, setAvailableNetHostIds] = useState(new Array());\r\n const [trackDetail, setTrackDetail] = useState(new TrackDetail());\r\n const [releasesForTrack, setReleasesForTrack] = useState(new Array());\r\n const [releaseImgFilePath, setReleaseImgFilePath] = useState('');\r\n\r\n const [showListenText, setShowListenText] = useState(false);\r\n\r\n useEffect(() => {\r\n fetchTrack();\r\n fetchAvailableEmbedHostIds();\r\n }, [props.trackId]);\r\n\r\n useEffect(() => {\r\n fetchEmbedInfos();\r\n }, [trackDetail, props.selectedNetHostId]);\r\n\r\n useEffect(() => {\r\n setTimeout(() => {\r\n calcLayout();\r\n }, 400)\r\n \r\n }, [])\r\n\r\n useEffect(() => {\r\n calcLayout();\r\n }, [width])\r\n\r\n function calcLayout() {\r\n respondToParentWidth('track-detail-wrapper', (width: number) => {\r\n setShowListenText(width > 450);\r\n });\r\n }\r\n\r\n function fetchTrack() {\r\n if (props.trackId == null) {\r\n return;\r\n };\r\n const callbackFunc = (_trackDetail: TrackDetail) => {\r\n setTrackDetail(_trackDetail);\r\n if (_trackDetail.trackOverview.keywordIds != null) {\r\n const _keywordsForTrack = new Array();\r\n _trackDetail.trackOverview.keywordIds.forEach((id: number) => {\r\n _keywordsForTrack.push(getKeywordNameForId(id) ?? '');\r\n });\r\n setKeywordsForTrack(_keywordsForTrack);\r\n };\r\n }\r\n fetchTrackDetail(props.trackId, callbackFunc);\r\n getReleasesForTrackId(props.trackId, (result: Array) => {\r\n \r\n setReleasesForTrack(result);\r\n if (result.length > 0) {\r\n // // just get the image for the first release..\r\n const release: Release = result[0];\r\n const catNo: string = release.catNo;\r\n const filePath: string = getReleaseImageSrcForCatNo(catNo);\r\n setReleaseImgFilePath(filePath);\r\n } else {\r\n setReleaseImgFilePath('');\r\n };\r\n });\r\n }\r\n\r\n function fetchEmbedInfos() {\r\n \r\n if (props.trackId != null) {\r\n const netHostId = props.selectedNetHostId;\r\n fetchEmbedInfosForTrackAndHost(props.trackId, netHostId, (result: Array) => {\r\n \r\n const _embeddedInfoRenderArray = new Array();\r\n result.forEach((object: any) => {\r\n // embeddedInfoJson is a string encoded json object\r\n const render: any = getRenderForEmbeddedInfo(object.embeddedInfoJson);\r\n if (render != null) {\r\n _embeddedInfoRenderArray.push(render);\r\n };\r\n });\r\n setEmbeddedInfoRenderArray(_embeddedInfoRenderArray);\r\n })\r\n } else {\r\n setEmbeddedInfoRenderArray([]);\r\n };\r\n }\r\n\r\n function fetchAvailableEmbedHostIds() {\r\n fetchAvailableEmbedHostIdsForTrack(props.trackId, (result) => {\r\n \r\n setAvailableNetHostIds(result);\r\n });\r\n }\r\n\r\n function netHostWasSelectedWithId(id: number) {\r\n props.netHostWasSelectedWithId(id);\r\n }\r\n\r\n function getSimilarClicked() {\r\n props.similarWasRequested();\r\n }\r\n\r\n function getReleaseClicked(releaseId: number) {\r\n \r\n const release = releasesForTrack.find((r: Release) => r.id === releaseId);\r\n if (release != null) {\r\n props.releaseWasRequested(release);\r\n }\r\n }\r\n\r\n\r\n // ADMIN: modal dialog to edit details\r\n function openModal(type: any) {\r\n if (!modalIsOpen) {\r\n setModalIsOpen(true);\r\n setModalType(type);\r\n };\r\n }\r\n\r\n function editTrackClicked() {\r\n openModal('editTrack');\r\n }\r\n\r\n function editTrackKeywordsClicked() {\r\n openModal('editTrackKeywords');\r\n }\r\n\r\n function editTrackOnReleaseClicked() {\r\n openModal('editTrackOnRelease');\r\n }\r\n\r\n function addEmbedClicked() {\r\n openModal('editTrackEmbed');\r\n }\r\n\r\n function editMoodClicked() {\r\n openModal('editMood');\r\n }\r\n\r\n function deleteTrackClicked() {\r\n openModal('confirm');\r\n }\r\n function deleteEmbedClicked() {\r\n openModal('confirm_delete_embed');\r\n }\r\n\r\n function handleTrackDetailsDidChange() {\r\n // console.log('handleTrackDetailsDidChange not implemented');\r\n }\r\n\r\n function setSnackbarParams(sp: any) {\r\n setSnackbarIsOpen(sp.isOpen);\r\n setSnackbarSeverity(sp.severity);\r\n setSnackbarMessage(sp.message);\r\n }\r\n\r\n function handleSnackbarClose() {\r\n setSnackbarIsOpen(false);\r\n }\r\n\r\n function handleModalClose() {\r\n setModalIsOpen(false);\r\n }\r\n\r\n function handleKeywordWasRequested(chipName: string) {\r\n props.keywordWasRequested(chipName);\r\n props.onClose();\r\n }\r\n\r\n\r\n let displayed: any = (
No track has been selected
);\r\n if (props.trackId != null && props.trackId > -1) {\r\n displayed = (
\r\n {props.showModalCloseButton ? \r\n (
) \r\n : null}\r\n \r\n
\r\n
\r\n \r\n \r\n \r\n \r\n {showListenText ? (\r\n \r\n
Listen
\r\n
\r\n
) : null}\r\n \r\n \r\n \r\n
\r\n
\r\n
\r\n
\r\n
\r\n {embeddedInfoRenderArray.map(embed => embed)}\r\n
\r\n
\r\n\r\n
\r\n \r\n \r\n \r\n {snackbarMessage}\r\n \r\n \r\n
);\r\n };\r\n\r\n return (
{displayed}
)\r\n\r\n\r\n}\r\n\r\n","import { getApiBaseAddr, sendRequest } from '../util/util_api.js';\r\n\r\nimport { fetchKeywords } from './api_keyword';\r\nimport { TrackOverview, TrackDetail, TrackOnRelease, Release, ReleaseGroup } from '../dtos/dto';\r\n\r\nimport { sortTrackOverviews } from '../util/track.util';\r\n\r\n/*\r\npublic int TrackId { get; set; }\r\npublic string ClassName { get { return \"TrackOverview\"; } }\r\npublic string ArtistName { get; set; }\r\npublic string TitleMain { get; set; }\r\npublic string TitleSecondary { get; set; }\r\npublic int DurationSecs { get; set; }\r\n*/\r\nfunction fetchTrackOverviews(token: any, onSuccessCallbackFunc: (results: Array) => any, onErrorCallbackFunc = (err: any) => {}) {\r\n sendRequest('GET', 'track/overviews', {}, token)\r\n .then(result => result.json())\r\n .then(result => {\r\n const results = new Array();\r\n // let count = 0;\r\n result.objects.forEach((entry: any) => {\r\n const trackOverview = TrackOverview.createFromDto(entry);\r\n results.push(trackOverview);\r\n });\r\n //const sortedTrackOverviews = sortTrackOverviews(results, 'displayTitle', 'DESC');\r\n //console.log('sortedTrackOverviews!!! ', sortedTrackOverviews);\r\n onSuccessCallbackFunc(results);\r\n })\r\n .catch(err => {\r\n onErrorCallbackFunc(err);\r\n });\r\n}\r\n\r\n/*\r\npublic string ClassName { get { return \"TrackDetail\"; } }\r\npublic int? ArtistId { get; set; }\r\npublic TrackOverview TrackOverview { get; set; }\t// contains TrackId\r\npublic int? RemixOfTrackId { get; set; }\r\npublic int? RemixArtistId { get; set; }\r\npublic float? Bpm { get; set; }\r\npublic int? ArtistIdSecondary { get; set; }\r\n\r\npublic ReleaseOverview[] AppearsOnReleases { get; set; } = { };\r\n*/\r\n// a track id of -1 fetches a random track\r\nfunction fetchTrackDetail(trackId: number, onSuccessCallbackFunc: (trackDetail: TrackDetail) => any, onErrorCallbackFunc = (err: any) => {}) {\r\n fetch(getApiBaseAddr() + \"track/detail/\" + trackId)\r\n .then(result => result.json())\r\n .then(result => {\r\n if (result.objects.length > 0) {\r\n const dto: any = result.objects[0];\r\n const trackDetail = TrackDetail.createFromDto(dto);\r\n onSuccessCallbackFunc(trackDetail);\r\n }\r\n else {\r\n onErrorCallbackFunc(\"the track could not be found.\");\r\n }\r\n },\r\n error => {\r\n onErrorCallbackFunc(error);\r\n });\r\n}\r\n\r\nfunction getIdOfRandomTrack(onSuccessCallbackFunc: (trackId: number) => any, onErrorCallbackFunc = (err: any) => {}) {\r\n fetch(getApiBaseAddr() + \"track/rndid/\")\r\n .then(result => result.json())\r\n .then(result => {\r\n if (result.objects.length > 0) {\r\n const trackId = result.objects[0];\r\n onSuccessCallbackFunc(trackId);\r\n };\r\n },\r\n error => {\r\n onErrorCallbackFunc(error);\r\n });\r\n}\r\n\r\nfunction fetchSimilarTrackIds(trackId: number, onSuccessCallbackFunc: (trackIds: Array) => any, onErrorCallbackFunc = (err: any) => {}) {\r\n const params = { trackId, noOfItems: 10 };\r\n sendRequest('POST', 'track/closest-to', params)\r\n .then(result => result.json())\r\n .then(result => {\r\n if (result.objects != null) {\r\n onSuccessCallbackFunc(result.objects);\r\n } else {\r\n onSuccessCallbackFunc([]);\r\n }\r\n })\r\n .catch(err => {\r\n onErrorCallbackFunc(err);\r\n });\r\n}\r\n\r\nfunction submitNewTrack(token: any, params: any, onSuccessCallbackFunc: any, onErrorCallbackFunc = (err: any) => {}) {\r\n sendRequest('POST', 'track', params, token)\r\n .then(result => result.json())\r\n .then(result => {\r\n onSuccessCallbackFunc(result);\r\n })\r\n .catch(err => {\r\n onErrorCallbackFunc(err);\r\n });\r\n}\r\n\r\nfunction submitEditTrack(token: any, trackId: number, params: any, onSuccessCallbackFunc: any, onErrorCallbackFunc = (err: any) => {}) {\r\n \r\n sendRequest('PUT', 'track/' + trackId, params, token)\r\n .then(result => result.json())\r\n .then(result => {\r\n onSuccessCallbackFunc(result);\r\n })\r\n .catch(err => {\r\n onErrorCallbackFunc(err);\r\n });\r\n}\r\n\r\nfunction submitDeleteTrack(token: any, trackId: number, onSuccessCallbackFunc: any, onErrorCallbackFunc = (err: any) => {}) {\r\n sendRequest('DELETE', 'track/' + trackId, {}, token)\r\n .then(result => result.json())\r\n .then(result => {\r\n onSuccessCallbackFunc(result);\r\n })\r\n .catch(err => {\r\n onErrorCallbackFunc(err);\r\n });\r\n}\r\n\r\nfunction getTrackKeywordNamesFromResult(result: any) {\r\n const objects = result.objects;\r\n const nameArray = new Array();\r\n objects.forEach((obj: any) => {\r\n nameArray.push(obj.name);\r\n });\r\n return nameArray;\r\n}\r\n\r\nfunction fetchTrackKeywords(trackId: number, onSuccessCallbackFunc: any, onErrorCallbackFunc = (err: any) => {}) {\r\n fetch(getApiBaseAddr() + \"trackkeyword/allkw/\" + trackId)\r\n .then(res => res.json())\r\n .then((result) => {\r\n const nameArray = getTrackKeywordNamesFromResult(result);\r\n onSuccessCallbackFunc(nameArray);\r\n },\r\n (error) => {\r\n onErrorCallbackFunc(error);\r\n });\r\n}\r\n\r\n/*\r\n @param trackId the ID of the track (number)\r\n @param addKeywords: array of strings of keywords to add\r\n @param deleteKeywords: array of strings of keywords to delete\r\n*/\r\nfunction changeKeywordsForTrack(token: any, trackId: number, keywords: Array, onSuccessCallbackFunc: any, onErrorCallbackFunc = (err: any) => {}) {\r\n\r\n const params = { trackId, keywordList: keywords };\r\n\r\n sendRequest('POST', 'trackkeyword/setk4t', params, token)\r\n .then(result => result.json())\r\n .then(result => {\r\n // refetch all keywords (which are cached..)\r\n fetchKeywords((result) => {\r\n \r\n });\r\n //const nameArray = getTrackKeywordNamesFromResult(result);\r\n onSuccessCallbackFunc(result);\r\n })\r\n .catch(err => {\r\n onErrorCallbackFunc(err);\r\n });\r\n \r\n}\r\n\r\nfunction setMoodForTrack(token: any, trackId: number, moodX: number, moodY: number, onSuccessCallbackFunc: any, onErrorCallbackFunc = (err: any) => {}) {\r\n const params = {\r\n trackId,\r\n mood: {\r\n polarity: moodX, \r\n energy: moodY\r\n }\r\n };\r\n sendRequest('POST', 'mood/fortrack/', params, token)\r\n .then (result => result.json())\r\n .then(result => {\r\n \r\n onSuccessCallbackFunc(result);\r\n })\r\n .catch(err => {\r\n onErrorCallbackFunc(err);\r\n })\r\n}\r\n\r\nfunction getMoodForTrack(trackId: number, onSuccessCallbackFunc: any, onErrorCallbackFunc = (err: any) => {}) {\r\n fetch(getApiBaseAddr() + 'mood/fortrack/' + trackId)\r\n .then(result => result.json())\r\n .then(result => {\r\n if (result.objects != null) {\r\n if (result.objects.length > 0) {\r\n const x = result.objects[0].polarity;\r\n const y = result.objects[0].energy;\r\n onSuccessCallbackFunc({x, y});\r\n } else {\r\n onSuccessCallbackFunc({x: 0, y: 0});\r\n }\r\n \r\n } else {\r\n onErrorCallbackFunc({error: 'response received but objects is null!'});\r\n }\r\n },\r\n error => {\r\n onErrorCallbackFunc(error);\r\n });\r\n}\r\n// visible: true / false\r\nfunction changeVisibilityForAllTracks(token: any, visible: boolean, onSuccessCallbackFunc: any, onErrorCallbackFunc = (err: any) => {}) {\r\n sendRequest('POST', 'track/v4all', {visible}, token)\r\n .then (result => result.json())\r\n .then(result => {\r\n onSuccessCallbackFunc(result);\r\n })\r\n .catch(err => {\r\n onErrorCallbackFunc(err);\r\n });\r\n}\r\n\r\nfunction submitTrackOnRelease(token: any, trackOnRelease: TrackOnRelease, onSuccessCallbackFunc: any, onErrorCallbackFunc = (err: any) => {}) {\r\n sendRequest('POST', 'trackonrelease', trackOnRelease, token)\r\n .then(result => result.json())\r\n .then(result => {\r\n onSuccessCallbackFunc(result);\r\n })\r\n .catch(err => {\r\n onErrorCallbackFunc(err);\r\n });\r\n}\r\n\r\nfunction getReleasesForTrackId(trackId: number, onSuccessCallbackFunc: (releases: Array) => any, onErrorCallbackFunc = (err: any) => {}) {\r\n fetch(getApiBaseAddr() + \"release/fortrack/\" + trackId)\r\n .then(result => result.json())\r\n .then(result => {\r\n \r\n const releases = new Array();\r\n if(result.objects != null) {\r\n result.objects.forEach((dto: any) => {\r\n const release = Release.createFromDto(dto);\r\n releases.push(release);\r\n });\r\n };\r\n onSuccessCallbackFunc(releases);\r\n },\r\n error => {\r\n onErrorCallbackFunc(error);\r\n });\r\n}\r\n\r\nexport { fetchTrackOverviews, fetchTrackDetail, submitNewTrack, submitEditTrack, submitDeleteTrack, changeKeywordsForTrack, fetchTrackKeywords, setMoodForTrack, getMoodForTrack, changeVisibilityForAllTracks, fetchSimilarTrackIds, getIdOfRandomTrack, submitTrackOnRelease, getReleasesForTrackId }\r\n"," \r\n import React from 'react';\r\n\r\n import BandcampEmbed from '../embed/BandcampEmbed.tsx';\r\n import SoundCloudEmbed from '../embed/SoundCloudEmbed.tsx';\r\n import YouTubeEmbed from '../embed/YouTubeEmbed.tsx';\r\n import SpotifyEmbed from '../embed/SpotifyEmbed.tsx';\r\n import AppleMusicEmbed from '../embed/AppleMusicEmbed.tsx';\r\n\r\n // source: https://gist.github.com/takien/4077195\r\n function getYouTubeParams(embedCode) {\r\n try {\r\n var urlArray = embedCode.split(/(vi\\/|v=|\\/v\\/|youtu\\.be\\/|\\/embed\\/)/);\r\n return {\r\n netHostName: 'youtube',\r\n videoCode: (urlArray[2] !== undefined) ? urlArray[2].split(/[^0-9a-z_\\-]/i)[0] : urlArray[0]\r\n };\r\n } catch (e) {\r\n return {\r\n error: 'could not parse youtube code'\r\n }\r\n }\r\n }\r\n\r\n function getSoundCloudParams(embedCode) {\r\n try {\r\n return {\r\n netHostName: 'soundcloud',\r\n trackCode: embedCode.split('/tracks/')[1].split('&')[0]\r\n }\r\n } catch (e) {\r\n return {\r\n error: 'could not parse soundcloud code'\r\n }\r\n }\r\n }\r\n\r\n function getAppleParams(embedCode) {\r\n let srcString = '';\r\n try {\r\n srcString = embedCode.split('src=\"')[1];\r\n srcString = srcString.split('\">