From 15784b8a674fafff13698853e786fca956d497e3 Mon Sep 17 00:00:00 2001 From: rui hildt Date: Mon, 3 Aug 2020 01:07:37 +0200 Subject: [PATCH] Updates --- asset-manifest.json | 8 ++++---- index.html | 2 +- ... precache-manifest.7bcffd4b12b982dc6e7670b7e41edd35.js | 6 +++--- service-worker.js | 2 +- static/js/main.94b0e65e.chunk.js | 2 -- static/js/main.94b0e65e.chunk.js.map | 1 - static/js/main.d9d52cb5.chunk.js | 2 ++ static/js/main.d9d52cb5.chunk.js.map | 1 + 8 files changed, 12 insertions(+), 12 deletions(-) rename precache-manifest.e0d7fbf4f59ffe089090a76fa910bffc.js => precache-manifest.7bcffd4b12b982dc6e7670b7e41edd35.js (79%) delete mode 100644 static/js/main.94b0e65e.chunk.js delete mode 100644 static/js/main.94b0e65e.chunk.js.map create mode 100644 static/js/main.d9d52cb5.chunk.js create mode 100644 static/js/main.d9d52cb5.chunk.js.map diff --git a/asset-manifest.json b/asset-manifest.json index 5d7172e..499df7e 100644 --- a/asset-manifest.json +++ b/asset-manifest.json @@ -1,13 +1,13 @@ { "files": { - "main.js": "/spoti-search/static/js/main.94b0e65e.chunk.js", - "main.js.map": "/spoti-search/static/js/main.94b0e65e.chunk.js.map", + "main.js": "/spoti-search/static/js/main.d9d52cb5.chunk.js", + "main.js.map": "/spoti-search/static/js/main.d9d52cb5.chunk.js.map", "runtime-main.js": "/spoti-search/static/js/runtime-main.190f0ea6.js", "runtime-main.js.map": "/spoti-search/static/js/runtime-main.190f0ea6.js.map", "static/js/2.f957e75b.chunk.js": "/spoti-search/static/js/2.f957e75b.chunk.js", "static/js/2.f957e75b.chunk.js.map": "/spoti-search/static/js/2.f957e75b.chunk.js.map", "index.html": "/spoti-search/index.html", - "precache-manifest.e0d7fbf4f59ffe089090a76fa910bffc.js": "/spoti-search/precache-manifest.e0d7fbf4f59ffe089090a76fa910bffc.js", + "precache-manifest.7bcffd4b12b982dc6e7670b7e41edd35.js": "/spoti-search/precache-manifest.7bcffd4b12b982dc6e7670b7e41edd35.js", "service-worker.js": "/spoti-search/service-worker.js", "static/js/2.f957e75b.chunk.js.LICENSE.txt": "/spoti-search/static/js/2.f957e75b.chunk.js.LICENSE.txt", "static/media/placeholder-music.jpg": "/spoti-search/static/media/placeholder-music.97fa2780.jpg" @@ -15,6 +15,6 @@ "entrypoints": [ "static/js/runtime-main.190f0ea6.js", "static/js/2.f957e75b.chunk.js", - "static/js/main.94b0e65e.chunk.js" + "static/js/main.d9d52cb5.chunk.js" ] } \ No newline at end of file diff --git a/index.html b/index.html index cfdd22b..d6217ce 100644 --- a/index.html +++ b/index.html @@ -1 +1 @@ -Spoti Search
\ No newline at end of file +Spoti Search
\ No newline at end of file diff --git a/precache-manifest.e0d7fbf4f59ffe089090a76fa910bffc.js b/precache-manifest.7bcffd4b12b982dc6e7670b7e41edd35.js similarity index 79% rename from precache-manifest.e0d7fbf4f59ffe089090a76fa910bffc.js rename to precache-manifest.7bcffd4b12b982dc6e7670b7e41edd35.js index d98d8cf..5ba27c9 100644 --- a/precache-manifest.e0d7fbf4f59ffe089090a76fa910bffc.js +++ b/precache-manifest.7bcffd4b12b982dc6e7670b7e41edd35.js @@ -1,6 +1,6 @@ self.__precacheManifest = (self.__precacheManifest || []).concat([ { - "revision": "d25d3f46d075a4589752c0c039f6138c", + "revision": "9b66654bcf7970de498783466f7bdf37", "url": "/spoti-search/index.html" }, { @@ -12,8 +12,8 @@ self.__precacheManifest = (self.__precacheManifest || []).concat([ "url": "/spoti-search/static/js/2.f957e75b.chunk.js.LICENSE.txt" }, { - "revision": "d84077c0bcbf8ffed5b0", - "url": "/spoti-search/static/js/main.94b0e65e.chunk.js" + "revision": "2b25514f4dc36ba4e05e", + "url": "/spoti-search/static/js/main.d9d52cb5.chunk.js" }, { "revision": "66fb266ab25aa742c873", diff --git a/service-worker.js b/service-worker.js index cd363af..0d21731 100644 --- a/service-worker.js +++ b/service-worker.js @@ -14,7 +14,7 @@ importScripts("https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js"); importScripts( - "/spoti-search/precache-manifest.e0d7fbf4f59ffe089090a76fa910bffc.js" + "/spoti-search/precache-manifest.7bcffd4b12b982dc6e7670b7e41edd35.js" ); self.addEventListener('message', (event) => { diff --git a/static/js/main.94b0e65e.chunk.js b/static/js/main.94b0e65e.chunk.js deleted file mode 100644 index f5dd8af..0000000 --- a/static/js/main.94b0e65e.chunk.js +++ /dev/null @@ -1,2 +0,0 @@ -(this["webpackJsonpspoti-search"]=this["webpackJsonpspoti-search"]||[]).push([[0],{115:function(e,t,a){e.exports=a(131)},131:function(e,t,a){"use strict";a.r(t);var r=a(0),n=a.n(r),i=a(33),l=a.n(i),c=a(57),o=a(58),s=a(89),m=a(56),u=a(52),g=a(92),d=a(145),p=a(93),h=a(78),f=a(90),b=a(146),E=a(147),v=function(){return n.a.createElement(b.a,{as:"header",direction:"row",align:"center",justify:"center",background:"brand",pad:{left:"medium",right:"small",vertical:"small"},style:{zIndex:1}},n.a.createElement(E.a,{margin:{vertical:"small"},color:"light-1",size:"xxlarge",weight:"bold"},"Spoti Search"))},y=a(143),x=a(144),j=function(e){var t=e.inputValue,a=e.handleChange,r=e.suggestions,i=e.handleSelect;return n.a.createElement(b.a,{as:"section",direction:"row",justify:"center",margin:{top:"large"}},n.a.createElement(b.a,{as:"div",margin:{vertical:"none"},width:"500px"},n.a.createElement(y.a,{type:"search",name:"q",value:t,suggestions:r,onChange:function(e){return a(e.target.value)},onSelect:function(e){return i(e.suggestion)},icon:n.a.createElement(x.a,{color:"plain"}),dropHeight:"large",placeholder:"Type an artist name",autoFocus:!0,"aria-label":"Search for an artist name"})))},w=a(150),O=a(149),k=a(142),S=a(148),A=a(49),q=a.n(A),C=function(e){var t=e.image,a=e.name;return t||(t=q.a),n.a.createElement(b.a,{round:"xxsmall",elevation:"small",overflow:"hidden"},n.a.createElement(b.a,{height:"300px"},n.a.createElement(S.a,{src:t,fit:"cover"})),n.a.createElement(O.a,{level:"4",margin:{bottom:"small",top:"small",left:"small"}},a))},z=function(e){var t=e.image,a=e.name,r=e.handleClick;return t||(t=q.a),n.a.createElement(b.a,{round:"xxsmall",pad:"xsmall",onClick:function(){return r(a)},width:"130px"},n.a.createElement(b.a,{height:"120px",width:"120px",round:"full",background:{repeat:"no-repeat",size:"cover",image:"url(".concat(t,")")}}),n.a.createElement(E.a,{margin:{bottom:"small",top:"small",left:"small"},textAlign:"center",weight:"bold",wordBreak:"break-word"},a))},N=function(e){var t=e.artists,a=e.handleClick,r=t[0],i=r.name,l=r.image,c=r.albums,o=t.slice(1,t.length),s=[],m=l;l||(m=q.a);var u=new Set;return c.forEach((function(e){u.has(e.name)||(u.add(e.name),s.push(e))})),n.a.createElement(w.a,{as:"section",rows:["fit","fit"],columns:["fit","fit"],gap:"large",areas:[["title","title"],["artist-other","artist-other"],["disco-title","disco-title"],["discography","discography"]],pad:"xlarge"},n.a.createElement(O.a,{level:"1",gridArea:"title",size:"medium",margin:{vertical:"none"}},i),n.a.createElement(b.a,{gridArea:"artist-other",direction:"row-responsive",responsive:!0,gap:"large"},n.a.createElement(b.a,{width:{min:"300px",max:"300px"}},n.a.createElement(b.a,{round:"full",background:{repeat:"no-repeat",size:"cover",image:"url(".concat(m,")")},height:"300px",width:"300px"})),n.a.createElement(b.a,{justify:"center"},n.a.createElement(O.a,{level:"2",margin:{vertical:"none"},size:"small"},"Other results"),n.a.createElement(b.a,{direction:"row-reverse",justify:"end",wrap:!0,gap:"medium",width:{min:"332px"}},o.map((function(e){return n.a.createElement(z,{key:e.id,image:e.image,name:e.name,handleClick:a})}))))),n.a.createElement(O.a,{level:"2",gridArea:"disco-title",size:"medium",margin:{bottom:"none"}},"Discography"),n.a.createElement(k.a.Consumer,null,(function(e){return n.a.createElement(w.a,{gridArea:"discography",align:"start",columns:{count:"fill",size:"260px"},gap:"large"},s.map((function(e){return n.a.createElement(C,{key:e.id,image:e.image,name:e.name})})))})))};function L(){var e=Object(g.a)(["\n\tquery Artist($byName: String!) {\n\t\tqueryArtists(byName: $byName) {\n\t\t\tname\n\t\t\timage\n\t\t\tid\n\t\t\talbums {\n\t\t\t\tname\n\t\t\t\timage\n\t\t\t\tid\n\t\t\t}\n\t\t}\n\t}\n"]);return L=function(){return e},e}var Q=Object(h.a)(L());function B(){var e=Object(r.useState)(""),t=Object(u.a)(e,2),a=t[0],i=t[1],l=Object(f.a)(Q),c=Object(u.a)(l,2),o=c[0],s=c[1],g=s.data,h=s.error,b=(s.loading,s.variables,Object(r.useState)([])),E=Object(u.a)(b,2),y=E[0],x=E[1],w=Object(r.useState)([]),O=Object(u.a)(w,2),k=O[0],S=O[1],A=Object(r.useState)(!1),q=Object(u.a)(A,2),C=q[0],z=q[1],L=Object(r.useCallback)(Object(p.debounce)((function(){o({variables:{byName:a}})}),200),[a]);Object(r.useEffect)((function(){return L(),L.cancel}),[a,L]);Object(r.useEffect)((function(){if(g&&g.queryArtists&&g.queryArtists!==[]){var e=g.queryArtists.slice(0,5).map((function(e){return e.name}));S(e)}}),[g]);var B=!1;return h&&h.graphQLErrors&&h.graphQLErrors.forEach((function(e){B="Error: 400: No search query"===e.message})),n.a.createElement(d.a,{theme:I},n.a.createElement(v,null),n.a.createElement(j,{inputValue:a,suggestions:k,handleChange:function(e){i(e)},handleSelect:function(e){for(var t=[],a=g.queryArtists.slice(0,5).map((function(e){return e})),r=0;r {\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\tSpoti Search\n\t\t\t\n\t\t\n\t);\n};\n","import React from 'react';\nimport { Box, TextInput } from 'grommet';\nimport { FormSearch } from 'grommet-icons';\n\nexport const Search = ({\n\tinputValue,\n\thandleChange,\n\tsuggestions,\n\thandleSelect,\n}: {\n\tinputValue: string;\n\thandleChange: (value: string) => void;\n\tsuggestions: string[];\n\thandleSelect: (suggestion: string) => void;\n}) => (\n\t\n\t\t\n\t\t\t handleChange(e.target.value)}\n\t\t\t\tonSelect={(target) => handleSelect(target.suggestion)}\n\t\t\t\ticon={}\n\t\t\t\tdropHeight='large'\n\t\t\t\tplaceholder='Type an artist name'\n\t\t\t\tautoFocus\n\t\t\t\taria-label='Search for an artist name'\n\t\t\t/>\n\t\t\n\t\n);","import React from 'react';\nimport { Box, Heading, Image } from 'grommet';\n\nimport placeholder from '../assets/placeholder-music.jpg';\n\nexport const Album = ({ image, name }: { image: string; name: string }) => {\n\t// Load placeholder image if none provided\n\tif (!image) {\n\t\timage = placeholder;\n\t}\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\t{name}\n\t\t\t\n\t\t\n\t);\n};\n","import React from 'react';\nimport { Box, Text } from 'grommet';\n\nimport placeholder from '../assets/placeholder-music.jpg';\n\nexport const Other = ({\n\timage,\n\tname,\n\thandleClick,\n}: {\n\timage: string;\n\tname: string;\n\thandleClick: (name: string) => void;\n}) => {\n\t// Load placeholder image if none provided\n\tif (!image) {\n\t\timage = placeholder;\n\t}\n\n\treturn (\n\t\t handleClick(name)}\n\t\t\twidth='130px'\n\t\t>\n\t\t\t\n\t\t\t\n\t\t\t\t{name}\n\t\t\t\n\t\t\n\t);\n};\n","import React from 'react';\nimport { Box, Grid, ResponsiveContext, Heading } from 'grommet';\n\nimport { Album } from './Album';\nimport { Artists, Albums } from '../interfaces';\nimport { Other } from './Other';\nimport placeholder from '../assets/placeholder-music.jpg';\n\nexport const Results = ({\n\tartists,\n\thandleClick,\n}: {\n\tartists: Artists;\n\thandleClick: (name: string) => void;\n}) => {\n\tconst { name: selectedName, image, albums } = artists[0];\n\tconst otherArtists = artists.slice(1, artists.length);\n\tlet selectedAlbums: Albums = [];\n\tlet selectedImage: string = image;\n\n\t// Load placeholder image if none provided\n\tif (!image) {\n\t\tselectedImage = placeholder;\n\t}\n\n\t// Remove duplicate albums based on `name`\n\t// Might need to refine this according to the data quality\n\tconst uniqueAlbums = new Set();\n\talbums.forEach((album) => {\n\t\tif (!uniqueAlbums.has(album.name)) {\n\t\t\tuniqueAlbums.add(album.name);\n\t\t\tselectedAlbums.push(album);\n\t\t}\n\t});\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t{selectedName}\n\t\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\tOther results\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t{otherArtists.map((artist) => (\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t))}\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\tDiscography\n\t\t\t\n\t\t\t\n\t\t\t\t{(size) => (\n\t\t\t\t\t\n\t\t\t\t\t\t{selectedAlbums.map((album) => (\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t))}\n\t\t\t\t\t\n\t\t\t\t)}\n\t\t\t\n\t\t\n\t);\n};\n","import React, { useState, useCallback, useEffect } from 'react';\nimport { Grommet } from 'grommet';\nimport { debounce } from 'lodash';\nimport { gql, useLazyQuery } from '@apollo/client';\n\nimport { Header } from './Header';\nimport { Search } from './Search';\nimport { Results } from './Results';\nimport { Artists, Artist } from '../interfaces';\n\nconst QUERY_ARTISTS = gql`\n\tquery Artist($byName: String!) {\n\t\tqueryArtists(byName: $byName) {\n\t\t\tname\n\t\t\timage\n\t\t\tid\n\t\t\talbums {\n\t\t\t\tname\n\t\t\t\timage\n\t\t\t\tid\n\t\t\t}\n\t\t}\n\t}\n`;\n\nexport default function App() {\n\tconst [inputValue, setInputValue] = useState('');\n\tconst [getArtists, { data, error, loading, variables }] = useLazyQuery(\n\t\tQUERY_ARTISTS,\n\t);\n\tconst [artists, setArtists] = useState([]);\n\tconst [suggestions, setSuggestions] = useState([]);\n\tconst [selected, setSelected] = useState(false);\n\n\t// Debounce the database query\n\t// Based on: https://archive.is/wip/6JDqb\n\tconst handleChange = (value: string) => {\n\t\tsetInputValue(value);\n\t};\n\n\tconst updateQuery = () => {\n\t\tgetArtists({ variables: { byName: inputValue } });\n\t};\n\n\tconst delayedQuery = useCallback(debounce(updateQuery, 200), [inputValue]);\n\n\tuseEffect(() => {\n\t\tdelayedQuery();\n\t\t// Cancel previous debounce calls during useEffect cleanup.\n\t\treturn delayedQuery.cancel;\n\t}, [inputValue, delayedQuery]);\n\n\tconst handleSelect = (suggestion: string) => {\n\t\tlet updatedArtists: Artists = [];\n\n\t\tlet suggestedArtists: Artists = data.queryArtists\n\t\t\t.slice(0, 5)\n\t\t\t// Map to make a copy of the array, maybe uneeded\n\t\t\t.map((artist: Artist) => artist);\n\n\t\t// Find the selected artist and move it to index 0\n\t\tfor (let i = 0; i < suggestedArtists!.length; i++) {\n\t\t\tif (suggestedArtists![i].name === suggestion) {\n\t\t\t\tlet selectedArtist: Artists = suggestedArtists?.splice(i, 1);\n\t\t\t\tlet otherArtists: Artists = suggestedArtists;\n\t\t\t\tupdatedArtists = [...selectedArtist, ...otherArtists];\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tsetArtists(updatedArtists);\n\t\tsetSelected(true);\n\t};\n\n\tconst handleClick = (name: string) => {\n\t\tlet updatedArtists: Artists = [];\n\n\t\tfor (let i = 0; i < artists.length; i++) {\n\t\t\tif (artists[i].name === name) {\n\t\t\t\tlet selectedArtist: Artists = artists.splice(i, 1);\n\t\t\t\tlet otherArtists: Artists = artists;\n\t\t\t\tupdatedArtists = [...selectedArtist, ...otherArtists];\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tsetArtists(updatedArtists);\n\t};\n\n\tuseEffect(() => {\n\t\tif (data && data.queryArtists && data.queryArtists !== []) {\n\t\t\t// Limit artists to 5\n\t\t\tconst updatedArtists = data.queryArtists.slice(0, 5);\n\t\t\tconst updatedSuggestions: string[] = updatedArtists.map(\n\t\t\t\t(el: Artist) => {\n\t\t\t\t\treturn el.name;\n\t\t\t\t},\n\t\t\t);\n\t\t\tsetSuggestions(updatedSuggestions);\n\t\t}\n\t}, [data]);\n\n\t// Create flag to filter \"No search query\" errors\n\tlet errorNoSearchQuery = false;\n\tif (error && error.graphQLErrors) {\n\t\terror.graphQLErrors.forEach((error) => {\n\t\t\tif (error.message === 'Error: 400: No search query') {\n\t\t\t\terrorNoSearchQuery = true;\n\t\t\t} else {\n\t\t\t\terrorNoSearchQuery = false;\n\t\t\t}\n\t\t});\n\t}\n\n\treturn (\n\t\t\n\t\t\t
\n\t\t\t\n\t\t\t{selected && (\n\t\t\t\t\n\t\t\t)}\n\t\t\t{error && !errorNoSearchQuery && (\n\t\t\t\t
\n\t\t\t\t\t{error.graphQLErrors.map(({ message }, i) => (\n\t\t\t\t\t\t{message}\n\t\t\t\t\t))}\n\t\t\t\t
\n\t\t\t)}\n\t\t\n\t);\n}\n\nconst theme = {\n\tglobal: {\n\t\tcolors: {\n\t\t\tbrand: 'rgb(24, 177, 147)',\n\t\t},\n\t\tfont: {\n\t\t\tfamily: 'Roboto',\n\t\t\tsize: '18px',\n\t\t\theight: '20px',\n\t\t},\n\t},\n};\n","import React from 'react';\nimport ReactDOM from 'react-dom';\nimport { ApolloClient, InMemoryCache, ApolloProvider } from '@apollo/client';\n\nimport App from './components/App';\n\nconst client = new ApolloClient({\n\turi: 'https://spotify-graphql-server.herokuapp.com/graphql',\n\tcache: new InMemoryCache(),\n});\n\nReactDOM.render(\n\t\n\t\t\n\t\t\t\n\t\t\n\t,\n\tdocument.getElementById('root'),\n);\n","module.exports = __webpack_public_path__ + \"static/media/placeholder-music.97fa2780.jpg\";"],"sourceRoot":""} \ No newline at end of file diff --git a/static/js/main.d9d52cb5.chunk.js b/static/js/main.d9d52cb5.chunk.js new file mode 100644 index 0000000..d6f25d6 --- /dev/null +++ b/static/js/main.d9d52cb5.chunk.js @@ -0,0 +1,2 @@ +(this["webpackJsonpspoti-search"]=this["webpackJsonpspoti-search"]||[]).push([[0],{115:function(e,t,a){e.exports=a(131)},131:function(e,t,a){"use strict";a.r(t);var r=a(0),n=a.n(r),i=a(33),l=a.n(i),c=a(57),o=a(58),s=a(89),m=a(56),u=a(52),g=a(92),p=a(145),d=a(93),h=a(78),f=a(90),b=a(146),E=a(147),v=function(){return n.a.createElement(b.a,{as:"header",direction:"row",align:"center",justify:"center",background:"brand",pad:{left:"medium",right:"small",vertical:"small"},style:{zIndex:1}},n.a.createElement(E.a,{margin:{vertical:"small"},color:"light-1",size:"xxlarge",weight:"bold"},"Spoti Search"))},y=a(143),x=a(144),j=function(e){var t=e.inputValue,a=e.handleChange,r=e.suggestions,i=e.handleSelect;return n.a.createElement(b.a,{as:"section",direction:"row",justify:"center",margin:{top:"large"}},n.a.createElement(b.a,{as:"div",margin:{vertical:"none"},width:"500px"},n.a.createElement(y.a,{type:"search",name:"q",value:t,suggestions:r,onChange:function(e){return a(e.target.value)},onSelect:function(e){return i(e.suggestion)},icon:n.a.createElement(x.a,{color:"plain"}),dropHeight:"large",placeholder:"Type an artist name",autoFocus:!0,"aria-label":"Search by artist name"})))},w=a(150),O=a(149),k=a(142),S=a(148),A=a(49),q=a.n(A),C=function(e){var t=e.image,a=e.name;return t||(t=q.a),n.a.createElement(b.a,{round:"xxsmall",elevation:"small",overflow:"hidden"},n.a.createElement(b.a,{height:"300px"},n.a.createElement(S.a,{src:t,fit:"cover"})),n.a.createElement(O.a,{level:"4",margin:{bottom:"small",top:"small",left:"small"}},a))},z=function(e){var t=e.image,a=e.name,r=e.handleClick;return t||(t=q.a),n.a.createElement(b.a,{round:"xxsmall",pad:"xsmall",onClick:function(){return r(a)},width:"130px"},n.a.createElement(b.a,{height:"120px",width:"120px",round:"full",background:{repeat:"no-repeat",size:"cover",image:"url(".concat(t,")")}}),n.a.createElement(E.a,{margin:{bottom:"small",top:"small",left:"small"},textAlign:"center",weight:"bold",wordBreak:"break-word"},a))},N=function(e){var t=e.artists,a=e.handleClick,r=t[0],i=r.name,l=r.image,c=r.albums,o=t.slice(1,t.length),s=[],m=l;l||(m=q.a);var u=new Set;return c.forEach((function(e){u.has(e.name)||(u.add(e.name),s.push(e))})),n.a.createElement(w.a,{as:"section",rows:["fit","fit"],columns:["fit","fit"],gap:"large",areas:[["title","title"],["artist-other","artist-other"],["disco-title","disco-title"],["discography","discography"]],pad:"xlarge"},n.a.createElement(O.a,{level:"1",gridArea:"title",size:"medium",margin:{vertical:"none"}},i),n.a.createElement(b.a,{gridArea:"artist-other",direction:"row-responsive",responsive:!0,gap:"large"},n.a.createElement(b.a,{width:{min:"300px",max:"300px"}},n.a.createElement(b.a,{round:"full",background:{repeat:"no-repeat",size:"cover",image:"url(".concat(m,")")},height:"300px",width:"300px"})),n.a.createElement(b.a,{justify:"center"},n.a.createElement(O.a,{level:"2",margin:{vertical:"none"},size:"small"},"Other results"),n.a.createElement(b.a,{direction:"row-reverse",justify:"end",wrap:!0,gap:"medium",width:{min:"332px"}},o.map((function(e){return n.a.createElement(z,{key:e.id,image:e.image,name:e.name,handleClick:a})}))))),n.a.createElement(O.a,{level:"2",gridArea:"disco-title",size:"medium",margin:{bottom:"none"}},"Discography"),n.a.createElement(k.a.Consumer,null,(function(e){return n.a.createElement(w.a,{gridArea:"discography",align:"start",columns:{count:"fill",size:"260px"},gap:"large"},s.map((function(e){return n.a.createElement(C,{key:e.id,image:e.image,name:e.name})})))})))};function L(){var e=Object(g.a)(["\n\tquery Artist($byName: String!) {\n\t\tqueryArtists(byName: $byName) {\n\t\t\tname\n\t\t\timage\n\t\t\tid\n\t\t\talbums {\n\t\t\t\tname\n\t\t\t\timage\n\t\t\t\tid\n\t\t\t}\n\t\t}\n\t}\n"]);return L=function(){return e},e}var Q=Object(h.a)(L());function B(){var e=Object(r.useState)(""),t=Object(u.a)(e,2),a=t[0],i=t[1],l=Object(f.a)(Q),c=Object(u.a)(l,2),o=c[0],s=c[1],g=s.data,h=s.error,b=Object(r.useState)([]),E=Object(u.a)(b,2),y=E[0],x=E[1],w=Object(r.useState)([]),O=Object(u.a)(w,2),k=O[0],S=O[1],A=Object(r.useState)(!1),q=Object(u.a)(A,2),C=q[0],z=q[1],L=Object(r.useCallback)(Object(d.debounce)((function(){o({variables:{byName:a}})}),200),[a]);Object(r.useEffect)((function(){return L(),L.cancel}),[a,L]);Object(r.useEffect)((function(){if(g&&g.queryArtists&&g.queryArtists!==[]){var e=g.queryArtists.slice(0,5).map((function(e){return e.name}));S(e)}}),[g]);var B=!1;return h&&h.graphQLErrors&&h.graphQLErrors.forEach((function(e){B="Error: 400: No search query"===e.message})),n.a.createElement(p.a,{theme:I},n.a.createElement(v,null),n.a.createElement(j,{inputValue:a,suggestions:k,handleChange:function(e){i(e)},handleSelect:function(e){for(var t=[],a=g.queryArtists.slice(0,5).map((function(e){return e})),r=0;r {\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\tSpoti Search\n\t\t\t\n\t\t\n\t);\n};\n","import React from 'react';\nimport { Box, TextInput } from 'grommet';\nimport { FormSearch } from 'grommet-icons';\n\nexport const Search = ({\n\tinputValue,\n\thandleChange,\n\tsuggestions,\n\thandleSelect,\n}: {\n\tinputValue: string;\n\thandleChange: (value: string) => void;\n\tsuggestions: string[];\n\thandleSelect: (suggestion: string) => void;\n}) => (\n\t\n\t\t\n\t\t\t handleChange(e.target.value)}\n\t\t\t\tonSelect={(target) => handleSelect(target.suggestion)}\n\t\t\t\ticon={}\n\t\t\t\tdropHeight='large'\n\t\t\t\tplaceholder='Type an artist name'\n\t\t\t\tautoFocus\n\t\t\t\taria-label='Search by artist name'\n\t\t\t/>\n\t\t\n\t\n);","import React from 'react';\nimport { Box, Heading, Image } from 'grommet';\n\nimport placeholder from '../assets/placeholder-music.jpg';\n\nexport const Album = ({ image, name }: { image: string; name: string }) => {\n\t// Load placeholder image if none provided\n\tif (!image) {\n\t\timage = placeholder;\n\t}\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\t{name}\n\t\t\t\n\t\t\n\t);\n};\n","import React from 'react';\nimport { Box, Text } from 'grommet';\n\nimport placeholder from '../assets/placeholder-music.jpg';\n\nexport const Other = ({\n\timage,\n\tname,\n\thandleClick,\n}: {\n\timage: string;\n\tname: string;\n\thandleClick: (name: string) => void;\n}) => {\n\t// Load placeholder image if none provided\n\tif (!image) {\n\t\timage = placeholder;\n\t}\n\n\treturn (\n\t\t handleClick(name)}\n\t\t\twidth='130px'\n\t\t>\n\t\t\t\n\t\t\t\n\t\t\t\t{name}\n\t\t\t\n\t\t\n\t);\n};\n","import React from 'react';\nimport { Box, Grid, ResponsiveContext, Heading } from 'grommet';\n\nimport { Album } from './Album';\nimport { Artists, Albums } from '../interfaces';\nimport { Other } from './Other';\nimport placeholder from '../assets/placeholder-music.jpg';\n\nexport const Results = ({\n\tartists,\n\thandleClick,\n}: {\n\tartists: Artists;\n\thandleClick: (name: string) => void;\n}) => {\n\tconst { name: selectedName, image, albums } = artists[0];\n\tconst otherArtists = artists.slice(1, artists.length);\n\tlet selectedAlbums: Albums = [];\n\tlet selectedImage: string = image;\n\n\t// Load placeholder image if none provided\n\tif (!image) {\n\t\tselectedImage = placeholder;\n\t}\n\n\t// Remove duplicate albums based on `name`\n\t// Might need to refine this according to the data quality\n\tconst uniqueAlbums = new Set();\n\talbums.forEach((album) => {\n\t\tif (!uniqueAlbums.has(album.name)) {\n\t\t\tuniqueAlbums.add(album.name);\n\t\t\tselectedAlbums.push(album);\n\t\t}\n\t});\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t{selectedName}\n\t\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\tOther results\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t{otherArtists.map((artist) => (\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t))}\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\tDiscography\n\t\t\t\n\t\t\t\n\t\t\t\t{(size) => (\n\t\t\t\t\t\n\t\t\t\t\t\t{selectedAlbums.map((album) => (\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t))}\n\t\t\t\t\t\n\t\t\t\t)}\n\t\t\t\n\t\t\n\t);\n};\n","import React, { useState, useCallback, useEffect } from 'react';\nimport { Grommet } from 'grommet';\nimport { debounce } from 'lodash';\nimport { gql, useLazyQuery } from '@apollo/client';\n\nimport { Header } from './Header';\nimport { Search } from './Search';\nimport { Results } from './Results';\nimport { Artists, Artist } from '../interfaces';\n\nexport const QUERY_ARTISTS = gql`\n\tquery Artist($byName: String!) {\n\t\tqueryArtists(byName: $byName) {\n\t\t\tname\n\t\t\timage\n\t\t\tid\n\t\t\talbums {\n\t\t\t\tname\n\t\t\t\timage\n\t\t\t\tid\n\t\t\t}\n\t\t}\n\t}\n`;\n\nexport default function App() {\n\tconst [inputValue, setInputValue] = useState('');\n\tconst [getArtists, { data, error }] = useLazyQuery(\n\t\tQUERY_ARTISTS,\n\t);\n\tconst [artists, setArtists] = useState([]);\n\tconst [suggestions, setSuggestions] = useState([]);\n\tconst [selected, setSelected] = useState(false);\n\n\t// Debounce the database query\n\t// Based on: https://archive.is/wip/6JDqb\n\tconst handleChange = (value: string) => {\n\t\tsetInputValue(value);\n\t};\n\n\tconst updateQuery = () => {\n\t\tgetArtists({ variables: { byName: inputValue } });\n\t};\n\n\tconst delayedQuery = useCallback(debounce(updateQuery, 200), [inputValue]);\n\n\tuseEffect(() => {\n\t\tdelayedQuery();\n\t\t// Cancel previous debounce calls during useEffect cleanup.\n\t\treturn delayedQuery.cancel;\n\t}, [inputValue, delayedQuery]);\n\n\tconst handleSelect = (suggestion: string) => {\n\t\tlet updatedArtists: Artists = [];\n\n\t\tlet suggestedArtists: Artists = data.queryArtists\n\t\t\t.slice(0, 5)\n\t\t\t// Map to make a copy of the array, maybe uneeded\n\t\t\t.map((artist: Artist) => artist);\n\n\t\t// Find the selected artist and move it to index 0\n\t\tfor (let i = 0; i < suggestedArtists!.length; i++) {\n\t\t\tif (suggestedArtists![i].name === suggestion) {\n\t\t\t\tlet selectedArtist: Artists = suggestedArtists?.splice(i, 1);\n\t\t\t\tlet otherArtists: Artists = suggestedArtists;\n\t\t\t\tupdatedArtists = [...selectedArtist, ...otherArtists];\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tsetArtists(updatedArtists);\n\t\tsetSelected(true);\n\t};\n\n\tconst handleClick = (name: string) => {\n\t\tlet updatedArtists: Artists = [];\n\n\t\tfor (let i = 0; i < artists.length; i++) {\n\t\t\tif (artists[i].name === name) {\n\t\t\t\tlet selectedArtist: Artists = artists.splice(i, 1);\n\t\t\t\tlet otherArtists: Artists = artists;\n\t\t\t\tupdatedArtists = [...selectedArtist, ...otherArtists];\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tsetArtists(updatedArtists);\n\t};\n\n\tuseEffect(() => {\n\t\tif (data && data.queryArtists && data.queryArtists !== []) {\n\t\t\t// Limit artists to 5\n\t\t\tconst updatedArtists = data.queryArtists.slice(0, 5);\n\t\t\tconst updatedSuggestions: string[] = updatedArtists.map(\n\t\t\t\t(el: Artist) => {\n\t\t\t\t\treturn el.name;\n\t\t\t\t},\n\t\t\t);\n\t\t\tsetSuggestions(updatedSuggestions);\n\t\t}\n\t}, [data]);\n\n\t// Create flag to filter \"No search query\" errors\n\tlet errorNoSearchQuery = false;\n\tif (error && error.graphQLErrors) {\n\t\terror.graphQLErrors.forEach((error) => {\n\t\t\tif (error.message === 'Error: 400: No search query') {\n\t\t\t\terrorNoSearchQuery = true;\n\t\t\t} else {\n\t\t\t\terrorNoSearchQuery = false;\n\t\t\t}\n\t\t});\n\t}\n\n\treturn (\n\t\t\n\t\t\t
\n\t\t\t\n\t\t\t{selected && (\n\t\t\t\t\n\t\t\t)}\n\t\t\t{error && !errorNoSearchQuery && (\n\t\t\t\t
\n\t\t\t\t\t{error.graphQLErrors.map(({ message }, i) => (\n\t\t\t\t\t\t{message}\n\t\t\t\t\t))}\n\t\t\t\t
\n\t\t\t)}\n\t\t\n\t);\n}\n\nconst theme = {\n\tglobal: {\n\t\tcolors: {\n\t\t\tbrand: 'rgb(24, 177, 147)',\n\t\t},\n\t\tfont: {\n\t\t\tfamily: 'Roboto',\n\t\t\tsize: '18px',\n\t\t\theight: '20px',\n\t\t},\n\t},\n};\n","import React from 'react';\nimport ReactDOM from 'react-dom';\nimport { ApolloClient, InMemoryCache, ApolloProvider } from '@apollo/client';\n\nimport App from './components/App';\n\nconst client = new ApolloClient({\n\turi: 'https://spotify-graphql-server.herokuapp.com/graphql',\n\tcache: new InMemoryCache(),\n});\n\nReactDOM.render(\n\t\n\t\t\n\t\t\t\n\t\t\n\t,\n\tdocument.getElementById('root'),\n);\n","module.exports = __webpack_public_path__ + \"static/media/placeholder-music.97fa2780.jpg\";"],"sourceRoot":""} \ No newline at end of file