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,23 +17,13 @@
<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>
<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 }} Deleted Scene {{ scene.deleted }}
</span> </span>
</b-card-text> </b-card-text>
@@ -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

@@ -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,
episode: payload.episode,
episodeData: res.data
})
resolve()
}) })
.catch((error) => { .catch((error) => {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
console.error(error); 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, season: season.season_id,
episode: episode.episode_id, episode: episode.episode_id,
episodeData: episode 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