diff --git a/client/src/api.ts b/client/src/api.ts
index 3ec1933..f119434 100644
--- a/client/src/api.ts
+++ b/client/src/api.ts
@@ -7,23 +7,38 @@
// a request structure, a response structure and
// a checking function which determines request validity.
+export enum ItemType {
+ Song = 0,
+ Artist,
+ Album,
+ Tag
+}
+
export interface ArtistDetails {
- id: Number,
+ artistId: Number,
name: String,
storeLinks?: String[],
}
export interface TagDetails {
- id: Number,
+ tagId: Number,
name: String,
parent?: TagDetails,
storeLinks?: String[],
}
+export interface RankingDetails {
+ rankingId: Number,
+ type: ItemType, // The item type being ranked
+ rankedId: Number, // The item being ranked
+ context: ArtistDetails | TagDetails,
+ value: Number, // The ranking (higher = better)
+}
export interface SongDetails {
- id: Number,
+ songId: Number,
title: String,
artists?: ArtistDetails[],
tags?: TagDetails[],
storeLinks?: String[],
+ rankings?: RankingDetails[],
}
// Query for items (POST).
diff --git a/client/src/components/ItemList.tsx b/client/src/components/ItemList.tsx
index 422224d..2a1ec18 100644
--- a/client/src/components/ItemList.tsx
+++ b/client/src/components/ItemList.tsx
@@ -17,7 +17,9 @@ export default function ItemList(props:any) {
return (
- {props.children}
+ {props.children.map((child: any) => {
+ return child;
+ })}
);
diff --git a/server/app.ts b/server/app.ts
index 101981f..3eb1619 100644
--- a/server/app.ts
+++ b/server/app.ts
@@ -4,7 +4,6 @@ import * as api from '../client/src/api';
import { CreateSongEndpointHandler } from './endpoints/CreateSongEndpointHandler';
import { CreateArtistEndpointHandler } from './endpoints/CreateArtistEndpointHandler';
import { QueryEndpointHandler } from './endpoints/QueryEndpointHandler';
-import { QueryArtistsEndpointHandler } from './endpoints/QueryArtistsEndpointHandler';
import { ArtistDetailsEndpointHandler } from './endpoints/ArtistDetailsEndpointHandler'
import { SongDetailsEndpointHandler } from './endpoints/SongDetailsEndpointHandler';
import { ModifyArtistEndpointHandler } from './endpoints/ModifyArtistEndpointHandler';
diff --git a/server/endpoints/QueryArtistsEndpointHandler.ts b/server/endpoints/QueryArtistsEndpointHandler.ts
deleted file mode 100644
index d521935..0000000
--- a/server/endpoints/QueryArtistsEndpointHandler.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-const models = require('../models');
-import * as api from '../../client/src/api';
-import { EndpointError, EndpointHandler, catchUnhandledErrors } from './types';
-
-export const QueryArtistsEndpointHandler: EndpointHandler = async (req: any, res: any) => {
- if (!api.checkQueryArtistsRequest(req.body)) {
- const e: EndpointError = {
- internalMessage: 'Invalid QueryArtists request: ' + JSON.stringify(req.body),
- httpStatus: 400
- };
- throw e;
- }
- const reqObject: api.QueryArtistsRequest = req.body;
-
- await models.Artist.findAll({
- offset: reqObject.offset,
- limit: reqObject.limit,
- })
- .then((artists: any[]) => {
- const response: api.QueryArtistsResponse = {
- ids: artists.map((artist: any) => {
- return artist.id
- })
- }
- res.send(response);
- })
- .catch(catchUnhandledErrors);
-}
\ No newline at end of file
diff --git a/server/endpoints/QueryEndpointHandler.ts b/server/endpoints/QueryEndpointHandler.ts
index f293845..b7a2f33 100644
--- a/server/endpoints/QueryEndpointHandler.ts
+++ b/server/endpoints/QueryEndpointHandler.ts
@@ -81,7 +81,7 @@ export const QueryEndpointHandler: EndpointHandler = async (req: any, res: any)
// NOTE: have to disable limit and offset because of bug: https://github.com/sequelize/sequelize/issues/11938.
// Custom pagination is implemented before responding.
where: getSequelizeWhere(reqObject.query, QueryType.Song),
- include: [models.Artist, models.Album, models.Tag],
+ include: [models.Artist, models.Album, models.Tag, models.Ranking],
//limit: reqObject.limit,
//offset: reqObject.offset,
})
@@ -104,36 +104,49 @@ export const QueryEndpointHandler: EndpointHandler = async (req: any, res: any)
const response: api.QueryResponse = {
songs: (reqObject.songLimit <= 0) ? [] : await Promise.all(songs.map(async (song: any) => {
- const artists = await song.getArtists();
- const tags = await song.getTags();
+ const artists = song.getArtists();
+ const tags = song.getTags();
+ const rankings = song.getRankings();
return {
- id: song.id,
+ songId: song.id,
title: song.title,
storeLinks: song.storeLinks,
- artists: artists.map((artist: any) => {
+ artists: (await artists).map((artist: any) => {
return {
- id: artist.id,
+ artistId: artist.id,
name: artist.name,
}
}),
- tags: tags.map((tag: any) => {
+ tags: (await tags).map((tag: any) => {
return {
- id: tag.id,
+ tagId: tag.id,
name: tag.name,
}
}),
+ rankings: await (await rankings).map(async (ranking: any) => {
+ const maybeTagContext: api.TagDetails | undefined = await ranking.getTagContext();
+ const maybeArtistContext: api.ArtistDetails | undefined = await ranking.getArtistContext();
+ const maybeContext = maybeTagContext || maybeArtistContext;
+ return {
+ rankingId: ranking.id,
+ type: api.ItemType.Song,
+ rankedId: song.id,
+ context: maybeContext,
+ value: ranking.value,
+ }
+ })
};
}).slice(reqObject.songOffset, reqObject.songOffset + reqObject.songLimit)),
// TODO: custom pagination due to bug mentioned above
artists: (reqObject.artistLimit <= 0) ? [] : await Promise.all(artists.map(async (artist: any) => {
return {
- id: artist.id,
+ artistId: artist.id,
name: artist.name,
};
}).slice(reqObject.artistOffset, reqObject.artistOffset + reqObject.artistLimit)),
tags: (reqObject.tagLimit <= 0) ? [] : await Promise.all(tags.map(async (tag: any) => {
return {
- id: tag.id,
+ tagId: tag.id,
name: tag.name,
};
}).slice(reqObject.tagOffset, reqObject.tagOffset + reqObject.tagLimit)),
diff --git a/server/models/ranking.js b/server/models/ranking.js
new file mode 100644
index 0000000..d15a74e
--- /dev/null
+++ b/server/models/ranking.js
@@ -0,0 +1,13 @@
+module.exports = (sequelize, DataTypes) => {
+ var Ranking = sequelize.define('Ranking', {
+ rank: DataTypes.DOUBLE
+ });
+
+ Ranking.associate = function (models) {
+ models.Ranking.hasOne(models.Tag, { as: 'tagContext' });
+ models.Ranking.hasOne(models.Artist, { as: 'artistContext' });
+ models.Ranking.belongsToMany(models.Song, { through: 'SongRankings' });
+ };
+
+ return Ranking;
+};
\ No newline at end of file
diff --git a/server/models/song.js b/server/models/song.js
index f21785d..0f0e965 100644
--- a/server/models/song.js
+++ b/server/models/song.js
@@ -8,6 +8,7 @@ module.exports = (sequelize, DataTypes) => {
models.Song.belongsToMany(models.Artist, { through: "SongArtists" });
models.Song.belongsToMany(models.Album, { through: "SongAlbums" });
models.Song.belongsToMany(models.Tag, { through: 'SongTags' });
+ models.Song.belongsToMany(models.Ranking, { through: 'SongRankings'});
};
return Song;