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">
<template v-if="ready">
<h3>"{{ episode.title }}"</h3>
<span>
{{ episode.description }}
</span>
<CharacterList
v-if="episode && episode.characters"
:characters="episode.characters"
></CharacterList>
<span>{{ episode.description }}</span>
<CharacterList v-if="episode && episode.characters" :characters="episode.characters"></CharacterList>
</template>
<template v-else>
<Skeleton style="width: 30%;"></Skeleton>
@@ -22,25 +17,15 @@
<Skeleton style="width: 69%; height: 40%;"></Skeleton>
</template>
</b-card>
<div v-if="episode != null">
<b-card
v-for="(scene, sceneIndex) in episode.scenes"
:key="`scene-${sceneIndex}`"
class="mb-1"
body-class="p-0"
>
<div v-if="ready">
<b-card v-for="(scene, sceneIndex) in episode.scenes" :key="`scene-${sceneIndex}`" class="mb-1"
body-class="p-0">
<b-card-text class="my-2">
<QuoteList
:quotes="scene.quotes"
:sceneIndex="sceneIndex"
></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 }}
</span>
<QuoteList :quotes="scene.quotes" :sceneIndex="sceneIndex"></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 }}
</span>
</b-card-text>
</b-card>
</div>
@@ -51,6 +36,7 @@
.breadcrumb-skeleton {
background-color: $grey-3;
height: 48px;
& > .card-body {
padding: 0 0 0 1em;
display: flex;
@@ -72,10 +58,10 @@
</style>
<script>
import axios from "axios";
import QuoteList from "./QuoteList.vue";
import CharacterList from "./CharacterList.vue";
import Skeleton from './Skeleton.vue';
import {types} from "@/mutation_types";
export default {
name: "Episode",
@@ -84,47 +70,45 @@ export default {
CharacterList,
Skeleton,
},
data() {
return {
episode: null,
};
created() {
this.fetch();
},
watch: {
$route() {
this.$nextTick(() => {
this.fetch();
// this.$store.dispatch(types.FETCH_EPISODE, {season: this.params.season, episode: this.params.episode})
})
},
},
methods: {
getEpisode() {
const path = `${process.env.VUE_APP_API_URL}/api/episode/\
${this.$route.params.season}/${this.$route.params.episode}/`;
axios
.get(path)
.then((res) => {
this.episode = res.data;
// Scroll
fetch() {
// Fetch the episode, then scroll - already fetched episode should scroll immediately
this.$store.dispatch(types.FETCH_EPISODE, {season: this.params.season, episode: this.params.episode})
.then(() => {
// Force update, as for some reason it doesn't update naturally. I hate it too.
this.$forceUpdate()
// Scroll down to quote
if (this.$route.hash) {
this.$nextTick(() => {
const section = document.getElementById(this.$route.hash.substring(1));
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: {
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() {
return this.episode !== null
return this.$store.getters.isFetched(this.params.season, this.params.episode)
},
breadcrumbs() {
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) => {
// Array of null values representing each 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({
@@ -30,43 +30,48 @@ export default new Vuex.Store({
const s = payload.season - 1;
const e = payload.episode - 1;
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) {
state.preloaded = status;
},
}
},
actions: {
// Perform async API call to fetch specific Episode data
[types.FETCH_EPISODE]({commit}, season, episode) {
const path = `${process.env.VUE_APP_API_URL}/api/episode/${season}/${episode}/`;
axios.get(path)
.then((res) => {
// Push episode data
commit(types.SET_EPISODE, {season: season, episode: episode, data: res.data})
})
.catch((error) => {
// eslint-disable-next-line no-console
console.error(error);
});
[types.FETCH_EPISODE]({commit}, payload) {
return new Promise((resolve, reject) => {
const path = `${process.env.VUE_APP_API_URL}/api/episode/${payload.season}/${payload.episode}/`;
axios.get(path)
.then((res) => {
// Push episode data
commit(types.MERGE_EPISODE, {
season: payload.season,
episode: payload.episode,
episodeData: res.data
})
resolve()
})
.catch((error) => {
// eslint-disable-next-line no-console
console.error(error);
reject()
});
})
},
[types.PRELOAD]({commit}) {
const path = `${process.env.VUE_APP_API_URL}/api/episodes/`;
console.log('preload axios')
axios.get(path)
.then((res) => {
for (const season of res.data) {
for (const season of res.data)
for (const episode of season.episodes) {
// Create payload and commit for each episode
commit(
types.MERGE_EPISODE,
{
season: season.season_id,
episode: episode.episode_id,
episodeData: episode
}
)
}
commit(types.MERGE_EPISODE, {
season: season.season_id,
episode: episode.episode_id,
episodeData: episode
})
}
commit(types.SET_PRELOADED, true);
@@ -80,7 +85,8 @@ export default new Vuex.Store({
getters: {
// Check whether a episode has been fetched yet
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
getEpisodeCount: (state) => (season) => {
@@ -88,9 +94,9 @@ export default new Vuex.Store({
},
// return Episode data if present
getEpisode: (state, getters) => (season, episode) => {
if (getters.isFetched(season, episode))
return state.quoteData[season]
else
if (getters.isFetched(season, episode)) {
return state.quoteData[season - 1].episodes[episode - 1];
} else
return null
},
// return true if a specific episode is valid