mirror of
https://github.com/Xevion/the-office.git
synced 2025-12-10 18:08:54 -06:00
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:
@@ -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 [
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user