Skip to content

Commit 334a56c

Browse files
committed
feat: make it possible to navigate to a random comic by item
Closes #20
1 parent 20c90bf commit 334a56c

16 files changed

Lines changed: 237 additions & 44 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1313
- Add Storybook link to README
1414
- Added list of comics an item is featured in. Closes [#19](https://github.com/Questionable-Content-Extensions/client/issues/19)
1515
- Added feature and setting for whether to show the current comic's tagline as its tooltip. Closes [#47](https://github.com/Questionable-Content-Extensions/client/issues/47)
16+
- Added feature and setting for being able to navigate to random comics by item. Closes [#20](https://github.com/Questionable-Content-Extensions/client/issues/20)
1617

1718
### Changed 🔧
1819

src/components/ComicDetailsPanel/ComicDetailsPanel.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,6 @@ function ComicDetailsPanel({
242242
<ErrorPresenter error={comicDataError} />
243243
)}
244244
<ItemNavigation
245-
currentComic={currentComic}
246245
itemNavigationData={comicItems ?? []}
247246
isLoading={isLoadingInitial}
248247
isFetching={isFetching}
@@ -324,7 +323,6 @@ function ComicDetailsPanel({
324323
<>
325324
<hr className="my-4 mx-0 border-solid border-b max-w-none" />
326325
<FilteredNavigationData
327-
currentComic={currentComic}
328326
isLoading={isLoadingInitial}
329327
isFetching={isFetching}
330328
isSaving={isSaving}

src/components/ComicDetailsPanel/ItemNavigation/ItemNavigation.stories.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import { NavElementMode } from '@components/NavElement/NavElement'
2+
import { setCurrentComic } from '@store/comicSlice'
3+
import store from '@store/store'
24
import { Meta, StoryFn } from '@storybook/react'
35

46
import { COMIC_DATA_666_HYDRATED_ITEMS } from '~/mocks'
@@ -28,12 +30,17 @@ const Template: StoryFn<typeof ItemNavigation> = (args) => {
2830
| NavElementMode.Missing
2931
}
3032

33+
const state = store.getState()
34+
35+
if (state.comic.current !== 666) {
36+
store.dispatch(setCurrentComic(666))
37+
}
38+
3139
return <ItemNavigation {...args} />
3240
}
3341

3442
export const Default = Template.bind({})
3543
Default.args = {
36-
currentComic: 666,
3744
itemNavigationData: COMIC_DATA_666_HYDRATED_ITEMS,
3845
useColors: true,
3946
isLoading: false,

src/components/ComicDetailsPanel/ItemNavigation/ItemNavigation.tsx

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,13 @@ import InlineSpinner from '@components/InlineSpinner'
44
import NavElement, { NavElementMode } from '@components/NavElement/NavElement'
55
import Spinner from '@components/Spinner'
66
import useItemNavigationDataByType from '@hooks/useItemNavigationDataByType'
7-
import { ComicId } from '@models/ComicId'
87
import { HydratedItemNavigationData } from '@models/HydratedItemData'
98
import { ItemId } from '@models/ItemId'
109

1110
import { PickEnum } from '~/tsUtils'
1211

1312
export default function ItemNavigation({
1413
itemNavigationData,
15-
currentComic,
1614
isLoading,
1715
isFetching,
1816
useColors,
@@ -24,7 +22,6 @@ export default function ItemNavigation({
2422
onAddItem,
2523
}: {
2624
itemNavigationData: HydratedItemNavigationData[]
27-
currentComic: ComicId
2825
isLoading: boolean
2926
isFetching: boolean
3027
useColors: boolean
@@ -46,7 +43,6 @@ export default function ItemNavigation({
4643
return (
4744
<NavElement
4845
key={item.id}
49-
currentComic={currentComic}
5046
item={item}
5147
onSetCurrentComic={onSetCurrentComic}
5248
useColors={useColors}
@@ -66,7 +62,6 @@ export default function ItemNavigation({
6662
onSetCurrentComic,
6763
onShowInfoFor,
6864
useColors,
69-
currentComic,
7065
]
7166
)
7267

src/components/EditorModePanel/EditorModePanel.tsx

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,6 @@ function EditorModePanel({
268268
<>
269269
<MissingNavElement
270270
navigationData={editorData.missing.cast}
271-
currentComic={currentComic}
272271
title="Missing cast"
273272
description="Navigate to comics without cast members"
274273
onSetCurrentComic={setCurrentComic}
@@ -277,7 +276,6 @@ function EditorModePanel({
277276
/>
278277
<MissingNavElement
279278
navigationData={editorData.missing.location}
280-
currentComic={currentComic}
281279
title="Missing location"
282280
description="Navigate to comics without locations"
283281
onSetCurrentComic={setCurrentComic}
@@ -286,7 +284,6 @@ function EditorModePanel({
286284
/>
287285
<MissingNavElement
288286
navigationData={editorData.missing.storyline}
289-
currentComic={currentComic}
290287
title="Missing storyline"
291288
description="Navigate to comics without storylines"
292289
onSetCurrentComic={setCurrentComic}
@@ -295,7 +292,6 @@ function EditorModePanel({
295292
/>
296293
<MissingNavElement
297294
navigationData={editorData.missing.title}
298-
currentComic={currentComic}
299295
title="Missing title"
300296
description="Navigate to comics without a title"
301297
onSetCurrentComic={setCurrentComic}
@@ -304,7 +300,6 @@ function EditorModePanel({
304300
/>
305301
<MissingNavElement
306302
navigationData={editorData.missing.tagline}
307-
currentComic={currentComic}
308303
title="Missing tagline"
309304
description="Navigate to comics without a tagline"
310305
onSetCurrentComic={setCurrentComic}

src/components/EditorModePanel/MissingNavElement/MissingNavElement.tsx

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,16 @@
11
import NavElement, { NavElementMode } from '@components/NavElement/NavElement'
2-
import { ComicId } from '@models/ComicId'
32
import { NavigationData } from '@models/NavigationData'
43

54
// TODO: Set up stories for `MissingNavElement`
65
export default function MissingNavElement({
76
navigationData,
8-
currentComic,
97
id,
108
title,
119
description,
1210
onSetCurrentComic,
1311
useColors,
1412
}: {
1513
navigationData: NavigationData | null
16-
currentComic: ComicId
1714
id: number
1815
title: string
1916
description: string
@@ -38,7 +35,6 @@ export default function MissingNavElement({
3835
type: 'cast',
3936
count: 0,
4037
}}
41-
currentComic={currentComic}
4238
onSetCurrentComic={onSetCurrentComic}
4339
useColors={useColors}
4440
onShowInfoFor={() => {}}

src/components/FilteredNavigationData/FilteredNavigationData.stories.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { setCurrentComic } from '@store/comicSlice'
2+
import store from '@store/store'
13
import { Meta, StoryFn } from '@storybook/react'
24

35
import { COMIC_DATA_666_HYDRATED_ITEMS } from '~/mocks'
@@ -9,12 +11,17 @@ export default {
911
} as Meta<typeof FilteredNavigationData>
1012

1113
const Template: StoryFn<typeof FilteredNavigationData> = (args) => {
14+
const state = store.getState()
15+
16+
if (state.comic.current !== 666) {
17+
store.dispatch(setCurrentComic(666))
18+
}
19+
1220
return <FilteredNavigationData {...args} />
1321
}
1422

1523
export const Default = Template.bind({})
1624
Default.args = {
17-
currentComic: 666,
1825
editMode: false,
1926
isFetching: false,
2027
isLoading: false,

src/components/FilteredNavigationData/FilteredNavigationData.tsx

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import { ItemId } from '@models/ItemId'
1111
import { ItemType } from '@models/ItemType'
1212

1313
export default function FilteredNavigationData({
14-
currentComic,
1514
isLoading,
1615
isFetching,
1716
isSaving,
@@ -23,7 +22,6 @@ export default function FilteredNavigationData({
2322
editMode,
2423
onAddItem,
2524
}: {
26-
currentComic: ComicId
2725
isLoading: boolean
2826
isFetching: boolean
2927
isSaving: boolean
@@ -73,7 +71,6 @@ export default function FilteredNavigationData({
7371
{(filteredItemData.length > 0 || isLoading) && !hasError ? (
7472
<div className="overflow-y-auto overflow-x-hidden max-h-52">
7573
<ItemNavigation
76-
currentComic={currentComic}
7774
itemNavigationData={filteredItemData}
7875
isLoading={isLoading}
7976
isFetching={isFetching}

src/components/ItemDetailsDialog/ItemDetails/ItemDetails.tsx

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ import ValueEditor from './ValueEditor/ValueEditor'
2424

2525
const mapState = (state: RootState) => {
2626
return {
27-
currentComic: state.comic.current,
2827
name: state.itemEditor.name,
2928
isNameDirty: isNameDirtySelector(state),
3029
shortName: state.itemEditor.shortName,
@@ -63,7 +62,6 @@ type ItemDetailsProps = PropsFromRedux & {
6362
}
6463

6564
export function ItemDetails({
66-
currentComic,
6765
name,
6866
isNameDirty,
6967
shortName,
@@ -228,7 +226,6 @@ export function ItemDetails({
228226
<strong>Navigation bar preview:</strong>
229227
</p>
230228
<NavElement
231-
currentComic={currentComic}
232229
item={{
233230
id: item.id,
234231
shortName: item.shortName,

src/components/NavElement/NavElement.stories.tsx

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1+
import { setCurrentComic } from '@store/comicSlice'
2+
import { setSettings } from '@store/settingsSlice'
3+
import store from '@store/store'
14
import { expect } from '@storybook/jest'
25
import { Meta, StoryFn } from '@storybook/react'
36
import { userEvent, within } from '@storybook/testing-library'
47

5-
import { MARTEN, MARTEN_HYDRATED, MARTEN_ITEM } from '~/mocks'
8+
import { MARTEN, MARTEN_HYDRATED, MARTEN_ITEM, useMswReady } from '~/mocks'
9+
import Settings from '~/settings'
610

711
import NavElement, { NavElementMode } from './NavElement'
812

@@ -18,23 +22,65 @@ export default {
1822
NavElementMode[NavElementMode.Preview],
1923
],
2024
},
25+
onSetCurrentComic: { action: 'onSetCurrentComic' },
26+
onShowInfoFor: { action: 'onShowInfoFor' },
27+
onAddItem: { action: 'onAddItem' },
28+
onRemoveItem: { action: 'onRemoveItem' },
2129
},
2230
} as Meta<typeof NavElement>
2331

24-
const Template: StoryFn<typeof NavElement> = (args) => {
32+
const Template: StoryFn<typeof NavElement> = function (
33+
this: { withRandom?: boolean },
34+
args
35+
) {
36+
const mswReady = useMswReady()
37+
38+
const state = store.getState()
39+
40+
if (state.comic.current !== 666) {
41+
store.dispatch(setCurrentComic(666))
42+
}
43+
if (this.withRandom && !state.settings.values?.showItemRandomButton) {
44+
store.dispatch(
45+
setSettings({
46+
...Settings.DEFAULTS,
47+
showItemRandomButton: true,
48+
})
49+
)
50+
} else if (
51+
!this.withRandom &&
52+
state.settings.values?.showItemRandomButton
53+
) {
54+
store.dispatch(
55+
setSettings({
56+
...Settings.DEFAULTS,
57+
showItemRandomButton: false,
58+
})
59+
)
60+
}
61+
62+
const { worker, rest } = window.msw
63+
worker.use(
64+
rest.get(
65+
'http://localhost:3000/api/v2/itemdata/1/comics/random',
66+
(req, res, ctx) => {
67+
return res(ctx.json(4269))
68+
}
69+
)
70+
)
71+
2572
// For better Storybook experience, we pretend this field is a string
2673
// and then turn it into a number here
2774
const mode = args.mode
2875
if (typeof mode === 'string') {
2976
args.mode = NavElementMode[mode] as unknown as NavElementMode
3077
}
3178

32-
return <NavElement {...args} />
79+
return mswReady ? <NavElement {...args} /> : <></>
3380
}
3481

3582
export const Default = Template.bind({})
3683
Default.args = {
37-
currentComic: 666,
3884
item: MARTEN_HYDRATED,
3985
useColors: true,
4086
mode: NavElementMode[NavElementMode.Present] as unknown as NavElementMode,
@@ -96,3 +142,8 @@ EditModeMissing.play = ({ canvasElement, args }) => {
96142
userEvent.click(canvas.getByTitle('Add Marten to comic'))
97143
expect(args.onAddItem).toBeCalledWith(MARTEN.id)
98144
}
145+
146+
export const WithRandomButton = Template.bind({ withRandom: true })
147+
WithRandomButton.args = {
148+
...Default.args,
149+
}

0 commit comments

Comments
 (0)