redo episode data loading to use Vuex, fix isFetched to use .loaded (MERGE_EPISODE), implement Promise (.then) for FETCH_EPISODE

This commit is contained in:
Xevion
2020-09-13 23:55:11 -05:00
parent a8a4866554
commit 5ec678ffb0
2 changed files with 74 additions and 84 deletions

View File

@@ -7,13 +7,8 @@
<b-card class="mb-4"> <b-card class="mb-4">
<template v-if="ready"> <template v-if="ready">
<h3>"{{ episode.title }}"</h3> <h3>"{{ episode.title }}"</h3>
<span> <span>{{ episode.description }}</span>
{{ episode.description }} <CharacterList v-if="episode && episode.characters" :characters="episode.characters"></CharacterList>
</span>
<CharacterList
v-if="episode && episode.characters"
:characters="episode.characters"
></CharacterList>
</template> </template>
<template v-else> <template v-else>
<Skeleton style="width: 30%;"></Skeleton> <Skeleton style="width: 30%;"></Skeleton>
@@ -22,25 +17,15 @@
<Skeleton style="width: 69%; height: 40%;"></Skeleton> <Skeleton style="width: 69%; height: 40%;"></Skeleton>
</template> </template>
</b-card> </b-card>
<div v-if="episode != null"> <div v-if="ready">
<b-card <b-card v-for="(scene, sceneIndex) in episode.scenes" :key="`scene-${sceneIndex}`" class="mb-1"
v-for="(scene, sceneIndex) in episode.scenes" body-class="p-0">
:key="`scene-${sceneIndex}`"
class="mb-1"
body-class="p-0"
>
<b-card-text class="my-2"> <b-card-text class="my-2">
<QuoteList <QuoteList :quotes="scene.quotes" :sceneIndex="sceneIndex"></QuoteList>
:quotes="scene.quotes" <span v-if="scene.deleted" class="mt-n2 mb-4 text-muted deleted-scene pl-2"
:sceneIndex="sceneIndex" :footer="`Deleted Scene ${scene.deleted}`">
></QuoteList> Deleted Scene {{ scene.deleted }}
<span </span>
v-if="scene.deleted"
class="mt-n2 mb-4 text-muted deleted-scene pl-2"
:footer="`Deleted Scene ${scene.deleted}`"
>
Deleted Scene {{ scene.deleted }}
</span>
</b-card-text> </b-card-text>
</b-card> </b-card>
</div> </div>
@@ -51,6 +36,7 @@
.breadcrumb-skeleton { .breadcrumb-skeleton {
background-color: $grey-3; background-color: $grey-3;
height: 48px; height: 48px;
& > .card-body { & > .card-body {
padding: 0 0 0 1em; padding: 0 0 0 1em;
display: flex; display: flex;
@@ -72,10 +58,10 @@
</style> </style>
<script> <script>
import axios from "axios";
import QuoteList from "./QuoteList.vue"; import QuoteList from "./QuoteList.vue";
import CharacterList from "./CharacterList.vue"; import CharacterList from "./CharacterList.vue";
import Skeleton from './Skeleton.vue'; import Skeleton from './Skeleton.vue';
import {types} from "@/mutation_types";
export default { export default {
name: "Episode", name: "Episode",
@@ -84,47 +70,45 @@ export default {
CharacterList, CharacterList,
Skeleton, Skeleton,
}, },
data() { created() {
return { this.fetch();
episode: null, },
}; watch: {
$route() {
this.$nextTick(() => {
this.fetch();
// this.$store.dispatch(types.FETCH_EPISODE, {season: this.params.season, episode: this.params.episode})
})
},
}, },
methods: { methods: {
getEpisode() { fetch() {
const path = `${process.env.VUE_APP_API_URL}/api/episode/\ // Fetch the episode, then scroll - already fetched episode should scroll immediately
${this.$route.params.season}/${this.$route.params.episode}/`; this.$store.dispatch(types.FETCH_EPISODE, {season: this.params.season, episode: this.params.episode})
axios .then(() => {
.get(path) // Force update, as for some reason it doesn't update naturally. I hate it too.
.then((res) => { this.$forceUpdate()
this.episode = res.data;
// Scroll // Scroll down to quote
if (this.$route.hash) { if (this.$route.hash) {
this.$nextTick(() => { this.$nextTick(() => {
const section = document.getElementById(this.$route.hash.substring(1)); const section = document.getElementById(this.$route.hash.substring(1));
this.$scrollTo(section, 500, {easing: "ease-in"}); this.$scrollTo(section, 500, {easing: "ease-in"});
}); });
} }
})
.catch((error) => {
// eslint-disable-next-line no-console
console.error(error);
}); });
}, }
},
created() {
this.getEpisode();
},
watch: {
$route() {
this.episode = null;
this.$nextTick(() => {
this.getEpisode();
})
},
}, },
computed: { computed: {
episode() {
return this.$store.getters.getEpisode(this.params.season, this.params.episode)
// return this.$store.state.quoteData[this.params.season - 1].episodes[this.params.episode - 1];
},
params() {
return this.$route.params
},
ready() { ready() {
return this.episode !== null return this.$store.getters.isFetched(this.params.season, this.params.episode)
}, },
breadcrumbs() { breadcrumbs() {
return [ return [

View File

@@ -10,9 +10,9 @@ const episodeCount = [6, 22, 23, 14, 26, 24, 24, 24, 23];
const baseData = Array.from({length: 9}, (x, season) => { const baseData = Array.from({length: 9}, (x, season) => {
// Array of null values representing each episode // Array of null values representing each episode
const episodeData = Array.from({length: episodeCount[season]}, (x, episode) => { const episodeData = Array.from({length: episodeCount[season]}, (x, episode) => {
return { episode_id: episode + 1, loaded: false } return {episode_id: episode + 1, loaded: false}
}) })
return {season_id: season + 1, episodes: episodeData }; return {season_id: season + 1, episodes: episodeData};
}) })
export default new Vuex.Store({ export default new Vuex.Store({
@@ -30,43 +30,48 @@ export default new Vuex.Store({
const s = payload.season - 1; const s = payload.season - 1;
const e = payload.episode - 1; const e = payload.episode - 1;
state.quoteData[s].episodes[e] = Object.assign(state.quoteData[s].episodes[e], payload.episodeData); state.quoteData[s].episodes[e] = Object.assign(state.quoteData[s].episodes[e], payload.episodeData);
if (payload.episodeData.scenes !== null)
state.quoteData[s].episodes[e].loaded = true;
}, },
[types.SET_PRELOADED](state, status) { [types.SET_PRELOADED](state, status) {
state.preloaded = status; state.preloaded = status;
}, }
}, },
actions: { actions: {
// Perform async API call to fetch specific Episode data // Perform async API call to fetch specific Episode data
[types.FETCH_EPISODE]({commit}, season, episode) { [types.FETCH_EPISODE]({commit}, payload) {
const path = `${process.env.VUE_APP_API_URL}/api/episode/${season}/${episode}/`; return new Promise((resolve, reject) => {
const path = `${process.env.VUE_APP_API_URL}/api/episode/${payload.season}/${payload.episode}/`;
axios.get(path) axios.get(path)
.then((res) => { .then((res) => {
// Push episode data // Push episode data
commit(types.SET_EPISODE, {season: season, episode: episode, data: res.data}) commit(types.MERGE_EPISODE, {
}) season: payload.season,
.catch((error) => { episode: payload.episode,
// eslint-disable-next-line no-console episodeData: res.data
console.error(error); })
}); resolve()
})
.catch((error) => {
// eslint-disable-next-line no-console
console.error(error);
reject()
});
})
}, },
[types.PRELOAD]({commit}) { [types.PRELOAD]({commit}) {
const path = `${process.env.VUE_APP_API_URL}/api/episodes/`; const path = `${process.env.VUE_APP_API_URL}/api/episodes/`;
console.log('preload axios') console.log('preload axios')
axios.get(path) axios.get(path)
.then((res) => { .then((res) => {
for (const season of res.data) { for (const season of res.data)
for (const episode of season.episodes) { for (const episode of season.episodes) {
// Create payload and commit for each episode // Create payload and commit for each episode
commit( commit(types.MERGE_EPISODE, {
types.MERGE_EPISODE, season: season.season_id,
{ episode: episode.episode_id,
season: season.season_id, episodeData: episode
episode: episode.episode_id, })
episodeData: episode
}
)
}
} }
commit(types.SET_PRELOADED, true); commit(types.SET_PRELOADED, true);
@@ -80,7 +85,8 @@ export default new Vuex.Store({
getters: { getters: {
// Check whether a episode has been fetched yet // Check whether a episode has been fetched yet
isFetched: (state) => (season, episode) => { isFetched: (state) => (season, episode) => {
return state.quoteData[season - 1].episodes[episode] !== null; const ep = state.quoteData[season - 1].episodes[episode - 1];
return ep !== null && ep.loaded;
}, },
// Get the number of episodes present for a given season // Get the number of episodes present for a given season
getEpisodeCount: (state) => (season) => { getEpisodeCount: (state) => (season) => {
@@ -88,9 +94,9 @@ export default new Vuex.Store({
}, },
// return Episode data if present // return Episode data if present
getEpisode: (state, getters) => (season, episode) => { getEpisode: (state, getters) => (season, episode) => {
if (getters.isFetched(season, episode)) if (getters.isFetched(season, episode)) {
return state.quoteData[season] return state.quoteData[season - 1].episodes[episode - 1];
else } else
return null return null
}, },
// return true if a specific episode is valid // return true if a specific episode is valid