diff --git a/htdocs/admin.html b/htdocs/admin.html index 9fb2a59e..fb22e896 100644 --- a/htdocs/admin.html +++ b/htdocs/admin.html @@ -10,10 +10,10 @@ - - + + - + @@ -25,7 +25,7 @@ --> @@ -281,9 +281,9 @@ - - - + + + diff --git a/htdocs/admin/js/forked-daapd.js b/htdocs/admin/js/forked-daapd.js index de51bb76..70b2a695 100644 --- a/htdocs/admin/js/forked-daapd.js +++ b/htdocs/admin/js/forked-daapd.js @@ -35,43 +35,43 @@ var app = new Vue({ methods: { loadConfig: function() { - axios.get('/api/config').then(response => { + axios.get('./api/config').then(response => { this.config = response.data; this.connect()}); }, loadLibrary: function() { - axios.get('/api/library').then(response => this.library = response.data); + axios.get('./api/library').then(response => this.library = response.data); }, loadOutputs: function() { - axios.get('/api/outputs').then(response => this.outputs = response.data.outputs); + axios.get('./api/outputs').then(response => this.outputs = response.data.outputs); }, loadSpotify: function() { - axios.get('/api/spotify').then(response => this.spotify = response.data); + axios.get('./api/spotify').then(response => this.spotify = response.data); }, loadPairing: function() { - axios.get('/api/pairing').then(response => this.pairing = response.data); + axios.get('./api/pairing').then(response => this.pairing = response.data); }, loadLastfm: function() { - axios.get('/api/lastfm').then(response => this.lastfm = response.data); + axios.get('./api/lastfm').then(response => this.lastfm = response.data); }, update: function() { this.library.updating = true; - axios.put('/api/update').then(console.log('Library is updating')); + axios.put('./api/update').then(console.log('Library is updating')); }, update_meta: function() { this.library.updating = true; - axios.put('/api/rescan').then(console.log('Library is rescanning meta')); + axios.put('./api/rescan').then(console.log('Library is rescanning meta')); }, kickoffPairing: function() { - axios.post('/api/pairing', this.pairing_req).then(response => { + axios.post('./api/pairing', this.pairing_req).then(response => { console.log('Kicked off pairing'); if (!this.config.websocket_port) { this.pairing = {}; @@ -80,7 +80,7 @@ var app = new Vue({ }, kickoffVerification: function() { - axios.post('/api/verification', this.verification_req).then(response => { + axios.post('./api/verification', this.verification_req).then(response => { console.log('Kicked off verification'); this.verification_req.pin = ''; }); @@ -94,7 +94,7 @@ var app = new Vue({ } } - axios.put('/api/outputs/set', { outputs: selected_outputs }).then(response => { + axios.put('./api/outputs/set', { outputs: selected_outputs }).then(response => { if (!this.config.websocket_port) { this.loadOutputs(); } @@ -102,7 +102,7 @@ var app = new Vue({ }, loginLibspotify: function() { - axios.post('/api/spotify-login', this.libspotify).then(response => { + axios.post('./api/spotify-login', this.libspotify).then(response => { this.libspotify.user = ''; this.libspotify.password = ''; this.libspotify.errors.user = ''; @@ -117,7 +117,7 @@ var app = new Vue({ }, loginLastfm: function() { - axios.post('/api/lastfm-login', this.lastfm_login).then(response => { + axios.post('./api/lastfm-login', this.lastfm_login).then(response => { this.lastfm_login.user = ''; this.lastfm_login.password = ''; this.lastfm_login.errors.user = ''; @@ -132,7 +132,7 @@ var app = new Vue({ }, logoutLastfm: function() { - axios.get('/api/lastfm-logout', this.lastfm_login).then(response => { + axios.get('./api/lastfm-logout', this.lastfm_login).then(response => { if (!this.config.websocket_port) { this.loadLastfm(); } diff --git a/htdocs/index.html b/htdocs/index.html index bd88fc1d..98b8b1cd 100644 --- a/htdocs/index.html +++ b/htdocs/index.html @@ -1 +1 @@ -forked-daapd-web 2
\ No newline at end of file +forked-daapd-web 2
\ No newline at end of file diff --git a/src/httpd_jsonapi.c b/src/httpd_jsonapi.c index f78dc49f..d3eea58c 100644 --- a/src/httpd_jsonapi.c +++ b/src/httpd_jsonapi.c @@ -213,7 +213,7 @@ artist_to_json(struct db_group_info *dbgri) if (ret < sizeof(uri)) json_object_object_add(item, "uri", json_object_new_string(uri)); - ret = snprintf(artwork_url, sizeof(artwork_url), "/artwork/group/%s", dbgri->id); + ret = snprintf(artwork_url, sizeof(artwork_url), "./artwork/group/%s", dbgri->id); if (ret < sizeof(artwork_url)) json_object_object_add(item, "artwork_url", json_object_new_string(artwork_url)); @@ -261,7 +261,7 @@ album_to_json(struct db_group_info *dbgri) if (ret < sizeof(uri)) json_object_object_add(item, "uri", json_object_new_string(uri)); - ret = snprintf(artwork_url, sizeof(artwork_url), "/artwork/group/%s", dbgri->id); + ret = snprintf(artwork_url, sizeof(artwork_url), "./artwork/group/%s", dbgri->id); if (ret < sizeof(artwork_url)) json_object_object_add(item, "artwork_url", json_object_new_string(artwork_url)); @@ -2099,7 +2099,7 @@ jsonapi_reply_player(struct httpd_request *hreq) json_object_object_add(reply, "item_id", json_object_new_int(status.item_id)); json_object_object_add(reply, "item_length_ms", json_object_new_int(status.len_ms)); json_object_object_add(reply, "item_progress_ms", json_object_new_int(status.pos_ms)); - json_object_object_add(reply, "artwork_url", json_object_new_string("/artwork/nowplaying")); + json_object_object_add(reply, "artwork_url", json_object_new_string("./artwork/nowplaying")); } else { @@ -2194,7 +2194,7 @@ queue_item_to_json(struct db_queue_item *queue_item, char shuffle) { // Queue item does not have a valid artwork url, construct artwork url to // get the image through the httpd_artworkapi (uses the artwork handlers). - ret = snprintf(artwork_url, sizeof(artwork_url), "/artwork/item/%d", queue_item->file_id); + ret = snprintf(artwork_url, sizeof(artwork_url), "./artwork/item/%d", queue_item->file_id); if (ret < sizeof(artwork_url)) json_object_object_add(item, "artwork_url", json_object_new_string(artwork_url)); } @@ -2203,7 +2203,7 @@ queue_item_to_json(struct db_queue_item *queue_item, char shuffle) // Pipe and stream metadata can change if the queue version changes. Construct artwork url // similar to non-pipe items, but append the queue version to the url to force // clients to reload image if the queue version changes (additional metadata was found). - ret = snprintf(artwork_url, sizeof(artwork_url), "/artwork/item/%d?v=%d", queue_item->file_id, queue_item->queue_version); + ret = snprintf(artwork_url, sizeof(artwork_url), "./artwork/item/%d?v=%d", queue_item->file_id, queue_item->queue_version); if (ret < sizeof(artwork_url)) json_object_object_add(item, "artwork_url", json_object_new_string(artwork_url)); } diff --git a/web-src/public/index.html b/web-src/public/index.html index fca734a3..a79a1dad 100644 --- a/web-src/public/index.html +++ b/web-src/public/index.html @@ -4,11 +4,11 @@ forked-daapd-web 2 - - - - - + + + + + diff --git a/web-src/src/components/NavbarBottom.vue b/web-src/src/components/NavbarBottom.vue index d59e81ab..3b88174f 100644 --- a/web-src/src/components/NavbarBottom.vue +++ b/web-src/src/components/NavbarBottom.vue @@ -81,7 +81,7 @@
-

HTTP stream (stream.mp3)

+

HTTP stream (stream.mp3)

-

HTTP stream (stream.mp3)

+

HTTP stream (stream.mp3)

{ + return axios.post('./api/queue/items/add', undefined, { params: options }).then((response) => { store.dispatch('add_notification', { text: response.data.count + ' tracks appended to queue', type: 'info', timeout: 2000 }) return Promise.resolve(response) }) @@ -91,21 +91,21 @@ export default { options.position = store.getters.now_playing.position + 1 } - return axios.post('/api/queue/items/add', undefined, { params: options }).then((response) => { + return axios.post('./api/queue/items/add', undefined, { params: options }).then((response) => { store.dispatch('add_notification', { text: response.data.count + ' tracks appended to queue', type: 'info', timeout: 2000 }) return Promise.resolve(response) }) }, queue_save_playlist (name) { - return axios.post('/api/queue/save', undefined, { params: { name: name } }).then((response) => { + return axios.post('./api/queue/save', undefined, { params: { name: name } }).then((response) => { store.dispatch('add_notification', { text: 'Queue saved to playlist "' + name + '"', type: 'info', timeout: 2000 }) return Promise.resolve(response) }) }, player_status () { - return axios.get('/api/player') + return axios.get('./api/player') }, player_play_uri (uris, shuffle, position = undefined) { @@ -116,7 +116,7 @@ export default { options.playback = 'start' options.playback_from_position = position - return axios.post('/api/queue/items/add', undefined, { params: options }) + return axios.post('./api/queue/items/add', undefined, { params: options }) }, player_play_expression (expression, shuffle, position = undefined) { @@ -127,111 +127,111 @@ export default { options.playback = 'start' options.playback_from_position = position - return axios.post('/api/queue/items/add', undefined, { params: options }) + return axios.post('./api/queue/items/add', undefined, { params: options }) }, player_play (options = {}) { - return axios.put('/api/player/play', undefined, { params: options }) + return axios.put('./api/player/play', undefined, { params: options }) }, player_playpos (position) { - return axios.put('/api/player/play?position=' + position) + return axios.put('./api/player/play?position=' + position) }, player_playid (itemId) { - return axios.put('/api/player/play?item_id=' + itemId) + return axios.put('./api/player/play?item_id=' + itemId) }, player_pause () { - return axios.put('/api/player/pause') + return axios.put('./api/player/pause') }, player_stop () { - return axios.put('/api/player/stop') + return axios.put('./api/player/stop') }, player_next () { - return axios.put('/api/player/next') + return axios.put('./api/player/next') }, player_previous () { - return axios.put('/api/player/previous') + return axios.put('./api/player/previous') }, player_shuffle (newState) { var shuffle = newState ? 'true' : 'false' - return axios.put('/api/player/shuffle?state=' + shuffle) + return axios.put('./api/player/shuffle?state=' + shuffle) }, player_consume (newState) { var consume = newState ? 'true' : 'false' - return axios.put('/api/player/consume?state=' + consume) + return axios.put('./api/player/consume?state=' + consume) }, player_repeat (newRepeatMode) { - return axios.put('/api/player/repeat?state=' + newRepeatMode) + return axios.put('./api/player/repeat?state=' + newRepeatMode) }, player_volume (volume) { - return axios.put('/api/player/volume?volume=' + volume) + return axios.put('./api/player/volume?volume=' + volume) }, player_output_volume (outputId, outputVolume) { - return axios.put('/api/player/volume?volume=' + outputVolume + '&output_id=' + outputId) + return axios.put('./api/player/volume?volume=' + outputVolume + '&output_id=' + outputId) }, player_seek_to_pos (newPosition) { - return axios.put('/api/player/seek?position_ms=' + newPosition) + return axios.put('./api/player/seek?position_ms=' + newPosition) }, player_seek (seekMs) { - return axios.put('/api/player/seek?seek_ms=' + seekMs) + return axios.put('./api/player/seek?seek_ms=' + seekMs) }, outputs () { - return axios.get('/api/outputs') + return axios.get('./api/outputs') }, output_update (outputId, output) { - return axios.put('/api/outputs/' + outputId, output) + return axios.put('./api/outputs/' + outputId, output) }, output_toggle (outputId) { - return axios.put('/api/outputs/' + outputId + '/toggle') + return axios.put('./api/outputs/' + outputId + '/toggle') }, library_artists (media_kind = undefined) { - return axios.get('/api/library/artists', { params: { media_kind: media_kind } }) + return axios.get('./api/library/artists', { params: { media_kind: media_kind } }) }, library_artist (artistId) { - return axios.get('/api/library/artists/' + artistId) + return axios.get('./api/library/artists/' + artistId) }, library_artist_albums (artistId) { - return axios.get('/api/library/artists/' + artistId + '/albums') + return axios.get('./api/library/artists/' + artistId + '/albums') }, library_albums (media_kind = undefined) { - return axios.get('/api/library/albums', { params: { media_kind: media_kind } }) + return axios.get('./api/library/albums', { params: { media_kind: media_kind } }) }, library_album (albumId) { - return axios.get('/api/library/albums/' + albumId) + return axios.get('./api/library/albums/' + albumId) }, library_album_tracks (albumId, filter = { limit: -1, offset: 0 }) { - return axios.get('/api/library/albums/' + albumId + '/tracks', { + return axios.get('./api/library/albums/' + albumId + '/tracks', { params: filter }) }, library_album_track_update (albumId, attributes) { - return axios.put('/api/library/albums/' + albumId + '/tracks', undefined, { params: attributes }) + return axios.put('./api/library/albums/' + albumId + '/tracks', undefined, { params: attributes }) }, library_genres () { - return axios.get('/api/library/genres') + return axios.get('./api/library/genres') }, library_genre (genre) { @@ -240,7 +240,7 @@ export default { media_kind: 'music', expression: 'genre is "' + genre + '"' } - return axios.get('/api/search', { + return axios.get('./api/search', { params: genreParams }) }, @@ -251,7 +251,7 @@ export default { media_kind: 'music', expression: 'genre is "' + genre + '"' } - return axios.get('/api/search', { + return axios.get('./api/search', { params: genreParams }) }, @@ -262,7 +262,7 @@ export default { media_kind: 'music', expression: 'data_kind is url and song_length = 0' } - return axios.get('/api/search', { + return axios.get('./api/search', { params: params }) }, @@ -273,7 +273,7 @@ export default { type: 'tracks', expression: 'songartistid is "' + artist + '"' } - return axios.get('/api/search', { + return axios.get('./api/search', { params: artistParams }) } @@ -284,7 +284,7 @@ export default { type: 'tracks', expression: 'media_kind is podcast and play_count = 0 ORDER BY time_added DESC' } - return axios.get('/api/search', { + return axios.get('./api/search', { params: episodesParams }) }, @@ -294,86 +294,86 @@ export default { type: 'tracks', expression: 'media_kind is podcast and songalbumid is "' + albumId + '" ORDER BY date_released DESC' } - return axios.get('/api/search', { + return axios.get('./api/search', { params: episodesParams }) }, library_add (url) { - return axios.post('/api/library/add', undefined, { params: { url: url } }) + return axios.post('./api/library/add', undefined, { params: { url: url } }) }, library_playlist_delete (playlistId) { - return axios.delete('/api/library/playlists/' + playlistId, undefined) + return axios.delete('./api/library/playlists/' + playlistId, undefined) }, library_playlists () { - return axios.get('/api/library/playlists') + return axios.get('./api/library/playlists') }, library_playlist_folder (playlistId = 0) { - return axios.get('/api/library/playlists/' + playlistId + '/playlists') + return axios.get('./api/library/playlists/' + playlistId + '/playlists') }, library_playlist (playlistId) { - return axios.get('/api/library/playlists/' + playlistId) + return axios.get('./api/library/playlists/' + playlistId) }, library_playlist_tracks (playlistId) { - return axios.get('/api/library/playlists/' + playlistId + '/tracks') + return axios.get('./api/library/playlists/' + playlistId + '/tracks') }, library_track (trackId) { - return axios.get('/api/library/tracks/' + trackId) + return axios.get('./api/library/tracks/' + trackId) }, library_track_playlists (trackId) { - return axios.get('/api/library/tracks/' + trackId + '/playlists') + return axios.get('./api/library/tracks/' + trackId + '/playlists') }, library_track_update (trackId, attributes = {}) { - return axios.put('/api/library/tracks/' + trackId, undefined, { params: attributes }) + return axios.put('./api/library/tracks/' + trackId, undefined, { params: attributes }) }, library_files (directory = undefined) { var filesParams = { directory: directory } - return axios.get('/api/library/files', { + return axios.get('./api/library/files', { params: filesParams }) }, search (searchParams) { - return axios.get('/api/search', { + return axios.get('./api/search', { params: searchParams }) }, spotify () { - return axios.get('/api/spotify') + return axios.get('./api/spotify') }, spotify_login (credentials) { - return axios.post('/api/spotify-login', credentials) + return axios.post('./api/spotify-login', credentials) }, lastfm () { - return axios.get('/api/lastfm') + return axios.get('./api/lastfm') }, lastfm_login (credentials) { - return axios.post('/api/lastfm-login', credentials) + return axios.post('./api/lastfm-login', credentials) }, lastfm_logout (credentials) { - return axios.get('/api/lastfm-logout') + return axios.get('./api/lastfm-logout') }, pairing () { - return axios.get('/api/pairing') + return axios.get('./api/pairing') }, pairing_kickoff (pairingReq) { - return axios.post('/api/pairing', pairingReq) + return axios.post('./api/pairing', pairingReq) }, artwork_url_append_size_params (artworkUrl, maxwidth = 600, maxheight = 600) { diff --git a/web-src/vue.config.js b/web-src/vue.config.js index 72a8964d..76d82b11 100644 --- a/web-src/vue.config.js +++ b/web-src/vue.config.js @@ -10,6 +10,9 @@ module.exports = { assetsDir: 'player', + // Relative public path + publicPath: './', + // Do not add hashes to the generated js/css filenames, would otherwise // require to adjust the Makefile in htdocs each time the web interface is // build