Skip to content
This repository was archived by the owner on Oct 23, 2018. It is now read-only.

Commit d6e4628

Browse files
authoredOct 21, 2018
Add media data to entries (#43)
* Add real media data to lists * Remove media from test data * Use new media types * Tweak entry editor image style * Add media data to entries endpoints * Rename show to tv in db
1 parent d4167fd commit d6e4628

File tree

18 files changed

+271
-227
lines changed

18 files changed

+271
-227
lines changed
 

‎database/scripts/create.sql

+4-10
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ CREATE TABLE users
88
image text
99
);
1010

11-
CREATE TYPE media_type AS ENUM ('game', 'anime', 'show', 'movie');
11+
CREATE TYPE media_type AS ENUM ('game', 'anime', 'tv', 'movie');
1212

1313
CREATE TABLE list
1414
(
@@ -18,21 +18,15 @@ CREATE TABLE list
1818
name text not null
1919
);
2020

21-
CREATE TABLE media
22-
(
23-
id serial primary key not null,
24-
api_id text not null
25-
);
26-
2721
CREATE TABLE entry
2822
(
2923
id serial primary key not null,
30-
media_id int not null REFERENCES media,
24+
media_id int not null,
3125
list_id int not null REFERENCES list ON DELETE CASCADE,
3226
category text,
33-
tags text[] DEFAULT '{}',
27+
tags text[] not null DEFAULT '{}',
3428
rating int,
35-
last_updated TIMESTAMP,
29+
last_updated TIMESTAMP DEFAULT now(),
3630
-- started/finished use ISO 8601 with partial dates allowed
3731
-- e.g. '2016', '2017-04-13', '2018-09'
3832
started text,

‎database/scripts/testData.sql

+4-10
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,14 @@ VALUES
99
('user3', '$2a$10$xYR4Kdp9/eCHpW8p15Jov.u7RHXVLKxQER4VrPirtYkPTR2aOh6rq', 'user3@gmail.com'),
1010
('user4', '$2a$10$xYR4Kdp9/eCHpW8p15Jov.u7RHXVLKxQER4VrPirtYkPTR2aOh6rq', 'user4@gmail.com');
1111

12-
-- Media
13-
INSERT INTO media(api_id)
14-
VALUES
15-
('12345'),
16-
('67890');
17-
1812
INSERT INTO list(name, user_id, media_type)
1913
VALUES
2014
('mezzode''s List', 1, 'game');
2115

2216
-- Entry
2317
INSERT INTO entry(media_id, category, started, finished, list_id, last_updated, tags)
2418
VALUES
25-
(1, 'Progress', '2016', '2018', 1, now(), '{"Favourites", "Friends"}'),
26-
(2, 'Complete', '2017-10-01', '2017-10-01', 1, now(), '{"Favourites"}'),
27-
(1, 'Progress', '2017-10-01', '2017-10-01', 1, now(), null),
28-
(2, 'Complete', '2017-10', '2017-10-01', 1, now(), null);
19+
(12579, 'Progress', '2016', '2018', 1, now(), '{"Favourites", "Friends"}'),
20+
(9694, 'Complete', '2017-10-01', '2017-10-01', 1, now(), '{"Favourites"}'),
21+
(12579, 'Progress', '2017-10-01', '2017-10-01', 1, now(), '{}'),
22+
(9694, 'Complete', '2017-10', '2017-10-01', 1, now(), '{}');

‎server/src/helpers/id.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export const bodyCodesToIds: RequestHandler = (req, res, next) => {
2727
next();
2828
};
2929

30-
const defaultFields = ['Entry', 'Media', 'List'];
30+
const defaultFields = ['Entry', 'List'];
3131

3232
/**
3333
* Replaces codes with ids in a given object.

‎server/src/routes/api/mediaapi.ts

+14
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import igdb from 'igdb-api-node';
44
import { DateTime } from 'luxon';
55
import * as fetch from 'node-fetch';
6+
import { MediaType } from '../lists/types';
67
import * as queries from './queries';
78
import { Anime, Game, Movie, SearchResults, Subset, TV } from './types';
89

@@ -265,3 +266,16 @@ export async function animeFetchSearch(
265266
console.log(final);
266267
return final;
267268
}
269+
270+
export const fetchMedia = (id: number, mediaType: MediaType) => {
271+
switch (mediaType) {
272+
case MediaType.Anime:
273+
return animeFetchID(id);
274+
case MediaType.Game:
275+
return gameFetchID(id);
276+
case MediaType.Movie:
277+
return movietvFetchID(id, MovieTvType.Movie);
278+
case MediaType.Show:
279+
return movietvFetchID(id, MovieTvType.TV);
280+
}
281+
};

‎server/src/routes/api/types.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,16 @@ export interface Subset {
66
mediaType: string;
77
}
88

9+
export type Results = Game | Movie | TV | Anime;
10+
911
export interface Game {
1012
id: number;
1113
title: string;
1214
status: string;
1315
description: string;
1416
genres: string[];
1517
cover: string | null;
16-
category: string[];
18+
category: string;
1719
themes: string[];
1820
publishers: string[];
1921
developers: string[];

‎server/src/routes/lists/entries.test.ts

+9-40
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,18 @@ describe('Test entries endpoints', () => {
2525

2626
describe('Test entry create', () => {
2727
test('Can create new entry', async () => {
28-
const entry = {
28+
const entryData = {
2929
category: 'In Progress',
3030
finished: null,
3131
listCode: 'XG', // 1
32-
mediaCode: 'XG', // 1
3332
rating: 10,
3433
started: '2018',
3534
tags: [],
3635
};
36+
const entry = {
37+
...entryData,
38+
mediaId: 1,
39+
};
3740
const res = await request(app)
3841
.post('/entry')
3942
.send(entry)
@@ -42,40 +45,12 @@ describe('Test entries endpoints', () => {
4245

4346
const { body } = res;
4447
expect(body).toBeDefined();
48+
const { media, lastUpdated, ...createdEntry } = body;
4549

4650
const { entryCode } = body;
4751
const [entryId] = hashids.decode(entryCode);
4852
expect(entryId).toBeGreaterThan(0);
49-
expect(body).toEqual({ ...entry, entryCode });
50-
});
51-
52-
test("Can't create entry for non-existent media", async () => {
53-
const errSpy = jest.spyOn(console, 'error');
54-
errSpy.mockImplementation();
55-
56-
const entry = {
57-
category: 'In Progress',
58-
finished: null,
59-
listCode: 'XG', // 1
60-
mediaCode: 'BaDCoDe',
61-
rating: 10,
62-
started: '2018',
63-
tags: [],
64-
};
65-
66-
const res = await request(app)
67-
.post('/entry')
68-
.send(entry)
69-
.set('Accept', 'application/json')
70-
.expect(404);
71-
72-
const error = 'Media not found';
73-
74-
const { body } = res;
75-
expect(body).toEqual({ error });
76-
77-
expect(errSpy).toBeCalledWith(new HandlerError(error, 404));
78-
errSpy.mockRestore();
53+
expect(createdEntry).toEqual({ ...entryData, entryCode });
7954
});
8055

8156
test("Can't create entry for non-existent list", async () => {
@@ -144,18 +119,12 @@ describe('Test entries endpoints', () => {
144119

145120
expect(res.body).toBeDefined();
146121

147-
const { lastUpdated, ...body } = res.body;
148-
expect(body).toEqual({
122+
const { lastUpdated, media, ...entry } = res.body;
123+
expect(entry).toEqual({
149124
category: 'In Progress',
150125
entryCode: 'XG',
151126
finished: '2018',
152127
listCode: 'XG',
153-
media: {
154-
artUrl:
155-
'https://78.media.tumblr.com/4f30940e947b58fb57e2b8499f460acb/tumblr_okccrbpkDY1rb48exo1_1280.jpg',
156-
mediaCode: 'XG',
157-
title: `Title of media ID 1`,
158-
},
159128
rating: 9,
160129
started: '2016',
161130
tags: [],

‎server/src/routes/lists/entries.ts

+90-70
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,19 @@ import {
99
idsToCodes,
1010
paramCodesToIds,
1111
} from '../../helpers/id';
12-
import { UserEntry } from './types';
12+
import { fetchMedia } from '../api/mediaapi';
13+
import { Entry, MediaType, UserEntry } from './types';
1314

1415
export const entryFields = `
15-
id AS "entryId",
16-
last_updated AS "lastUpdated",
17-
category,
18-
tags,
19-
rating,
20-
started,
21-
finished,
22-
media_id AS "mediaId",
23-
list_id AS "listId"
24-
`;
16+
e.id AS "entryId",
17+
e.last_updated AS "lastUpdated",
18+
e.category,
19+
e.tags,
20+
e.rating,
21+
e.started,
22+
e.finished,
23+
e.media_id AS "mediaId",
24+
e.list_id AS "listId"`;
2525

2626
const getEntry = asyncHandler(async (req, res) => {
2727
const { entryId }: { entryId: number } = req.params;
@@ -35,27 +35,23 @@ const getEntry = asyncHandler(async (req, res) => {
3535
started: string;
3636
finished: string;
3737
tags: string;
38+
mediaType: MediaType;
3839
}>(
3940
// TODO: separate the select clause so can reuse (e.g. same as in lists.ts)
40-
`SELECT ${entryFields}
41+
`SELECT ${entryFields}, l.media_type AS "mediaType"
4142
FROM entry e
43+
JOIN list l ON l.id = e.list_id
4244
WHERE e.id = $(entryId)`,
4345
{ entryId },
4446
);
4547
if (!row) {
4648
throw new HandlerError('Entry not found', 404);
4749
}
4850

49-
const { mediaId, ...other } = row;
51+
const { mediaId, mediaType, ...other } = row;
5052
const entry = {
5153
...idsToCodes(other),
52-
media: {
53-
// TODO: get media data
54-
artUrl:
55-
'https://78.media.tumblr.com/4f30940e947b58fb57e2b8499f460acb/tumblr_okccrbpkDY1rb48exo1_1280.jpg',
56-
mediaCode: hashids.encode(mediaId),
57-
title: `Title of media ID ${mediaId}`,
58-
},
54+
media: await fetchMedia(mediaId, mediaType),
5955
};
6056

6157
res.send(entry);
@@ -83,27 +79,35 @@ const newEntry = asyncHandler(async (req, res) => {
8379
...data,
8480
};
8581

86-
// TODO: consider checking for existence of list first so can
87-
// return "List not found" instead of generic error
82+
const insertedEntry = await db.task<Entry>(async t => {
83+
// TODO: consider checking for existence of list first so can
84+
// return "List not found" instead of generic error
8885

89-
// note this returns list_id, etc. in snake case
90-
const { entryId, ...insertedData } = await db.one<
91-
{ entryId: number } & UserEntry
92-
>(
93-
`${pgp.helpers.insert(entry, undefined, 'entry')}
94-
RETURNING $(data:name), id AS "entryId"`,
95-
{ entry, data },
96-
);
97-
const entryCode = hashids.encode(entryId);
98-
const listCode = hashids.encode(listId);
99-
const mediaCode = hashids.encode(mediaId);
100-
101-
const insertedEntry = {
102-
entryCode,
103-
listCode,
104-
mediaCode,
105-
...insertedData,
106-
};
86+
const { mediaType } = await t.one<{ mediaType: MediaType }>(
87+
`SELECT media_type AS "mediaType"
88+
FROM list l
89+
WHERE l.id = $(listId)`,
90+
{ listId },
91+
);
92+
93+
// note this returns list_id, etc. in snake case
94+
const { entryId, ...insertedData } = await t.one<
95+
{ entryId: number; lastUpdated: string } & UserEntry
96+
>(
97+
`${pgp.helpers.insert(entry, undefined, 'entry')}
98+
RETURNING $(data:name), id AS "entryId", last_updated AS "lastUpdated"`,
99+
{ entry, data },
100+
);
101+
const entryCode = hashids.encode(entryId);
102+
const listCode = hashids.encode(listId);
103+
104+
return {
105+
entryCode,
106+
listCode,
107+
...insertedData,
108+
media: await fetchMedia(mediaId, mediaType),
109+
};
110+
});
107111

108112
res.json(insertedEntry);
109113
});
@@ -162,37 +166,53 @@ const updateEntry = asyncHandler(async (req, res) => {
162166
throw new HandlerError('Invalid entry', 400);
163167
}
164168
const { entryId } = req.params;
165-
const { mediaId, ...updatedEntry } = await db.one<{
166-
entryId: number;
167-
mediaId: number;
168-
listId: number;
169-
category: string;
170-
tags: string[];
171-
rating: number;
172-
lastUpdated: string;
173-
started: string;
174-
finished: string;
175-
last_updated: string;
176-
}>(
177-
`${pgp.helpers.update(
178-
{ ...entryUpdate, last_updated: DateTime.local() },
179-
undefined,
180-
'entry',
181-
)}
182-
WHERE id = $(entryId)
183-
RETURNING ${entryFields}`,
184-
{ entryId, entryUpdate },
185-
);
186-
res.json({
187-
...idsToCodes(updatedEntry),
188-
media: {
189-
// TODO: get media data
190-
artUrl:
191-
'https://78.media.tumblr.com/4f30940e947b58fb57e2b8499f460acb/tumblr_okccrbpkDY1rb48exo1_1280.jpg',
192-
mediaCode: hashids.encode(mediaId),
193-
title: `Title of media ID ${mediaId}`,
194-
},
169+
170+
const editedEntry = await db.task<Entry>(async t => {
171+
const { mediaId, ...updatedEntry } = await t.one<{
172+
entryId: number;
173+
mediaId: number;
174+
listId: number;
175+
category: string;
176+
tags: string[];
177+
rating: number;
178+
lastUpdated: string;
179+
started: string;
180+
finished: string;
181+
last_updated: string;
182+
}>(
183+
`${pgp.helpers.update(
184+
{ ...entryUpdate, last_updated: DateTime.local() },
185+
undefined,
186+
'entry',
187+
)}
188+
WHERE id = $(entryId)
189+
RETURNING
190+
id AS "entryId",
191+
last_updated AS "lastUpdated",
192+
category,
193+
tags,
194+
rating,
195+
started,
196+
finished,
197+
media_id AS "mediaId",
198+
list_id AS "listId"`,
199+
{ entryId, entryUpdate },
200+
);
201+
202+
const { mediaType } = await t.one<{ mediaType: MediaType }>(
203+
`SELECT media_type AS "mediaType"
204+
FROM list l
205+
JOIN entry e ON e.id = $(entryId) AND e.list_id = l.id`,
206+
{ entryId },
207+
);
208+
209+
return {
210+
...(idsToCodes(updatedEntry) as Entry),
211+
media: await fetchMedia(mediaId, mediaType),
212+
};
195213
});
214+
215+
res.json(editedEntry);
196216
});
197217

198218
const deleteEntry = asyncHandler(async (req, res) => {

‎server/src/routes/lists/lists.ts

+10-13
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import * as asyncHandler from 'express-async-handler';
33
import { db } from '../../helpers/database';
44
import { HandlerError } from '../../helpers/error';
55
import { hashids } from '../../helpers/id';
6+
import { fetchMedia } from '../api/mediaapi';
67
import { entryFields } from './entries';
78
import { EntryList, MediaType } from './types';
89

@@ -42,19 +43,15 @@ const getList = asyncHandler(async (req, res) => {
4243
{ listId },
4344
);
4445
return {
45-
entries: entries.map(({ entryId, mediaId, ...entry }) => ({
46-
...entry,
47-
entryCode: hashids.encode(entryId),
48-
listCode,
49-
media: {
50-
// TODO: get media data
51-
artUrl:
52-
'https://78.media.tumblr.com/4f30940e947b58fb57e2b8499f460acb/tumblr_okccrbpkDY1rb48exo1_1280.jpg',
53-
mediaCode: hashids.encode(mediaId),
54-
title: `Title of media ID ${mediaId}`,
55-
},
56-
progress: 'Placeholder', // TODO: add progress column to db
57-
})),
46+
entries: await Promise.all(
47+
entries.map(async ({ entryId, mediaId, ...entry }) => ({
48+
...entry,
49+
entryCode: hashids.encode(entryId),
50+
listCode,
51+
media: await fetchMedia(mediaId, listMeta.mediaType),
52+
progress: 'Placeholder', // TODO: add progress column to db
53+
})),
54+
),
5855
listCode,
5956
...listMeta,
6057
};

‎server/src/routes/lists/types.ts

+3-7
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { Results } from '../api/types';
2+
13
// TODO: share common types between web and server
24

35
/**
@@ -20,13 +22,7 @@ interface SystemEntry {
2022
entryCode: string;
2123
listCode: string;
2224
lastUpdated: string;
23-
media: Media;
24-
}
25-
26-
export interface Media {
27-
mediaCode: string;
28-
title: string;
29-
artUrl: string;
25+
media: Results;
3026
}
3127

3228
export type Entry = UserEntry & SystemEntry;

‎server/src/routes/user/lists.ts

+10-13
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import * as asyncHandler from 'express-async-handler';
33
import { db } from '../../helpers/database';
44
import { HandlerError } from '../../helpers/error';
55
import { hashids } from '../../helpers/id';
6+
import { fetchMedia } from '../api/mediaapi';
67
import { entryFields } from '../lists/entries';
78
import { EntryList, MediaType } from '../lists/types'; // TODO: consolidate types
89

@@ -60,19 +61,15 @@ const getLists = asyncHandler(async (req, res) => {
6061
);
6162
const listCode = hashids.encode(id);
6263
return {
63-
entries: entries.map(({ entryId, mediaId, ...entry }) => ({
64-
...entry,
65-
entryCode: hashids.encode(entryId),
66-
listCode,
67-
media: {
68-
// TODO: get media data
69-
artUrl:
70-
'https://78.media.tumblr.com/4f30940e947b58fb57e2b8499f460acb/tumblr_okccrbpkDY1rb48exo1_1280.jpg',
71-
mediaCode: hashids.encode(mediaId),
72-
title: `Title of media ID ${mediaId}`,
73-
},
74-
progress: 'Placeholder', // TODO: add progress column to db
75-
})),
64+
entries: await Promise.all(
65+
entries.map(async ({ entryId, mediaId, ...entry }) => ({
66+
...entry,
67+
entryCode: hashids.encode(entryId),
68+
listCode,
69+
media: await fetchMedia(mediaId, mediaType),
70+
progress: 'Placeholder', // TODO: add progress column to db
71+
})),
72+
),
7673
listCode,
7774
mediaType,
7875
name,

‎server/test/data.ts

+1-6
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ export const users = [
66
{ username: 'jfu', password: 'foobar', email: 'test@test.org' },
77
];
88

9-
export const media = [{ api_id: 12345 }, { api_id: 9175 }];
10-
119
export const lists = [{ name: "mezzode's List", userId: 1, mediaType: 'game' }];
1210

1311
export const entries = [
@@ -47,17 +45,14 @@ export const entries = [
4745

4846
export const seedTestData = () =>
4947
db.task(async t => {
50-
await t.none(
51-
'TRUNCATE TABLE users, media, list, entry RESTART IDENTITY',
52-
);
48+
await t.none('TRUNCATE TABLE users, list, entry RESTART IDENTITY');
5349
await t.none(
5450
pgp.helpers.insert(
5551
users,
5652
['username', 'password', 'email'],
5753
'users',
5854
),
5955
);
60-
await t.none(pgp.helpers.insert(media, ['api_id'], 'media'));
6156
await t.none(
6257
pgp.helpers.insert(
6358
lists,

‎web/src/components/lists/List/Component.tsx

+4-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
import { createStyles, withStyles } from '@material-ui/core/styles';
1414
import * as React from 'react';
1515
import { Link } from 'react-router-dom';
16+
import { mediaUrl } from 'src/types';
1617
import { Props } from './types';
1718

1819
export const styles = (theme: Theme) =>
@@ -81,7 +82,9 @@ const RawList: React.SFC<Props> = ({
8182
<TableCell component="th" scope="row">
8283
<Typography variant="body1">
8384
<Link
84-
to={`/media/${entry.media.mediaCode}`}
85+
to={`/media/${
86+
mediaUrl[list.mediaType]
87+
}/${entry.media.id}`}
8588
className={classes.link}
8689
>
8790
{entry.media.title}

‎web/src/components/lists/List/stories.tsx

+38-14
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,19 @@ const entries: Entry[] = [
1515
lastUpdated: '2018/09/15 19:01',
1616
listCode: 'a',
1717
media: {
18-
artUrl:
19-
'https://78.media.tumblr.com/4f30940e947b58fb57e2b8499f460acb/tumblr_okccrbpkDY1rb48exo1_1280.jpg',
20-
description: '',
21-
mediaCode: 'a',
22-
title: 'Danganronpa',
18+
category: 'Main Game',
19+
cover:
20+
'//images.igdb.com/igdb/image/upload/t_thumb/dckh8rr0f4lo4hbw1uty.jpg',
21+
description:
22+
"The follow up to Danganronpa: Trigger Happy Havoc. Danganronpa 2: Goodbye Despair introduces a new cast of characters. The main character, Hajime Hinata a new 'Ultimate' student at Hope's Peak Academy. On their first day, Hajime and all of his classmates are taken on a field trip to the mysterious Jabberwock island by their anthropomorphic rabbit teacher, Usami. Usami explains that on this island the students are to have fun together and become friends to gather Hope Fragments. Usami's field trip does not go as planned when Monokuma appears and begins a new Killing Game. Anyone that wants to leave the island must commit a murder and get away with it. If the murderer is successful, he/she is allowed to leave the island, while everyone else is killed. When a murder occurs, the player investigates. After the investigations, a trial commences to determine who the culprit is.",
23+
developers: ['Spike ChunSoft'],
24+
first_release_date: '2012-07-26T00:00:00.000+00:00',
25+
genres: ['Shooter', 'Music', 'Adventure'],
26+
id: 9694,
27+
publishers: ['NIS America', 'Spike ChunSoft'],
28+
status: 'Released',
29+
themes: ['Action', 'Horror'],
30+
title: 'Danganronpa 2: Goodbye Despair',
2331
},
2432
progress: '50 hrs',
2533
rating: 10,
@@ -33,10 +41,18 @@ const entries: Entry[] = [
3341
lastUpdated: '2018/09/15 19:01',
3442
listCode: 'a',
3543
media: {
36-
artUrl:
37-
'https://78.media.tumblr.com/4f30940e947b58fb57e2b8499f460acb/tumblr_okccrbpkDY1rb48exo1_1280.jpg',
38-
description: '',
39-
mediaCode: 'b',
44+
category: 'Main Game',
45+
cover:
46+
'//images.igdb.com/igdb/image/upload/t_thumb/dckh8rr0f4lo4hbw1uty.jpg',
47+
description:
48+
"The follow up to Danganronpa: Trigger Happy Havoc. Danganronpa 2: Goodbye Despair introduces a new cast of characters. The main character, Hajime Hinata a new 'Ultimate' student at Hope's Peak Academy. On their first day, Hajime and all of his classmates are taken on a field trip to the mysterious Jabberwock island by their anthropomorphic rabbit teacher, Usami. Usami explains that on this island the students are to have fun together and become friends to gather Hope Fragments. Usami's field trip does not go as planned when Monokuma appears and begins a new Killing Game. Anyone that wants to leave the island must commit a murder and get away with it. If the murderer is successful, he/she is allowed to leave the island, while everyone else is killed. When a murder occurs, the player investigates. After the investigations, a trial commences to determine who the culprit is.",
49+
developers: ['Spike ChunSoft'],
50+
first_release_date: '2012-07-26T00:00:00.000+00:00',
51+
genres: ['Shooter', 'Music', 'Adventure'],
52+
id: 9694,
53+
publishers: ['NIS America', 'Spike ChunSoft'],
54+
status: 'Released',
55+
themes: ['Action', 'Horror'],
4056
title: 'Danganronpa 2: Goodbye Despair',
4157
},
4258
progress: '50 hrs',
@@ -51,11 +67,19 @@ const entries: Entry[] = [
5167
lastUpdated: '2018/09/15 19:01',
5268
listCode: 'a',
5369
media: {
54-
artUrl:
55-
'https://78.media.tumblr.com/4f30940e947b58fb57e2b8499f460acb/tumblr_okccrbpkDY1rb48exo1_1280.jpg',
56-
description: '',
57-
mediaCode: 'c',
58-
title: 'Danganronpa V3: Killing Harmony',
70+
category: 'Main Game',
71+
cover:
72+
'//images.igdb.com/igdb/image/upload/t_thumb/dckh8rr0f4lo4hbw1uty.jpg',
73+
description:
74+
"The follow up to Danganronpa: Trigger Happy Havoc. Danganronpa 2: Goodbye Despair introduces a new cast of characters. The main character, Hajime Hinata a new 'Ultimate' student at Hope's Peak Academy. On their first day, Hajime and all of his classmates are taken on a field trip to the mysterious Jabberwock island by their anthropomorphic rabbit teacher, Usami. Usami explains that on this island the students are to have fun together and become friends to gather Hope Fragments. Usami's field trip does not go as planned when Monokuma appears and begins a new Killing Game. Anyone that wants to leave the island must commit a murder and get away with it. If the murderer is successful, he/she is allowed to leave the island, while everyone else is killed. When a murder occurs, the player investigates. After the investigations, a trial commences to determine who the culprit is.",
75+
developers: ['Spike ChunSoft'],
76+
first_release_date: '2012-07-26T00:00:00.000+00:00',
77+
genres: ['Shooter', 'Music', 'Adventure'],
78+
id: 9694,
79+
publishers: ['NIS America', 'Spike ChunSoft'],
80+
status: 'Released',
81+
themes: ['Action', 'Horror'],
82+
title: 'Danganronpa 2: Goodbye Despair',
5983
},
6084
progress: '50 hrs',
6185
rating: 10,

‎web/src/components/lists/Lists/stories.tsx

+51-19
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,19 @@ const lists: EntryList[] = [
1717
lastUpdated: '2018/09/15 19:01',
1818
listCode: 'a',
1919
media: {
20-
artUrl:
21-
'https://78.media.tumblr.com/4f30940e947b58fb57e2b8499f460acb/tumblr_okccrbpkDY1rb48exo1_1280.jpg',
22-
description: '',
23-
mediaCode: 'a',
24-
title: 'Danganronpa',
20+
category: 'Main Game',
21+
cover:
22+
'//images.igdb.com/igdb/image/upload/t_thumb/dckh8rr0f4lo4hbw1uty.jpg',
23+
description:
24+
"The follow up to Danganronpa: Trigger Happy Havoc. Danganronpa 2: Goodbye Despair introduces a new cast of characters. The main character, Hajime Hinata a new 'Ultimate' student at Hope's Peak Academy. On their first day, Hajime and all of his classmates are taken on a field trip to the mysterious Jabberwock island by their anthropomorphic rabbit teacher, Usami. Usami explains that on this island the students are to have fun together and become friends to gather Hope Fragments. Usami's field trip does not go as planned when Monokuma appears and begins a new Killing Game. Anyone that wants to leave the island must commit a murder and get away with it. If the murderer is successful, he/she is allowed to leave the island, while everyone else is killed. When a murder occurs, the player investigates. After the investigations, a trial commences to determine who the culprit is.",
25+
developers: ['Spike ChunSoft'],
26+
first_release_date: '2012-07-26T00:00:00.000+00:00',
27+
genres: ['Shooter', 'Music', 'Adventure'],
28+
id: 9694,
29+
publishers: ['NIS America', 'Spike ChunSoft'],
30+
status: 'Released',
31+
themes: ['Action', 'Horror'],
32+
title: 'Danganronpa 2: Goodbye Despair',
2533
},
2634
progress: '50 hrs',
2735
rating: 10,
@@ -35,10 +43,18 @@ const lists: EntryList[] = [
3543
lastUpdated: '2018/09/15 19:01',
3644
listCode: 'a',
3745
media: {
38-
artUrl:
39-
'https://78.media.tumblr.com/4f30940e947b58fb57e2b8499f460acb/tumblr_okccrbpkDY1rb48exo1_1280.jpg',
40-
description: '',
41-
mediaCode: 'b',
46+
category: 'Main Game',
47+
cover:
48+
'//images.igdb.com/igdb/image/upload/t_thumb/dckh8rr0f4lo4hbw1uty.jpg',
49+
description:
50+
"The follow up to Danganronpa: Trigger Happy Havoc. Danganronpa 2: Goodbye Despair introduces a new cast of characters. The main character, Hajime Hinata a new 'Ultimate' student at Hope's Peak Academy. On their first day, Hajime and all of his classmates are taken on a field trip to the mysterious Jabberwock island by their anthropomorphic rabbit teacher, Usami. Usami explains that on this island the students are to have fun together and become friends to gather Hope Fragments. Usami's field trip does not go as planned when Monokuma appears and begins a new Killing Game. Anyone that wants to leave the island must commit a murder and get away with it. If the murderer is successful, he/she is allowed to leave the island, while everyone else is killed. When a murder occurs, the player investigates. After the investigations, a trial commences to determine who the culprit is.",
51+
developers: ['Spike ChunSoft'],
52+
first_release_date: '2012-07-26T00:00:00.000+00:00',
53+
genres: ['Shooter', 'Music', 'Adventure'],
54+
id: 9694,
55+
publishers: ['NIS America', 'Spike ChunSoft'],
56+
status: 'Released',
57+
themes: ['Action', 'Horror'],
4258
title: 'Danganronpa 2: Goodbye Despair',
4359
},
4460
progress: '50 hrs',
@@ -53,11 +69,19 @@ const lists: EntryList[] = [
5369
lastUpdated: '2018/09/15 19:01',
5470
listCode: 'a',
5571
media: {
56-
artUrl:
57-
'https://78.media.tumblr.com/4f30940e947b58fb57e2b8499f460acb/tumblr_okccrbpkDY1rb48exo1_1280.jpg',
58-
description: '',
59-
mediaCode: 'c',
60-
title: 'Danganronpa V3: Killing Harmony',
72+
category: 'Main Game',
73+
cover:
74+
'//images.igdb.com/igdb/image/upload/t_thumb/dckh8rr0f4lo4hbw1uty.jpg',
75+
description:
76+
"The follow up to Danganronpa: Trigger Happy Havoc. Danganronpa 2: Goodbye Despair introduces a new cast of characters. The main character, Hajime Hinata a new 'Ultimate' student at Hope's Peak Academy. On their first day, Hajime and all of his classmates are taken on a field trip to the mysterious Jabberwock island by their anthropomorphic rabbit teacher, Usami. Usami explains that on this island the students are to have fun together and become friends to gather Hope Fragments. Usami's field trip does not go as planned when Monokuma appears and begins a new Killing Game. Anyone that wants to leave the island must commit a murder and get away with it. If the murderer is successful, he/she is allowed to leave the island, while everyone else is killed. When a murder occurs, the player investigates. After the investigations, a trial commences to determine who the culprit is.",
77+
developers: ['Spike ChunSoft'],
78+
first_release_date: '2012-07-26T00:00:00.000+00:00',
79+
genres: ['Shooter', 'Music', 'Adventure'],
80+
id: 9694,
81+
publishers: ['NIS America', 'Spike ChunSoft'],
82+
status: 'Released',
83+
themes: ['Action', 'Horror'],
84+
title: 'Danganronpa 2: Goodbye Despair',
6185
},
6286
progress: '50 hrs',
6387
rating: 10,
@@ -79,11 +103,19 @@ const lists: EntryList[] = [
79103
lastUpdated: '2018/09/15 19:01',
80104
listCode: 'b',
81105
media: {
82-
artUrl:
83-
'https://78.media.tumblr.com/4f30940e947b58fb57e2b8499f460acb/tumblr_okccrbpkDY1rb48exo1_1280.jpg',
84-
description: '',
85-
mediaCode: 'asdf',
86-
title: 'Rainbow 6: Siege',
106+
category: 'Main Game',
107+
cover:
108+
'//images.igdb.com/igdb/image/upload/t_thumb/dckh8rr0f4lo4hbw1uty.jpg',
109+
description:
110+
"The follow up to Danganronpa: Trigger Happy Havoc. Danganronpa 2: Goodbye Despair introduces a new cast of characters. The main character, Hajime Hinata a new 'Ultimate' student at Hope's Peak Academy. On their first day, Hajime and all of his classmates are taken on a field trip to the mysterious Jabberwock island by their anthropomorphic rabbit teacher, Usami. Usami explains that on this island the students are to have fun together and become friends to gather Hope Fragments. Usami's field trip does not go as planned when Monokuma appears and begins a new Killing Game. Anyone that wants to leave the island must commit a murder and get away with it. If the murderer is successful, he/she is allowed to leave the island, while everyone else is killed. When a murder occurs, the player investigates. After the investigations, a trial commences to determine who the culprit is.",
111+
developers: ['Spike ChunSoft'],
112+
first_release_date: '2012-07-26T00:00:00.000+00:00',
113+
genres: ['Shooter', 'Music', 'Adventure'],
114+
id: 9694,
115+
publishers: ['NIS America', 'Spike ChunSoft'],
116+
status: 'Released',
117+
themes: ['Action', 'Horror'],
118+
title: 'Danganronpa 2: Goodbye Despair',
87119
},
88120
progress: '50 hrs',
89121
rating: 10,

‎web/src/components/modals/entries/EntryEditor/Component.tsx

+7-2
Original file line numberDiff line numberDiff line change
@@ -170,10 +170,15 @@ const RawEntryEditor: React.SFC<Props> = ({
170170
/>
171171
</Grid>
172172
{isWidthUp('xs', width, false) && (
173-
<Grid item={true} sm={5}>
173+
<Grid
174+
item={true}
175+
sm={5}
176+
container={true}
177+
alignItems="center"
178+
>
174179
<img
175180
className={classes.art}
176-
src={entry.media.artUrl}
181+
src={entry.media.cover}
177182
/>
178183
</Grid>
179184
)}

‎web/src/components/modals/entries/EntryEditor/stories.tsx

+13-5
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,19 @@ storiesOf('EntryEditor', module)
4848
lastUpdated: '2018/09/15 19:01',
4949
listCode: 'a',
5050
media: {
51-
artUrl:
52-
'https://78.media.tumblr.com/4f30940e947b58fb57e2b8499f460acb/tumblr_okccrbpkDY1rb48exo1_1280.jpg',
53-
description: '',
54-
mediaCode: 'asdf',
55-
title: 'Danganronpa V3: Killing Harmony',
51+
category: 'Main Game',
52+
cover:
53+
'//images.igdb.com/igdb/image/upload/t_thumb/dckh8rr0f4lo4hbw1uty.jpg',
54+
description:
55+
"The follow up to Danganronpa: Trigger Happy Havoc. Danganronpa 2: Goodbye Despair introduces a new cast of characters. The main character, Hajime Hinata a new 'Ultimate' student at Hope's Peak Academy. On their first day, Hajime and all of his classmates are taken on a field trip to the mysterious Jabberwock island by their anthropomorphic rabbit teacher, Usami. Usami explains that on this island the students are to have fun together and become friends to gather Hope Fragments. Usami's field trip does not go as planned when Monokuma appears and begins a new Killing Game. Anyone that wants to leave the island must commit a murder and get away with it. If the murderer is successful, he/she is allowed to leave the island, while everyone else is killed. When a murder occurs, the player investigates. After the investigations, a trial commences to determine who the culprit is.",
56+
developers: ['Spike ChunSoft'],
57+
first_release_date: '2012-07-26T00:00:00.000+00:00',
58+
genres: ['Shooter', 'Music', 'Adventure'],
59+
id: 9694,
60+
publishers: ['NIS America', 'Spike ChunSoft'],
61+
status: 'Released',
62+
themes: ['Action', 'Horror'],
63+
title: 'Danganronpa 2: Goodbye Despair',
5664
},
5765
progress: '50 hrs',
5866
rating: 10,

‎web/src/types.ts

+8-13
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,6 @@ interface SystemEntry {
2323

2424
export type Entry = UserEntry & SystemEntry;
2525

26-
export interface Media {
27-
mediaCode: string;
28-
title: string;
29-
description: string;
30-
artUrl: string;
31-
}
32-
3326
export interface EntryList {
3427
entries: Entry[];
3528
listCode: string;
@@ -56,6 +49,7 @@ export const isMediaType = (s: string): s is MediaType =>
5649
.map(k => MediaType[k])
5750
.filter(t => t === s).length === 1;
5851

52+
// TODO: refactor into function for better separation
5953
export const mediaUrl = {
6054
[MediaType.Game]: 'games',
6155
[MediaType.Show]: 'shows',
@@ -74,15 +68,16 @@ export interface ListsMap {
7468
[listCode: string]: EntryList;
7569
}
7670

77-
// From server/api/types.ts - TODO: common types
71+
export type Media = Game | Movie | TV | Anime;
72+
7873
export interface Game {
7974
id: number;
8075
title: string;
8176
status: string;
8277
description: string;
8378
genres: string[];
84-
cover: string | null;
85-
category: string[];
79+
cover: string;
80+
category: string;
8681
themes: string[];
8782
publishers: string[];
8883
developers: string[];
@@ -95,7 +90,7 @@ export interface Movie {
9590
status: string;
9691
description: string;
9792
genres: string[];
98-
cover: string | null;
93+
cover: string;
9994
releaseDate: string;
10095
production_companies: string[];
10196
production_countries: string[];
@@ -109,7 +104,7 @@ export interface TV {
109104
status: string;
110105
description: string;
111106
genres: string[];
112-
cover: string | null;
107+
cover: string;
113108
type: string;
114109
firstAirDate: string;
115110
production_companies: string[];
@@ -125,7 +120,7 @@ export interface Anime {
125120
status: string;
126121
description: string;
127122
genres: string[];
128-
cover: string | null;
123+
cover: string;
129124
format: string;
130125
startDate: string;
131126
endDate: string;

‎web/src/views/SearchResult/Component.tsx

+1-2
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,7 @@ class RawSearchResult extends React.Component<Props, State> {
140140
</Link>
141141
<Typography
142142
dangerouslySetInnerHTML={
143-
searchResult.description !==
144-
null &&
143+
searchResult.description &&
145144
searchResult.description.trim() !==
146145
''
147146
? {

0 commit comments

Comments
 (0)
This repository has been archived.