diff --git a/package-lock.json b/package-lock.json index 8b6334a..53b6a02 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3,8 +3,35 @@ "version": "0.0.0", "lockfileVersion": 1, "requires": true, - "dependencies": { - "@aashutoshrathi/word-wrap": { + "packages": { + "": { + "name": "track-lineage", + "version": "0.0.0", + "dependencies": { + "axios": "^1.5.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "reactflow": "^11.8.3" + }, + "devDependencies": { + "@types/react": "^18.2.15", + "@types/react-dom": "^18.2.7", + "@typescript-eslint/eslint-plugin": "^6.0.0", + "@typescript-eslint/parser": "^6.0.0", + "@vitejs/plugin-react": "^4.0.3", + "autoprefixer": "^10.4.15", + "eslint": "^8.45.0", + "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-react-refresh": "^0.4.3", + "postcss": "^8.4.29", + "prettier": "^3.0.3", + "prettier-plugin-tailwindcss": "^0.5.4", + "tailwindcss": "^3.3.3", + "typescript": "^5.0.2", + "vite": "^4.4.5" + } + }, + "node_modules/@aashutoshrathi/word-wrap": { "version": "1.2.6", "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", @@ -1115,7 +1142,16 @@ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true }, +<<<<<<< HEAD + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/autoprefixer": { +======= "autoprefixer": { +>>>>>>> 2ff2e955c69f5d511fa624e5eeff4565bb0db28a "version": "10.4.15", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.15.tgz", "integrity": "sha512-KCuPB8ZCIqFdA4HwKXsvz7j6gvSDNhDP7WnUjBleRkKjPdvCmHFuQ77ocavI8FT6NdvlBnE2UFr2H4Mycn8Vew==", @@ -1129,7 +1165,21 @@ "postcss-value-parser": "^4.2.0" } }, +<<<<<<< HEAD + "node_modules/axios": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.5.0.tgz", + "integrity": "sha512-D4DdjDo5CY50Qms0qGQTTw6Q44jl7zRwY7bthds06pUGfChBCTcQs+N743eFWGEd6pRTMd6A+I87aWyFV5wiZQ==", + "dependencies": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/balanced-match": { +======= "balanced-match": { +>>>>>>> 2ff2e955c69f5d511fa624e5eeff4565bb0db28a "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", @@ -1237,7 +1287,22 @@ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true }, +<<<<<<< HEAD + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { +======= "commander": { +>>>>>>> 2ff2e955c69f5d511fa624e5eeff4565bb0db28a "version": "4.1.1", "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", @@ -1359,7 +1424,19 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, +<<<<<<< HEAD + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/didyoumean": { +======= "didyoumean": { +>>>>>>> 2ff2e955c69f5d511fa624e5eeff4565bb0db28a "version": "1.2.2", "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", @@ -1711,7 +1788,43 @@ "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", "dev": true }, +<<<<<<< HEAD + "node_modules/follow-redirects": { + "version": "1.15.3", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", + "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fraction.js": { +======= "fraction.js": { +>>>>>>> 2ff2e955c69f5d511fa624e5eeff4565bb0db28a "version": "4.3.6", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.6.tgz", "integrity": "sha512-n2aZ9tNfYDwaHhvFTkhFErqOMIb8uyzSQ+vGJBjZyanAKZVbGUQ1sngfk9FdkBw7G26O7AgNjLcecLffD1c7eg==", @@ -2024,7 +2137,30 @@ "picomatch": "^2.3.1" } }, +<<<<<<< HEAD + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { +======= "minimatch": { +>>>>>>> 2ff2e955c69f5d511fa624e5eeff4565bb0db28a "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", @@ -2280,7 +2416,16 @@ "integrity": "sha512-QZzzB1bID6qPsKHTeA9qPo1APmmxfFrA5DD3LQ+vbTmAnY40eJI7t9Q1ocqel2EKMWNPLJqdTDWZj1hKYgqSgg==", "dev": true }, +<<<<<<< HEAD + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "node_modules/punycode": { +======= "punycode": { +>>>>>>> 2ff2e955c69f5d511fa624e5eeff4565bb0db28a "version": "2.3.0", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", diff --git a/package.json b/package.json index eb5d4f6..11423b4 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "prettier:write": "prettier --check --write './**/*'" }, "dependencies": { + "axios": "^1.5.0", "react": "^18.2.0", "react-dom": "^18.2.0", "reactflow": "^11.8.3" diff --git a/src/CustomNode.tsx b/src/CustomNode.tsx index 3e2cd06..883995f 100644 --- a/src/CustomNode.tsx +++ b/src/CustomNode.tsx @@ -16,8 +16,8 @@ function CustomNode({ data, isConnectable }) { className="h-3 w-3 bg-purple" />
- -
+ {data.title} - {data.artist} +
Key: {data.key} BPM: {data.bpm} Style: {data.style} diff --git a/src/Header.tsx b/src/Header.tsx index 8be34af..d671bd4 100644 --- a/src/Header.tsx +++ b/src/Header.tsx @@ -1,4 +1,6 @@ + function Header() { + return (

Track Lineage

@@ -7,3 +9,4 @@ function Header() { } export default Header + diff --git a/src/Search.tsx b/src/Search.tsx index e23ef12..a1892e2 100644 --- a/src/Search.tsx +++ b/src/Search.tsx @@ -1,10 +1,68 @@ -import SearchList from './SearchList.tsx' +import SearchList from './SearchList.tsx'; +import { useEffect, useState } from 'react'; +import axios from 'axios'; + + +const CLIENT_ID = "0350c90137454dc5a748549664e5ba75" +const REDIRECT_URI = "http://localhost:5173" +const AUTH_ENDPOINT = "https://accounts.spotify.com/authorize" +const RESPONSE_TYPE = "token" function Search({ nodes, setNodes }: Props) { + + const [token, setToken] = useState("") + + useEffect(() => { + const hash = window.location.hash + let token = window.localStorage.getItem("token") + + if (!token && hash) { + token = hash.substring(1).split("&").find(elem => elem.startsWith("access_token")).split("=")[1] + + window.location.hash = "" + window.localStorage.setItem("token", token) + } + + setToken(token) + + }, []) + + const logout = () => { + setToken("") + window.localStorage.removeItem("token") + } + + const [searchKey, setSearchKey] = useState("") + const [tracks, setTracks] = useState([]) + + const searchTracks = async (e) => { + e.preventDefault() + const { data } = await axios.get("https://api.spotify.com/v1/search", { + headers: { + Authorization: `Bearer ${token}` + }, + params: { + q: searchKey, + type: "track" + } + }) + console.log(data) + setTracks(data.tracks.items) + + } + return ( -
- Search - +
+ {!token ? + Login + to Spotify + : } +
+ setSearchKey(e.target.value)} class="col-span-4 bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" /> + +
+
+
) } diff --git a/src/SearchList.tsx b/src/SearchList.tsx index 0b1c3b8..b553635 100644 --- a/src/SearchList.tsx +++ b/src/SearchList.tsx @@ -6,40 +6,33 @@ type Props = { nodes: Node[] setNodes: React.Dispatch> } -function SearchList({ nodes, setNodes }: Props) { - function onSubmit(node, event: FormEvent) { +function SearchList({ nodes, setNodes, tracks}: Props) { + + function onSubmit(track, event: FormEvent) { event.preventDefault() - console.log(node) + console.log(track) setNodes( nodes.concat({ - id: node.id, - type: 'customNode', - data: { - label: node.data.label, - bpm: node.data.bpm, - key: node.data.key, - style: node.data.style, - }, + id: track.id, + type: "customNode", + data: { title: track.name, artist: track.artists[0].name, bpm: "110", key: "Eb", style: "Disco", image: track.album.images[0].url }, position: { x: 500, y: 25 }, }), ) } return ( -
- {node_library.map((node) => ( -
-
onSubmit(node, e)} - key={node.id} - > +
+ {tracks.map(track => ( +
+ onSubmit(track, e)} key={track.id}>
-

- {node.data.label} +

+ + {track.name} +

+

+ {track.artists[0].name}

diff --git a/src/nodes.tsx b/src/nodes.tsx index 02ab603..a2fa9a2 100644 --- a/src/nodes.tsx +++ b/src/nodes.tsx @@ -1,12 +1,16 @@ -function create_library(nb_title: number) { - var tmp = [] - for (let i = 0; i < nb_title; i++) { - const node = { - id: `${i}`, - sourcePosition: 'right', - targetPosition: 'left', - data: { label: `Title ${i}`, bpm: '110', key: 'Eb', style: 'Disco' }, - position: { x: 500, y: 100 }, + + +function create_library(nb_title: number){ + var tmp = []; + for (let i = 0; i < nb_title; i++) { + const node = { + id: `${i}`, + sourcePosition: 'right', + targetPosition: 'left', + data: { title: `Title ${i}`, artist: `Artist ${i*2}`, bpm: '110', key: 'Eb', style:'Disco' }, + position: { x: 500, y: 100 }, + }; + tmp.push(node); } tmp.push(node) } diff --git a/tailwind.config.js b/tailwind.config.js index 59a0365..086818b 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -8,6 +8,7 @@ export default { extend: { colors: { 'purple': '#8926D7', + 'light-purple': 'rgba(137, 38, 215, 0.2)', }, }, },